/* ****************************************************************************
*
* 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.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using System.Reflection;
using System.IO;
using System.Collections.ObjectModel;
namespace Microsoft.Scripting.Hosting {
///
/// Stores information needed to setup a ScriptRuntime
///
[Serializable]
public sealed class ScriptRuntimeSetup {
// host specification:
private Type _hostType;
private IList _hostArguments;
// languages available in the runtime:
private IList _languageSetups;
// DLR options:
private bool _debugMode;
private bool _privateBinding;
// common language options:
private IDictionary _options;
// true if the ScriptRuntimeSetup is no longer mutable because it's been
// used to start a ScriptRuntime
private bool _frozen;
public ScriptRuntimeSetup() {
_languageSetups = new List();
_options = new Dictionary();
_hostType = typeof(ScriptHost);
_hostArguments = ArrayUtils.EmptyObjects;
}
///
/// The list of language setup information for languages to load into
/// the runtime
///
public IList LanguageSetups {
get { return _languageSetups; }
}
///
/// Indicates that the script runtime is in debug mode.
/// This means:
///
/// 1) Symbols are emitted for debuggable methods (methods associated with SourceUnit).
/// 2) Debuggable methods are emitted to non-collectable types (this is due to CLR limitations on dynamic method debugging).
/// 3) JIT optimization is disabled for all methods
/// 4) Languages may disable optimizations based on this value.
///
public bool DebugMode {
get { return _debugMode; }
set {
CheckFrozen();
_debugMode = value;
}
}
///
/// Ignore CLR visibility checks
///
public bool PrivateBinding {
get { return _privateBinding; }
set {
CheckFrozen();
_privateBinding = value;
}
}
///
/// Can be any derived class of ScriptHost. When set, it allows the
/// host to override certain methods to control behavior of the runtime
///
public Type HostType {
get { return _hostType; }
set {
ContractUtils.RequiresNotNull(value, "value");
ContractUtils.Requires(typeof(ScriptHost).IsAssignableFrom(value), "value", "Must be ScriptHost or a derived type of ScriptHost");
CheckFrozen();
_hostType = value;
}
}
///
/// Option names are case-sensitive.
///
public IDictionary Options {
get { return _options; }
}
///
/// Arguments passed to the host type when it is constructed
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public IList HostArguments {
get {
return _hostArguments;
}
set {
ContractUtils.RequiresNotNull(value, "value");
CheckFrozen();
_hostArguments = value;
}
}
internal DlrConfiguration ToConfiguration() {
ContractUtils.Requires(_languageSetups.Count > 0, "ScriptRuntimeSetup must have at least one LanguageSetup");
// prepare
ReadOnlyCollection setups = new ReadOnlyCollection(ArrayUtils.MakeArray(_languageSetups));
var hostArguments = new ReadOnlyCollection(ArrayUtils.MakeArray(_hostArguments));
var options = new ReadOnlyDictionary(new Dictionary(_options));
var config = new DlrConfiguration(_debugMode, _privateBinding, options);
// validate
foreach (var language in setups) {
config.AddLanguage(
language.TypeName,
language.DisplayName,
language.Names,
language.FileExtensions,
language.Options
);
}
// commit
_languageSetups = setups;
_options = options;
_hostArguments = hostArguments;
Freeze(setups);
return config;
}
private void Freeze(ReadOnlyCollection setups) {
foreach (var language in setups) {
language.Freeze();
}
_frozen = true;
}
private void CheckFrozen() {
if (_frozen) {
throw new InvalidOperationException("Cannot modify ScriptRuntimeSetup after it has been used to create a ScriptRuntime");
}
}
///
/// Reads setup from .NET configuration system (.config files).
/// If there is no configuration available returns an empty setup.
///
public static ScriptRuntimeSetup ReadConfiguration() {
#if SILVERLIGHT
return new ScriptRuntimeSetup();
#else
var setup = new ScriptRuntimeSetup();
Configuration.Section.LoadRuntimeSetup(setup, null);
return setup;
#endif
}
#if !SILVERLIGHT
///
/// Reads setup from a specified XML stream.
///
public static ScriptRuntimeSetup ReadConfiguration(Stream configFileStream) {
ContractUtils.RequiresNotNull(configFileStream, "configFileStream");
var setup = new ScriptRuntimeSetup();
Configuration.Section.LoadRuntimeSetup(setup, configFileStream);
return setup;
}
///
/// Reads setup from a specified XML file.
///
public static ScriptRuntimeSetup ReadConfiguration(string configFilePath) {
ContractUtils.RequiresNotNull(configFilePath, "configFilePath");
using (var stream = File.OpenRead(configFilePath)) {
return ReadConfiguration(stream);
}
}
#endif
}
}