From 2e2addebf7b8a4ec73b6d451fea6ef8095012ceb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 13 Jun 2017 12:40:25 +0200 Subject: [PATCH] #28538 Remove existing workspace configuration service. Update tests. --- src/vs/workbench/electron-browser/main.ts | 12 +- .../workbench/electron-browser/workbench.ts | 2 +- .../node/configuration.ts} | 4 +- .../node/configurationService.ts | 357 ------------------ .../node/nullConfigurationService.ts | 44 --- ...nService.test.ts => configuration.test.ts} | 2 +- .../node/configurationEditingService.test.ts | 6 +- 7 files changed, 13 insertions(+), 414 deletions(-) rename src/vs/workbench/services/{workspace/node/workspace.ts => configuration/node/configuration.ts} (98%) delete mode 100644 src/vs/workbench/services/configuration/node/configurationService.ts delete mode 100644 src/vs/workbench/services/configuration/node/nullConfigurationService.ts rename src/vs/workbench/services/configuration/test/node/{configurationService.test.ts => configuration.test.ts} (99%) diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 26d301a6ded..cf9c5e45db7 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -19,7 +19,7 @@ import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); import { IResourceInput } from 'vs/platform/editor/common/editor'; import { Workspace } from 'vs/platform/workspace/common/workspace'; -import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; +import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configuration'; import { realpath, stat } from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import path = require('path'); @@ -129,12 +129,12 @@ function getWorkspace(workspacePath: string): TPromise { function openWorkbench(configuration: IWindowConfiguration, workspace: Workspace, options: IOptions): TPromise { const environmentService = new EnvironmentService(configuration, configuration.execPath); - const workspaceService = new WorkspaceService(environmentService, workspace); - const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, !workspaceService.hasWorkspace()); + const workspaceConfigurationService = new WorkspaceConfigurationService(environmentService, workspace); + const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, !workspaceConfigurationService.hasWorkspace()); // Since the configuration service is one of the core services that is used in so many places, we initialize it // right before startup of the workbench shell to have its data ready for consumers - return workspaceService.initialize().then(() => { + return workspaceConfigurationService.initialize().then(() => { timerService.beforeDOMContentLoaded = Date.now(); return domContentLoaded().then(() => { @@ -143,8 +143,8 @@ function openWorkbench(configuration: IWindowConfiguration, workspace: Workspace // Open Shell timerService.beforeWorkbenchOpen = Date.now(); const shell = new WorkbenchShell(document.body, { - contextService: workspaceService, - configurationService: workspaceService, + contextService: workspaceConfigurationService, + configurationService: workspaceConfigurationService, environmentService, timerService }, configuration, options); diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index d5b3f3bd621..a8afe425a03 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -47,7 +47,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService'; import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configurationService'; +import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configuration'; import { IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; diff --git a/src/vs/workbench/services/workspace/node/workspace.ts b/src/vs/workbench/services/configuration/node/configuration.ts similarity index 98% rename from src/vs/workbench/services/workspace/node/workspace.ts rename to src/vs/workbench/services/configuration/node/configuration.ts index 85f411d715c..4f0baaf5ba0 100644 --- a/src/vs/workbench/services/workspace/node/workspace.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -44,7 +44,7 @@ interface IWorkspaceConfiguration { type IWorkspaceFoldersConfiguration = { [rootFolder: string]: { folders: string[]; } }; -export class WorkspaceService extends Disposable implements IWorkspaceContextService, IWorkspaceConfigurationService { +export class WorkspaceConfigurationService extends Disposable implements IWorkspaceContextService, IWorkspaceConfigurationService { private static RELOAD_CONFIGURATION_DELAY = 50; @@ -83,7 +83,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceContextSer source: ConfigurationSource.Workspace, sourceConfig: config.workspace })) - .done(null, errors.onUnexpectedError), WorkspaceService.RELOAD_CONFIGURATION_DELAY)); + .done(null, errors.onUnexpectedError), WorkspaceConfigurationService.RELOAD_CONFIGURATION_DELAY)); this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); this._register(this.onDidUpdateConfiguration(e => this.resolveAdditionalFolders(true))); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts deleted file mode 100644 index 7001b1bb00d..00000000000 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ /dev/null @@ -1,357 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { TPromise } from 'vs/base/common/winjs.base'; -import uri from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import extfs = require('vs/base/node/extfs'); -import objects = require('vs/base/common/objects'); -import { RunOnceScheduler } from 'vs/base/common/async'; -import collections = require('vs/base/common/collections'); -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { readFile } from 'vs/base/node/pfs'; -import errors = require('vs/base/common/errors'); -import { ScopedConfigModel, WorkspaceConfigModel, WorkspaceSettingsConfigModel } from 'vs/workbench/services/configuration/common/configurationModels'; -import { IConfigurationServiceEvent, ConfigurationSource, getConfigurationValue, IConfigModel, IConfigurationOptions } from 'vs/platform/configuration/common/configuration'; -import { ConfigModel } from 'vs/platform/configuration/common/model'; -import { ConfigurationService as BaseConfigurationService } from 'vs/platform/configuration/node/configurationService'; -import { IWorkspaceConfigurationValues, IWorkspaceConfigurationService, IWorkspaceConfigurationValue, WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME, WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH } from 'vs/workbench/services/configuration/common/configuration'; -import { FileChangeType, FileChangesEvent, isEqual } from 'vs/platform/files/common/files'; -import Event, { Emitter } from 'vs/base/common/event'; -import { Workspace } from "vs/platform/workspace/common/workspace"; - -interface IStat { - resource: uri; - isDirectory?: boolean; - children?: { resource: uri; }[]; -} - -interface IContent { - resource: uri; - value: string; -} - -interface IWorkspaceConfiguration { - workspace: T; - consolidated: any; -} - -/** - * Wraps around the basic configuration service and adds knowledge about workspace settings. - */ -export class WorkspaceConfigurationService extends Disposable implements IWorkspaceConfigurationService, IDisposable { - - public _serviceBrand: any; - - private static RELOAD_CONFIGURATION_DELAY = 50; - - private _onDidUpdateConfiguration: Emitter; - private baseConfigurationService: BaseConfigurationService; - - private cachedConfig: ConfigModel; - private cachedWorkspaceConfig: WorkspaceConfigModel; - - private bulkFetchFromWorkspacePromise: TPromise; - private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise> }; - private reloadConfigurationScheduler: RunOnceScheduler; - - constructor( - private environmentService: IEnvironmentService, - private workspace?: Workspace, - private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME - ) { - super(); - this.workspaceFilePathToConfiguration = Object.create(null); - - this.cachedConfig = new ConfigModel(null); - this.cachedWorkspaceConfig = new WorkspaceConfigModel(new WorkspaceSettingsConfigModel(null), []); - - this._onDidUpdateConfiguration = this._register(new Emitter()); - - this.baseConfigurationService = this._register(new BaseConfigurationService(environmentService)); - - this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.doLoadConfiguration() - .then(config => this._onDidUpdateConfiguration.fire({ - config: config.consolidated, - source: ConfigurationSource.Workspace, - sourceConfig: config.workspace - })) - .done(null, errors.onUnexpectedError), WorkspaceConfigurationService.RELOAD_CONFIGURATION_DELAY)); - - this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); - } - - get onDidUpdateConfiguration(): Event { - return this._onDidUpdateConfiguration.event; - } - - private onBaseConfigurationChanged(event: IConfigurationServiceEvent): void { - if (event.source === ConfigurationSource.Default) { - this.cachedWorkspaceConfig.update(); - } - - // update cached config when base config changes - const configModel = >this.baseConfigurationService.getCache().consolidated // global/default values (do NOT modify) - .merge(this.cachedWorkspaceConfig); // workspace configured values - - // emit this as update to listeners if changed - if (!objects.equals(this.cachedConfig.contents, configModel.contents)) { - this.cachedConfig = configModel; - this._onDidUpdateConfiguration.fire({ - config: this.cachedConfig.contents, - source: event.source, - sourceConfig: event.sourceConfig - }); - } - } - - public initialize(): TPromise { - return this.doLoadConfiguration().then(() => null); - } - - public getConfiguration(section?: string): C - public getConfiguration(options?: IConfigurationOptions): C - public getConfiguration(arg?: any): C { - const options = this.toOptions(arg); - const configModel = options.overrideIdentifier ? this.cachedConfig.configWithOverrides(options.overrideIdentifier) : this.cachedConfig; - return options.section ? configModel.getContentsFor(options.section) : configModel.contents; - } - - public lookup(key: string, overrideIdentifier?: string): IWorkspaceConfigurationValue { - const configurationValue = this.baseConfigurationService.lookup(key, overrideIdentifier); - return { - default: configurationValue.default, - user: configurationValue.user, - workspace: objects.clone(getConfigurationValue(overrideIdentifier ? this.cachedWorkspaceConfig.configWithOverrides(overrideIdentifier).contents : this.cachedWorkspaceConfig.contents, key)), - value: objects.clone(getConfigurationValue(overrideIdentifier ? this.cachedConfig.configWithOverrides(overrideIdentifier).contents : this.cachedConfig.contents, key)) - }; - } - - public keys() { - const keys = this.baseConfigurationService.keys(); - - return { - default: keys.default, - user: keys.user, - workspace: this.cachedWorkspaceConfig.keys - }; - } - - public values(): IWorkspaceConfigurationValues { - const result: IWorkspaceConfigurationValues = Object.create(null); - const keyset = this.keys(); - const keys = [...keyset.workspace, ...keyset.user, ...keyset.default].sort(); - - let lastKey: string; - for (const key of keys) { - if (key !== lastKey) { - lastKey = key; - result[key] = this.lookup(key); - } - } - - return result; - } - - public reloadConfiguration(section?: string): TPromise { - - // Reset caches to ensure we are hitting the disk - this.bulkFetchFromWorkspacePromise = null; - this.workspaceFilePathToConfiguration = Object.create(null); - - // Load configuration - return this.baseConfigurationService.reloadConfiguration().then(() => { - const current = this.cachedConfig; - return this.doLoadConfiguration().then(configuration => { - // emit this as update to listeners if changed - if (!objects.equals(current, this.cachedConfig)) { - this._onDidUpdateConfiguration.fire({ - config: configuration.consolidated, - source: ConfigurationSource.Workspace, - sourceConfig: configuration.workspace - }); - } - return section ? configuration.consolidated[section] : configuration.consolidated; - }); - }); - } - - private toOptions(arg: any): IConfigurationOptions { - if (typeof arg === 'string') { - return { section: arg }; - } - if (typeof arg === 'object') { - return arg; - } - return {}; - } - - private doLoadConfiguration(): TPromise> { - - // Load workspace locals - return this.loadWorkspaceConfigFiles().then(workspaceConfigFiles => { - - // Consolidate (support *.json files in the workspace settings folder) - const workspaceSettingsConfig = >workspaceConfigFiles[WORKSPACE_CONFIG_DEFAULT_PATH] || new WorkspaceSettingsConfigModel(null); - const otherConfigModels = Object.keys(workspaceConfigFiles).filter(key => key !== WORKSPACE_CONFIG_DEFAULT_PATH).map(key => >workspaceConfigFiles[key]); - this.cachedWorkspaceConfig = new WorkspaceConfigModel(workspaceSettingsConfig, otherConfigModels); - - // Override base (global < user) with workspace locals (global < user < workspace) - this.cachedConfig = >this.baseConfigurationService.getCache().consolidated // global/default values (do NOT modify) - .merge(this.cachedWorkspaceConfig); // workspace configured values - - return { - consolidated: this.cachedConfig.contents, - workspace: this.cachedWorkspaceConfig.contents - }; - }); - } - - private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: IConfigModel }> { - - // Return early if we don't have a workspace - if (!this.workspace) { - return TPromise.as(Object.create(null)); - } - - // once: when invoked for the first time we fetch json files that contribute settings - if (!this.bulkFetchFromWorkspacePromise) { - this.bulkFetchFromWorkspacePromise = resolveStat(this.workspace.toResource(this.workspaceSettingsRootFolder)).then(stat => { - if (!stat.isDirectory) { - return TPromise.as([]); - } - - return resolveContents(stat.children.filter(stat => { - const isJson = paths.extname(stat.resource.fsPath) === '.json'; - if (!isJson) { - return false; // only JSON files - } - - return this.isWorkspaceConfigurationFile(this.workspace.toWorkspaceRelativePath(stat.resource)); // only workspace config files - }).map(stat => stat.resource)); - }, err => [] /* never fail this call */) - .then((contents: IContent[]) => { - contents.forEach(content => this.workspaceFilePathToConfiguration[this.workspace.toWorkspaceRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content))); - }, errors.onUnexpectedError); - } - - // on change: join on *all* configuration file promises so that we can merge them into a single configuration object. this - // happens whenever a config file changes, is deleted, or added - return this.bulkFetchFromWorkspacePromise.then(() => TPromise.join(this.workspaceFilePathToConfiguration)); - } - - public handleWorkspaceFileEvents(event: FileChangesEvent): void { - if (!this.workspace) { - return; // only enabled when we have a known workspace - } - - const events = event.changes; - let affectedByChanges = false; - - // Find changes that affect workspace configuration files - for (let i = 0, len = events.length; i < len; i++) { - const resource = events[i].resource; - const isJson = paths.extname(resource.fsPath) === '.json'; - const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && isEqual(paths.basename(resource.fsPath), this.workspaceSettingsRootFolder)); - if (!isJson && !isDeletedSettingsFolder) { - continue; // only JSON files or the actual settings folder - } - - const workspacePath = this.workspace.toWorkspaceRelativePath(resource); - if (!workspacePath) { - continue; // event is not inside workspace - } - - // Handle case where ".vscode" got deleted - if (workspacePath === this.workspaceSettingsRootFolder && events[i].type === FileChangeType.DELETED) { - this.workspaceFilePathToConfiguration = Object.create(null); - affectedByChanges = true; - } - - // only valid workspace config files - if (!this.isWorkspaceConfigurationFile(workspacePath)) { - continue; - } - - // insert 'fetch-promises' for add and update events and - // remove promises for delete events - switch (events[i].type) { - case FileChangeType.DELETED: - affectedByChanges = collections.remove(this.workspaceFilePathToConfiguration, workspacePath); - break; - case FileChangeType.UPDATED: - case FileChangeType.ADDED: - this.workspaceFilePathToConfiguration[workspacePath] = resolveContent(resource).then(content => this.createConfigModel(content), errors.onUnexpectedError); - affectedByChanges = true; - } - } - - // trigger reload of the configuration if we are affected by changes - if (affectedByChanges && !this.reloadConfigurationScheduler.isScheduled()) { - this.reloadConfigurationScheduler.schedule(); - } - } - - private createConfigModel(content: IContent): IConfigModel { - const path = this.workspace.toWorkspaceRelativePath(content.resource); - if (path === WORKSPACE_CONFIG_DEFAULT_PATH) { - return new WorkspaceSettingsConfigModel(content.value, content.resource.toString()); - } else { - const matches = /\/([^\.]*)*\.json/.exec(path); - if (matches && matches[1]) { - return new ScopedConfigModel(content.value, content.resource.toString(), matches[1]); - } - } - - return new ConfigModel(null); - } - - private isWorkspaceConfigurationFile(workspaceRelativePath: string): boolean { - return [WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS.launch, WORKSPACE_STANDALONE_CONFIGURATIONS.tasks].some(p => p === workspaceRelativePath); - } - - public getUnsupportedWorkspaceKeys(): string[] { - return this.cachedWorkspaceConfig.workspaceSettingsConfig.unsupportedKeys; - } -} - -// node.hs helper functions - -function resolveContents(resources: uri[]): TPromise { - const contents: IContent[] = []; - - return TPromise.join(resources.map(resource => { - return resolveContent(resource).then(content => { - contents.push(content); - }); - })).then(() => contents); -} - -function resolveContent(resource: uri): TPromise { - return readFile(resource.fsPath).then(contents => ({ resource, value: contents.toString() })); -} - -function resolveStat(resource: uri): TPromise { - return new TPromise((c, e) => { - extfs.readdir(resource.fsPath, (error, children) => { - if (error) { - if ((error).code === 'ENOTDIR') { - c({ resource }); - } else { - e(error); - } - } else { - c({ - resource, - isDirectory: true, - children: children.map(child => { return { resource: uri.file(paths.join(resource.fsPath, child)) }; }) - }); - } - }); - }); -} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/nullConfigurationService.ts b/src/vs/workbench/services/configuration/node/nullConfigurationService.ts deleted file mode 100644 index c38b5b29b2e..00000000000 --- a/src/vs/workbench/services/configuration/node/nullConfigurationService.ts +++ /dev/null @@ -1,44 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, getConfigurationValue, IConfigurationKeys } from "vs/platform/configuration/common/configuration"; -import Event, { Emitter } from 'vs/base/common/event'; -import { TPromise } from "vs/base/common/winjs.base"; - -export class NullConfigurationService implements IConfigurationService { - - _serviceBrand: any; - - private _onDidUpdateConfiguration = new Emitter(); - public onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; - - private _config: any; - - constructor() { - this._config = Object.create(null); - } - - public getConfiguration(section?: any): T { - return this._config; - } - - public reloadConfiguration(section?: string): TPromise { - return TPromise.as(this.getConfiguration(section)); - } - - public lookup(key: string): IConfigurationValue { - return { - value: getConfigurationValue(this.getConfiguration(), key), - default: getConfigurationValue(this.getConfiguration(), key), - user: getConfigurationValue(this.getConfiguration(), key) - }; - } - - public keys(): IConfigurationKeys { - return { default: [], user: [] }; - } -} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configuration.test.ts similarity index 99% rename from src/vs/workbench/services/configuration/test/node/configurationService.test.ts rename to src/vs/workbench/services/configuration/test/node/configuration.test.ts index c61238061d7..d7de49aba32 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configuration.test.ts @@ -19,7 +19,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import extfs = require('vs/base/node/extfs'); import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configurationService'; +import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configuration'; import URI from 'vs/base/common/uri'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index 7e7eb3de7af..dfba23f324a 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -21,7 +21,7 @@ import extfs = require('vs/base/node/extfs'); import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService } from 'vs/workbench/test/workbenchTestServices'; import uuid = require('vs/base/common/uuid'); import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { WorkspaceService } from 'vs/workbench/services/workspace/node/workspace'; +import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configuration'; import URI from 'vs/base/common/uri'; import { FileService } from 'vs/workbench/services/files/node/fileService'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService'; @@ -116,7 +116,7 @@ suite('ConfigurationEditingService', () => { const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); instantiationService.stub(IEnvironmentService, environmentService); const workspace = noWorkspace ? null : new Workspace(URI.file(workspaceDir)); - const workspaceService = new WorkspaceService(environmentService, workspace); + const workspaceService = new WorkspaceConfigurationService(environmentService, workspace); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); instantiationService.stub(ILifecycleService, new TestLifecycleService()); @@ -150,7 +150,7 @@ suite('ConfigurationEditingService', () => { function clearServices(): void { if (instantiationService) { - const configuraitonService = instantiationService.get(IConfigurationService); + const configuraitonService = instantiationService.get(IConfigurationService); if (configuraitonService) { configuraitonService.dispose(); }