configurationService.ts 5.1 KB
Newer Older
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

J
Johannes Rieken 已提交
7
import { TPromise } from 'vs/base/common/winjs.base';
8
import * as objects from 'vs/base/common/objects';
J
Johannes Rieken 已提交
9 10 11
import { ConfigWatcher } from 'vs/base/node/config';
import { Registry } from 'vs/platform/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
S
Sandeep Somavarapu 已提交
12
import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
13 14
import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, getConfigurationValue, IConfigurationKeys, IConfigModel, IConfigurationOptions } from 'vs/platform/configuration/common/configuration';
import { ConfigModel, DefaultConfigModel } from 'vs/platform/configuration/common/model';
J
Johannes Rieken 已提交
15 16
import Event, { Emitter } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
17

18 19 20 21
export interface ICache<T> {
	defaults: IConfigModel<T>;
	user: IConfigModel<T>;
	consolidated: IConfigModel<any>;
22
}
23

24
export class ConfigurationService<T> extends Disposable implements IConfigurationService, IDisposable {
25 26 27

	_serviceBrand: any;

28
	private cache: ICache<T>;
29
	private userConfigModelWatcher: ConfigWatcher<IConfigModel<T>>;
30

31 32
	private _onDidUpdateConfiguration: Emitter<IConfigurationServiceEvent> = this._register(new Emitter<IConfigurationServiceEvent>());
	public readonly onDidUpdateConfiguration: Event<IConfigurationServiceEvent> = this._onDidUpdateConfiguration.event;
33 34 35 36

	constructor(
		@IEnvironmentService environmentService: IEnvironmentService
	) {
37 38 39 40 41 42 43 44 45 46
		super();

		this.userConfigModelWatcher = new ConfigWatcher(environmentService.appSettingsPath, {
			changeBufferDelay: 300, defaultConfig: new ConfigModel<T>(null, environmentService.appSettingsPath), parse: (content: string, parseErrors: any[]) => {
				const userConfigModel = new ConfigModel<T>(content, environmentService.appSettingsPath);
				parseErrors = [...userConfigModel.errors];
				return userConfigModel;
			}
		});
		this._register(toDisposable(() => this.userConfigModelWatcher.dispose()));
47

B
Benjamin Pasero 已提交
48
		// Listeners
49 50
		this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User)));
		this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidRegisterConfiguration(() => this.onConfigurationChange(ConfigurationSource.Default)));
51 52
	}

53
	private onConfigurationChange(source: ConfigurationSource): void {
54
		this.cache = void 0; // reset our caches
55

56
		const cache = this.getCache();
57

58 59 60
		this._onDidUpdateConfiguration.fire({
			config: this.getConfiguration(),
			source,
61
			sourceConfig: source === ConfigurationSource.Default ? cache.defaults.contents : cache.user.contents
62
		});
63 64
	}

65
	public reloadConfiguration<C>(section?: string): TPromise<C> {
B
Benjamin Pasero 已提交
66
		return new TPromise<C>(c => {
67
			this.userConfigModelWatcher.reload(() => {
68 69
				this.cache = void 0; // reset our caches

B
Benjamin Pasero 已提交
70
				c(this.getConfiguration<C>(section));
71 72 73 74
			});
		});
	}

75 76 77 78
	public getConfiguration<C>(section?: string): C
	public getConfiguration<C>(options?: IConfigurationOptions): C
	public getConfiguration<C>(arg?: any): C {
		const options = this.toOptions(arg);
79
		const cache = this.getCache();
80
		const configModel = options.overrideIdentifier ? cache.consolidated.configWithOverrides<C>(options.overrideIdentifier) : cache.consolidated;
S
Sandeep Somavarapu 已提交
81
		return options.section ? configModel.getContentsFor<C>(options.section) : configModel.contents;
82 83
	}

84
	public lookup<C>(key: string, overrideIdentifier?: string): IConfigurationValue<C> {
85 86
		const cache = this.getCache();

87
		// make sure to clone the configuration so that the receiver does not tamper with the values
B
Benjamin Pasero 已提交
88
		return {
89 90 91
			default: objects.clone(getConfigurationValue<C>(overrideIdentifier ? cache.defaults.configWithOverrides(overrideIdentifier).contents : cache.defaults.contents, key)),
			user: objects.clone(getConfigurationValue<C>(overrideIdentifier ? cache.user.configWithOverrides(overrideIdentifier).contents : cache.user.contents, key)),
			value: objects.clone(getConfigurationValue<C>(overrideIdentifier ? cache.consolidated.configWithOverrides(overrideIdentifier).contents : cache.consolidated.contents, key))
B
Benjamin Pasero 已提交
92 93 94
		};
	}

B
Benjamin Pasero 已提交
95
	public keys(): IConfigurationKeys {
96 97
		const cache = this.getCache();

B
Benjamin Pasero 已提交
98
		return {
99 100
			default: cache.defaults.keys,
			user: cache.user.keys
B
Benjamin Pasero 已提交
101 102 103
		};
	}

104 105 106
	public getCache(): ICache<T> {
		return this.cache || (this.cache = this.consolidateConfigurations());
	}
107

108 109 110 111 112 113 114 115
	private toOptions(arg: any): IConfigurationOptions {
		if (typeof arg === 'string') {
			return { section: arg };
		}
		if (typeof arg === 'object') {
			return arg;
		}
		return {};
116 117
	}

118 119 120 121 122
	private consolidateConfigurations(): ICache<T> {
		const defaults = new DefaultConfigModel<T>();
		const user = this.userConfigModelWatcher.getConfig();
		const consolidated = defaults.merge(user);
		return { defaults, user, consolidated };
123 124
	}
}