/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if !SILVERLIGHT
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Xml;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
namespace Microsoft.Scripting.Hosting.Configuration{
//
// <configSections>
// <section name="microsoft.scripting" type="Microsoft.Scripting.Hosting.Configuration.Section, Microsoft.Scripting" />
// </configSections>
//
// <microsoft.scripting [debugMode="{bool}"]? [privateBinding="{bool}"]?>
// <languages> <!-- BasicMap with key (type): inherits language nodes, overwrites previous nodes (last wins) -->
// <language names="{(semi)colon-separated}" extensions="{(semi)colon-separated-with-optional-dot}" type="{AQTN}" [displayName="{string}"]? />
// </languages>
//
// <options> <!-- AddRemoveClearMap with key (option, [language]?): inherits language nodes, overwrites previous nodes (last wins) -->
// <set option="{string}" value="{string}" [language="{language-name}"]? />
// <clear />
// <remove option="{string}" [language="{language-name}"]? />
// </options>
//
// </microsoft.scripting>
//
public class Section : ConfigurationSection {
public static readonly string SectionName = "microsoft.scripting";
private const string _DebugMode = "debugMode";
private const string _PrivateBinding = "privateBinding";
private const string _Languages = "languages";
private const string _Options = "options";
private static ConfigurationPropertyCollection _Properties = new ConfigurationPropertyCollection() {
new ConfigurationProperty(_DebugMode, typeof(bool?), null),
new ConfigurationProperty(_PrivateBinding, typeof(bool?), null),
new ConfigurationProperty(_Languages, typeof(LanguageElementCollection), null, ConfigurationPropertyOptions.IsDefaultCollection),
new ConfigurationProperty(_Options, typeof(OptionElementCollection), null),
};
protected override ConfigurationPropertyCollection Properties {
get { return _Properties; }
}
public bool? DebugMode {
get { return (bool?)base[_DebugMode]; }
set { base[_DebugMode] = value; }
}
public bool? PrivateBinding {
get { return (bool?)base[_PrivateBinding]; }
set { base[_PrivateBinding] = value; }
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public IEnumerable<LanguageElement> GetLanguages() {
var languages = this[_Languages] as LanguageElementCollection;
if (languages == null) {
yield break;
}
foreach (var languageConfig in languages) {
yield return (LanguageElement)languageConfig;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public IEnumerable<OptionElement> GetOptions() {
var options = this[_Options] as OptionElementCollection;
if (options == null) {
yield break;
}
foreach (var option in options) {
yield return (OptionElement)option;
}
}
private static Section LoadFromFile(Stream configFileStream) {
var result = new Section();
using (var reader = XmlReader.Create(configFileStream)) {
if (reader.ReadToDescendant("configuration") && reader.ReadToDescendant(SectionName)) {
result.DeserializeElement(reader, false);
} else {
return null;
}
}
return result;
}
internal static void LoadRuntimeSetup(ScriptRuntimeSetup setup, Stream configFileStream) {
Section config;
if (configFileStream != null) {
config = LoadFromFile(configFileStream);
} else {
config = System.Configuration.ConfigurationManager.GetSection(Section.SectionName) as Section;
}
if (config == null) {
return;
}
if (config.DebugMode.HasValue) {
setup.DebugMode = config.DebugMode.Value;
}
if (config.PrivateBinding.HasValue) {
setup.PrivateBinding = config.PrivateBinding.Value;
}
foreach (var languageConfig in config.GetLanguages()) {
var provider = languageConfig.Type;
var names = languageConfig.GetNamesArray();
var extensions = languageConfig.GetExtensionsArray();
var displayName = languageConfig.DisplayName ?? ((names.Length > 0) ? names[0] : languageConfig.Type);
// Honor the latest-wins behavior of the <languages> tag for options that were already included in the setup object;
// Keep the options though.
bool found = false;
foreach (var language in setup.LanguageSetups) {
if (language.TypeName == provider) {
language.Names.Clear();
foreach (string name in names) {
language.Names.Add(name);
}
language.FileExtensions.Clear();
foreach (string extension in extensions) {
language.FileExtensions.Add(extension);
}
language.DisplayName = displayName;
found = true;
break;
}
}
if (!found) {
setup.LanguageSetups.Add(new LanguageSetup(provider, displayName, names, extensions));
}
}
foreach (var option in config.GetOptions()) {
if (String.IsNullOrEmpty(option.Language)) {
// common option:
setup.Options[option.Name] = option.Value;
} else {
// language specific option:
bool found = false;
foreach (var language in setup.LanguageSetups) {
if (language.Names.Any(s => DlrConfiguration.LanguageNameComparer.Equals(s, option.Language))) {
language.Options[option.Name] = option.Value;
found = true;
break;
}
}
if (!found) {
throw new ConfigurationErrorsException(string.Format("Unknown language name: '{0}'", option.Language));
}
}
}
}
}
}
#endif
|