From e4ecb3850793c6b384a755ccd84a550de306819f Mon Sep 17 00:00:00 2001 From: eeichinger Date: Wed, 13 May 2009 16:16:05 +0000 Subject: [PATCH] fixed SPRNET-1204: added Server Component support --- .../Factory/Config/ConfigurationReader.cs | 778 ++++++++++-------- .../Spring.Core/Spring.Core.2008.csproj | 1 + .../Spring.Core/Util/ConfigurationUtils.cs | 61 +- .../Util/IChainableConfigSystem.cs | 39 + .../EnterpriseServicesExporter.cs | 2 +- .../ExeConfigurationSystem.cs | 156 ++++ .../ServicedComponentHelper.cs | 68 +- .../Spring.Services.2008.csproj | 2 + .../Config/ConfigurationReaderTests.cs | 225 +++-- .../Spring.Core.Tests/TestResourceLoader.cs | 42 + .../ExeConfigurationSystemTests.config | 26 + .../ExeConfigurationSystemTests.cs | 45 + .../ServicedComponentExporterTests.cs | 5 +- ...terTests.TestServicedComponents.dll.config | 17 + ...terTests.TestServicedComponents.exe.config | 47 ++ ...tServicedComponents.exe.spring-context.xml | 6 - .../Spring.Services.Tests.2008.csproj | 19 +- 17 files changed, 1109 insertions(+), 430 deletions(-) create mode 100644 src/Spring/Spring.Core/Util/IChainableConfigSystem.cs create mode 100644 src/Spring/Spring.Services/EnterpriseServices/ExeConfigurationSystem.cs create mode 100644 test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.config create mode 100644 test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.cs create mode 100644 test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.dll.config create mode 100644 test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.config delete mode 100644 test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.spring-context.xml diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/ConfigurationReader.cs b/src/Spring/Spring.Core/Objects/Factory/Config/ConfigurationReader.cs index e7c74623..5d20f88e 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/ConfigurationReader.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/ConfigurationReader.cs @@ -1,5 +1,5 @@ -#region License - +#region License + /* * Copyright © 2002-2005 the original author or authors. * @@ -14,333 +14,449 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Collections.Specialized; -using System.Configuration; -using System.IO; -using System.Xml; - -using Common.Logging; -using Spring.Core; -using Spring.Core.IO; -using Spring.Core.TypeResolution; -using Spring.Util; - -#endregion - -namespace Spring.Objects.Factory.Config -{ - /// - /// Various utility methods for .NET style .config files. - /// - /// - ///

- /// Currently supports reading custom configuration sections and returning them as - /// objects. - ///

- ///
- /// Simon White - /// Mark Pollack - public sealed class ConfigurationReader - { - private const string ConfigSectionTypeAttribute = "type"; - private const string ConfigurationElement = "configuration"; - private const string ConfigSectionsElement = "configSections"; - private const string ConfigSectionElement = "section"; - private const string ConfigSectionNameAttribute = "name"; - - private static readonly ILog _log = LogManager.GetLogger(typeof (ConfigurationReader)); - - /// - /// Reads the specified configuration section into a - /// . - /// - /// The resource to read. - /// The section name. - /// - /// A newly populated - /// . - /// - /// - /// If any errors are encountered while attempting to open a stream - /// from the supplied . - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.1 and greater of the .NET Framework) the actual XML. - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.0 of the .NET Framework). - /// - /// - /// If the configuration section was otherwise invalid. - /// - public static NameValueCollection Read(IResource resource, string configSection) - { - return ConfigurationReader.Read(resource, configSection, new NameValueCollection()); - } - - /// - /// Reads the specified configuration section into the supplied - /// . - /// - /// The resource to read. - /// The section name. - /// - /// The collection that is to be populated. May be - /// . - /// - /// - /// A newly populated - /// . - /// - /// - /// If any errors are encountered while attempting to open a stream - /// from the supplied . - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.1 and greater of the .NET Framework) the actual XML. - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.0 of the .NET Framework). - /// - /// - /// If the configuration section was otherwise invalid. - /// - public static NameValueCollection Read( - IResource resource, string configSection, NameValueCollection properties) - { - return ConfigurationReader.Read(resource, configSection, properties, true); - } - - /// - /// Reads the specified configuration section into the supplied - /// . - /// - /// The resource to read. - /// The section name. - /// - /// The collection that is to be populated. May be - /// . - /// - /// - /// If a key already exists, is its value to be appended to the current - /// value or replaced? - /// - /// - /// The populated - /// . - /// - /// - /// If any errors are encountered while attempting to open a stream - /// from the supplied . - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.1 and greater of the .NET Framework) the actual XML. - /// - /// - /// If any errors are encountered while loading or reading (this only applies to - /// v1.0 of the .NET Framework). - /// - /// - /// If the configuration section was otherwise invalid. - /// - public static NameValueCollection Read( - IResource resource, string configSection, NameValueCollection properties, bool overrideValues) - { - if (properties == null) - { - properties = new NameValueCollection(); - } - Stream stream = null; - try - { - XmlDocument doc = new XmlDocument(); - stream = resource.InputStream; - doc.Load(stream); - NameValueCollection newProperties = ReadFromXmlDocument(doc, configSection); - if(newProperties != null) - { - PopulateProperties(overrideValues, properties, newProperties); - } - } - finally - { - if (stream != null) - { - try - { - stream.Close(); - } - catch (IOException ex) - { - #region Instrumentation - - if (_log.IsWarnEnabled) - { - _log.Warn("Could not close stream from resource " + resource.Description, ex); - } - - #endregion - } - } - } - return properties; - } - - /// - /// Read from the specified configuration from the supplied XML - /// into a - /// . - /// - /// - /// - /// Does not support section grouping. The supplied XML - /// must already be loaded. - /// - /// - /// - /// The to read from. - /// - /// - /// The configuration section name to read. - /// - /// - /// A newly populated - /// . - /// - /// - /// If any errors are encountered while reading (this only applies to - /// v1.1 and greater of the .NET Framework). - /// - /// - /// If any errors are encountered while reading (this only applies to - /// v1.0 of the .NET Framework). - /// - /// - /// If the configuration section was otherwise invalid. - /// - public static NameValueCollection ReadFromXmlDocument(XmlDocument document, - string configSectionName) - { - // find the config section declaration (if one exists)... - XmlNode xmlConfig = document.SelectSingleNode( - string.Format("//{0}//{1}//{2}[@{3}='{4}']", - ConfigurationElement, ConfigSectionsElement, - ConfigSectionElement, ConfigSectionNameAttribute, configSectionName)); - - // create appropriate configuration section handler... - NameValueSectionHandler handler = null; - if (xmlConfig == null) - { - // none specified, so use the default... - handler = new NameValueSectionHandler(); - } - else - { - XmlAttribute xmlConfigType = xmlConfig.Attributes[ConfigSectionTypeAttribute]; - Type cshType = TypeResolutionUtils.ResolveType(xmlConfigType.Value); - object o = ObjectUtils.InstantiateType(cshType); - handler = o as NameValueSectionHandler; - if (handler == null) - { - throw ConfigurationUtils.CreateConfigurationException("Configuration section '" + configSectionName + "' not of type NameValueCollection."); - } - - } - XmlNode collectionNode = document.SelectSingleNode( - string.Format("//{0}//{1}", ConfigurationElement, configSectionName)); - if (collectionNode == null) - { - throw ConfigurationUtils.CreateConfigurationException("Cannot read properties; config section '" + configSectionName + "' not found."); - } - else - { - return (NameValueCollection) handler.Create(null, null, collectionNode); - } - } - - /// - /// Populates the supplied with values from - /// a .NET application configuration file. - /// - /// - /// The - /// to add any key-value pairs to. - /// - /// - /// The configuration section name in the a .NET application configuration - /// file. - /// - /// - /// If a key already exists, is its value to be appended to the current - /// value or replaced? - /// - /// - /// if the supplied - /// was found. - /// - public static bool PopulateFromAppConfig( - NameValueCollection properties, string configSectionName, bool overrideValues) - { - bool sectionFound = false; - - NameValueCollection newProperties - = ConfigurationUtils.GetSection(configSectionName) as NameValueCollection; - - if (newProperties != null) - { - sectionFound = true; - PopulateProperties(overrideValues, properties, newProperties); - } - return sectionFound; - } - - private static void PopulateProperties( - bool overrideValues, NameValueCollection properties, NameValueCollection newProperties) - { - if (!overrideValues) - { - properties.Add(newProperties); - } - else - { - foreach (string key in newProperties.AllKeys) - { - properties.Set(key, newProperties.Get(key)); - } - } - } - - #region Constructor (s) / Destructor - - // CLOVER:OFF - - /// - /// Creates a new instance of the ConfigurationReader class. - /// - /// - ///

- /// This is a utility class, and as such has no publicly visible - /// constructors. - ///

- ///
- private ConfigurationReader() - { - } - - // CLOVER:ON - - #endregion - } + */ + +#endregion + +#region Imports + +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; + +using Common.Logging; +using Spring.Core; +using Spring.Core.IO; +using Spring.Core.TypeResolution; +using Spring.Util; +using ConfigurationException=Common.Logging.ConfigurationException; +using ConfigXmlDocument = Spring.Util.ConfigXmlDocument; + +#endregion + +namespace Spring.Objects.Factory.Config +{ + /// + /// Various utility methods for .NET style .config files. + /// + /// + ///

+ /// Currently supports reading custom configuration sections and returning them as + /// objects. + ///

+ ///
+ /// Simon White + /// Mark Pollack + public sealed class ConfigurationReader + { + private const string ConfigSectionTypeAttribute = "type"; + private const string ConfigurationElement = "configuration"; + private const string ConfigSectionsElement = "configSections"; + private const string ConfigSectionGroupElement = "sectionGroup"; + private const string ConfigSectionElement = "section"; + private const string ConfigSectionNameAttribute = "name"; + + private static readonly ILog _log = LogManager.GetLogger(typeof(ConfigurationReader)); + + /// + /// Initializes the type members + /// + static ConfigurationReader() + {} + + /// + /// Reads the specified configuration section into a + /// . + /// + /// The resource to read. + /// The section name. + /// + /// A newly populated + /// . + /// + /// + /// If any errors are encountered while attempting to open a stream + /// from the supplied . + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.1 and greater of the .NET Framework) the actual XML. + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.0 of the .NET Framework). + /// + /// + /// If the configuration section was otherwise invalid. + /// + public static NameValueCollection Read(IResource resource, string configSection) + { + return ConfigurationReader.Read(resource, configSection, new NameValueCollection()); + } + + /// + /// Reads the specified configuration section into the supplied + /// . + /// + /// The resource to read. + /// The section name. + /// + /// The collection that is to be populated. May be + /// . + /// + /// + /// A newly populated + /// . + /// + /// + /// If any errors are encountered while attempting to open a stream + /// from the supplied . + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.1 and greater of the .NET Framework) the actual XML. + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.0 of the .NET Framework). + /// + /// + /// If the configuration section was otherwise invalid. + /// + public static NameValueCollection Read( + IResource resource, string configSection, NameValueCollection properties) + { + return ConfigurationReader.Read(resource, configSection, properties, true); + } + + /// + /// Reads the specified configuration section into the supplied + /// . + /// + /// The resource to read. + /// The section name. + /// + /// The collection that is to be populated. May be + /// . + /// + /// + /// If a key already exists, is its value to be appended to the current + /// value or replaced? + /// + /// + /// The populated + /// . + /// + /// + /// If any errors are encountered while attempting to open a stream + /// from the supplied . + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.1 and greater of the .NET Framework) the actual XML. + /// + /// + /// If any errors are encountered while loading or reading (this only applies to + /// v1.0 of the .NET Framework). + /// + /// + /// If the configuration section was otherwise invalid. + /// + public static NameValueCollection Read( + IResource resource, string configSection, NameValueCollection properties, bool overrideValues) + { + if (properties == null) + { + properties = new NameValueCollection(); + } + Stream stream = null; + try + { + ConfigXmlDocument doc = new ConfigXmlDocument(); + stream = resource.InputStream; + doc.Load(stream); + NameValueCollection newProperties = ReadFromXmlDocument(doc, configSection); + if (newProperties != null) + { + PopulateProperties(overrideValues, properties, newProperties); + } + } + finally + { + if (stream != null) + { + try + { + stream.Close(); + } + catch (IOException ex) + { + #region Instrumentation + + if (_log.IsWarnEnabled) + { + _log.Warn("Could not close stream from resource " + resource.Description, ex); + } + + #endregion + } + } + } + return properties; + } + + /// + /// Read from the specified configuration from the supplied XML + /// into a + /// . + /// + /// + /// + /// Does not support section grouping. The supplied XML + /// must already be loaded. + /// + /// + /// + /// The to read from. + /// + /// + /// The configuration section name to read. + /// + /// + /// A newly populated + /// . + /// + /// + /// If any errors are encountered while reading (this only applies to + /// v1.1 and greater of the .NET Framework). + /// + /// + /// If any errors are encountered while reading (this only applies to + /// v1.0 of the .NET Framework). + /// + /// + /// If the configuration section was otherwise invalid. + /// + public static NameValueCollection ReadFromXmlDocument(XmlDocument document, + string configSectionName) + { + // find the config section declaration (if one exists)... + return (NameValueCollection)GetSectionFromXmlDocument(document, configSectionName); + } + + /// + /// Returns the section from the specified resource with the given section name + /// + public static object GetSection(IResource resource, string configSectionName) + { + using (Stream istm = resource.InputStream) + { + ConfigXmlDocument doc = new ConfigXmlDocument(); + doc.Load(istm); + return GetSectionFromXmlDocument(doc, configSectionName); + } + } + +#if NET_2_0 + /// + /// Returns the typed section from the specified resource with the given section name + /// + public static TResult GetSection(IResource resource, string configSectionName) + { + using (Stream istm = resource.InputStream) + { + ConfigXmlDocument doc = new ConfigXmlDocument(); + doc.Load(istm); + object result = GetSectionFromXmlDocument(doc, configSectionName); + if (result != null && !(result is TResult)) + { + throw new ArgumentException(string.Format("evaluating configuration sectoin {0} does not result in an instance of type {1}", configSectionName, typeof(TResult))); + } + return (TResult)result; + } + } + + /// + /// Returns the typed result of evaluating the specified . + /// + /// if the result's type does not match the expected type + public static TResult GetSectionFromXmlDocument(XmlDocument configDocument, string configSectionName) + { + object result = GetSectionFromXmlDocument(configDocument, configSectionName); + if (result != null && !(result is TResult)) + { + throw new ArgumentException(string.Format("evaluating configuration sectoin {0} does not result in an instance of type {1}", configSectionName, typeof(TResult))); + } + return (TResult)result; + } +#endif + /// + /// Reads the specified configuration section from the given + /// + /// + /// + /// + public static object GetSectionFromXmlDocument(XmlDocument document, string configSectionName) + { + string[] sectionNameParts = configSectionName.Split('/'); + + string sectionHandlerPath = string.Format("//{0}/{1}", ConfigurationElement, ConfigSectionsElement); + + if (sectionNameParts.Length > 1) + { + // deal with sectionGroups + for (int i = 0; i < sectionNameParts.Length - 1; i++) + { + sectionHandlerPath = string.Format("{0}/{1}[@{2}='{3}']", sectionHandlerPath, ConfigSectionGroupElement, ConfigSectionNameAttribute, sectionNameParts[i]); + } + } + sectionHandlerPath = string.Format("{0}/{1}[@{2}='{3}']", sectionHandlerPath, ConfigSectionElement, ConfigSectionNameAttribute, sectionNameParts[sectionNameParts.Length - 1]); + + XmlNode xmlConfig = document.SelectSingleNode(sectionHandlerPath); + + // create appropriate configuration section handler... + Type handlerType = null; + if (xmlConfig == null) + { + // none specified, use machine inherited + XmlDocument machineConfig = new XmlDocument(); + machineConfig.Load(RuntimeEnvironment.SystemConfigurationFile); + xmlConfig = machineConfig.SelectSingleNode(sectionHandlerPath); + if (xmlConfig == null) + { + // TOOD: better throw a sensible exception in case of a missing handler configuration? + handlerType = typeof(NameValueFileSectionHandler); + } + } + + if (xmlConfig != null) + { + XmlAttribute xmlConfigType = xmlConfig.Attributes[ConfigSectionTypeAttribute]; + handlerType = TypeResolutionUtils.ResolveType(xmlConfigType.Value); + } + + if (handlerType == null) + { + throw new ConfigurationException(string.Format("missing 'type' attribute on section definition for '{0}'", configSectionName)); + } + + // obtain Xml node with section content + XmlNode sectionContent = document.SelectSingleNode(string.Format("//{0}/{1}", ConfigurationElement, configSectionName)); + if (sectionContent == null) + { + throw ConfigurationUtils.CreateConfigurationException("Cannot read properties; config section '" + configSectionName + "' not found."); + } + + // IConfigurationSectionHandler + if (typeof(IConfigurationSectionHandler).IsAssignableFrom(handlerType)) + { + IConfigurationSectionHandler handler = (IConfigurationSectionHandler)ObjectUtils.InstantiateType(handlerType); + return ((IConfigurationSectionHandler)handler).Create(null, null, sectionContent); + } + +#if !NET_1_0 && !NET_1_1 + // NET 2.0 ConfigurationSection + if (typeof(ConfigurationSection).IsAssignableFrom(handlerType)) + { + ConfigurationSection section = CreateConfigurationSection(handlerType, new XmlNodeReader(sectionContent)); + return section; + } +#endif + // Not supported + throw ConfigurationUtils.CreateConfigurationException("Configuration section '" + configSectionName + "' is neither of type IConfigurationSectionHandler nor ConfigurationSection."); + } + + +#if !NET_1_0 && !NET_1_1 + private delegate void DeserializeSectionMethod(ConfigurationSection section, XmlReader reader); + private static DeserializeSectionMethod deserialized = (DeserializeSectionMethod)Delegate.CreateDelegate(typeof(DeserializeSectionMethod), + typeof(ConfigurationSection).GetMethod("DeserializeSection", + BindingFlags.Instance | + BindingFlags.NonPublic)); + + private static ConfigurationSection CreateConfigurationSection(Type handlerType, XmlReader reader) + { + ConfigurationSection section = (ConfigurationSection)ObjectUtils.InstantiateType(handlerType); + deserialized(section, reader); + return section; + } +#endif + + /// + /// Populates the supplied with values from + /// a .NET application configuration file. + /// + /// + /// The + /// to add any key-value pairs to. + /// + /// + /// The configuration section name in the a .NET application configuration + /// file. + /// + /// + /// If a key already exists, is its value to be appended to the current + /// value or replaced? + /// + /// + /// if the supplied + /// was found. + /// + public static bool PopulateFromAppConfig( + NameValueCollection properties, string configSectionName, bool overrideValues) + { + bool sectionFound = false; + + NameValueCollection newProperties + = ConfigurationUtils.GetSection(configSectionName) as NameValueCollection; + + if (newProperties != null) + { + sectionFound = true; + PopulateProperties(overrideValues, properties, newProperties); + } + return sectionFound; + } + + private static void PopulateProperties( + bool overrideValues, NameValueCollection properties, NameValueCollection newProperties) + { + if (!overrideValues) + { + properties.Add(newProperties); + } + else + { + foreach (string key in newProperties.AllKeys) + { + properties.Set(key, newProperties.Get(key)); + } + } + } + + #region Constructor (s) / Destructor + + // CLOVER:OFF + + /// + /// Creates a new instance of the ConfigurationReader class. + /// + /// + ///

+ /// This is a utility class, and as such has no publicly visible + /// constructors. + ///

+ ///
+ private ConfigurationReader() + { + } + + // CLOVER:ON + + #endregion + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj index 3dc89ca4..97de62a9 100644 --- a/src/Spring/Spring.Core/Spring.Core.2008.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj @@ -1008,6 +1008,7 @@ + diff --git a/src/Spring/Spring.Core/Util/ConfigurationUtils.cs b/src/Spring/Spring.Core/Util/ConfigurationUtils.cs index 71f022f0..436357a0 100644 --- a/src/Spring/Spring.Core/Util/ConfigurationUtils.cs +++ b/src/Spring/Spring.Core/Util/ConfigurationUtils.cs @@ -22,6 +22,7 @@ using System; using System.Configuration; +using System.Reflection; using System.Xml; #endregion @@ -34,6 +35,12 @@ namespace Spring.Util /// Aleksandar Seovic public class ConfigurationUtils { + /// + /// Avoid BeforeFieldInit pitfall + /// + static ConfigurationUtils() + {} + /// /// Parses the configuration section. /// @@ -161,7 +168,7 @@ namespace Spring.Util /// Configuration exception. public static Exception CreateConfigurationException(string message) { - return CreateConfigurationException(message, (Exception) null); + return CreateConfigurationException(message, (Exception)null); } /// @@ -170,7 +177,7 @@ namespace Spring.Util /// Configuration exception. public static Exception CreateConfigurationException() { - return CreateConfigurationException(null, (Exception) null); + return CreateConfigurationException(null, (Exception)null); } /// @@ -225,5 +232,55 @@ namespace Spring.Util #endif } + +#if NET_2_0 + /// + /// Sets the current to be used by . + /// + /// + /// íf implements , this method invokes + /// on the new configSystem to chain them.
+ /// Note, that this method requires reflection on internals of + ///
+ /// the configuration system to set + /// bypasses the check if the current system has already been initialized + /// the previous config system, if any + public static System.Configuration.Internal.IInternalConfigSystem SetConfigurationSystem(System.Configuration.Internal.IInternalConfigSystem configSystem, bool enforce) + { + FieldInfo s_configSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic); + System.Configuration.Internal.IInternalConfigSystem innerConfigSystem = (System.Configuration.Internal.IInternalConfigSystem)s_configSystem.GetValue(null); + if (configSystem is IChainableConfigSystem) + { + ((IChainableConfigSystem)configSystem).SetInnerConfigurationSystem(innerConfigSystem); + } + + try + { + setConfigurationSystem(configSystem, true); + } + catch (InvalidOperationException) + { + if (!enforce) + { + throw; + } + s_configSystem.SetValue(null, configSystem); + } + + return innerConfigSystem; + } + + private static T CreateDelegate(MethodInfo method) + { + return (T)(object)Delegate.CreateDelegate(typeof(T), method); + } + + private delegate void SetConfigurationSystemHandler(System.Configuration.Internal.IInternalConfigSystem configSystem, bool setComplete); + + private static SetConfigurationSystemHandler setConfigurationSystem = + CreateDelegate(typeof(ConfigurationManager).GetMethod("SetConfigurationSystem" + , BindingFlags.Static | BindingFlags.NonPublic)); +#endif + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Util/IChainableConfigSystem.cs b/src/Spring/Spring.Core/Util/IChainableConfigSystem.cs new file mode 100644 index 00000000..e9634dbd --- /dev/null +++ b/src/Spring/Spring.Core/Util/IChainableConfigSystem.cs @@ -0,0 +1,39 @@ +#region License + +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +namespace Spring.Util +{ +#if NET_2_0 + using System.Configuration.Internal; + + /// + /// Implement this interface to create your own, delegating + /// and set them using + /// + public interface IChainableConfigSystem : IInternalConfigSystem + { + /// + /// + /// + /// + void SetInnerConfigurationSystem(IInternalConfigSystem innerConfigSystem); + } +#endif +} \ No newline at end of file diff --git a/src/Spring/Spring.Services/EnterpriseServices/EnterpriseServicesExporter.cs b/src/Spring/Spring.Services/EnterpriseServices/EnterpriseServicesExporter.cs index 1bd9fa07..82c39c37 100644 --- a/src/Spring/Spring.Services/EnterpriseServices/EnterpriseServicesExporter.cs +++ b/src/Spring/Spring.Services/EnterpriseServices/EnterpriseServicesExporter.cs @@ -38,7 +38,7 @@ using Spring.Util; namespace Spring.EnterpriseServices { /// - /// Exports specified components as ServicedComponents. + /// Exports components as ServicedComponents using the specified s. /// /// /// diff --git a/src/Spring/Spring.Services/EnterpriseServices/ExeConfigurationSystem.cs b/src/Spring/Spring.Services/EnterpriseServices/ExeConfigurationSystem.cs new file mode 100644 index 00000000..225a6738 --- /dev/null +++ b/src/Spring/Spring.Services/EnterpriseServices/ExeConfigurationSystem.cs @@ -0,0 +1,156 @@ +#region License + +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +namespace Spring.EnterpriseServices +{ +#if NET_2_0 + using System; + using System.Configuration; + using System.Reflection; + using System.Xml; + using Spring.Core.TypeResolution; + using Spring.Util; + + using System.Configuration.Internal; + + /// + /// SUBJECT TO CHANGE -FOR INTERNAL USE ONLY!
+ /// Holds configuration information from a given configuration file, obtained by . + /// You may use to replace the active configuration system. + ///
+ /// + /// + public class ExeConfigurationSystem : IChainableConfigSystem + { + private string _configPath; + private Configuration _configuration; + private IInternalConfigSystem _next; + + /// + /// initializes this instance with a path to be passed into + /// + /// + public ExeConfigurationSystem(string configPath) + { + _configPath = configPath; + } + + /// + /// Purges cached configuration + /// + public void RefreshConfig(string sectionName) + { + if (_next != null) + { + _next.RefreshConfig(sectionName); + } + _configuration = null; + } + + /// + /// Only true if the underlying config system supports this. + /// + public bool SupportsUserConfig + { + get + { + EnsureInit(); + if (_next != null) + { + return _next.SupportsUserConfig; + } + return false; + } + } + + /// + /// Set the nested configuration system to delegate calls in case we can't resolve a config section ourselves + /// + public void SetInnerConfigurationSystem(IInternalConfigSystem innerConfigSystem) + { + _next = innerConfigSystem; + } + + private void EnsureInit() + { + if (_configuration == null) + { + lock (this) + { + if (_configuration == null) + { + _configuration = ConfigurationManager.OpenExeConfiguration(_configPath); + } + } + } + } + + private delegate object ResolveSectionRuntimeObject(ConfigurationSection section); + + private static ResolveSectionRuntimeObject resolveSectionRuntimeObject = + (ResolveSectionRuntimeObject)Delegate.CreateDelegate(typeof(ResolveSectionRuntimeObject), + typeof (ConfigurationSection).GetMethod("GetRuntimeObject", + BindingFlags.Instance | + BindingFlags.NonPublic)); + + /// + /// Get the specified section + /// + /// + /// + public object GetSection(string sectionName) + { + EnsureInit(); + ConfigurationSection thisSection = _configuration.GetSection(sectionName); + + object parent = null; + if (_next != null) + { + parent = _next.GetSection(sectionName); + } + if (thisSection == null) + { + return parent; + } + + object result = resolveSectionRuntimeObject(thisSection); + if (result is DefaultSection) + { + string rawXml = thisSection.SectionInformation.GetRawXml(); + if (string.IsNullOrEmpty(rawXml)) + { + return null; + } + + Type t = TypeResolutionUtils.ResolveType(thisSection.SectionInformation.Type); + if (typeof(IConfigurationSectionHandler).IsAssignableFrom(t)) + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(thisSection.SectionInformation.GetRawXml()); + IConfigurationSectionHandler handler = (IConfigurationSectionHandler) Activator.CreateInstance(t); + return handler.Create(parent, null, xmlDoc.DocumentElement ); + } + throw new ConfigurationErrorsException(string.Format("missing
declaration for section '{0}'", sectionName)); + } + return result; + } + } +#endif +} \ No newline at end of file diff --git a/src/Spring/Spring.Services/EnterpriseServices/ServicedComponentHelper.cs b/src/Spring/Spring.Services/EnterpriseServices/ServicedComponentHelper.cs index ce85085a..00fb0496 100644 --- a/src/Spring/Spring.Services/EnterpriseServices/ServicedComponentHelper.cs +++ b/src/Spring/Spring.Services/EnterpriseServices/ServicedComponentHelper.cs @@ -23,11 +23,17 @@ #region Imports using System; +using System.Configuration; +using System.Diagnostics; using System.EnterpriseServices; using System.IO; using System.Reflection; using System.Xml; +using Spring.Context; using Spring.Context.Support; +using Spring.Core.IO; +using Spring.Objects.Factory.Config; +using Spring.Util; using ConfigXmlDocument = Spring.Util.ConfigXmlDocument; #endregion @@ -43,6 +49,7 @@ namespace Spring.EnterpriseServices { private static bool isInitialized; private static string componentDirectory; + private static IApplicationContext _appContext; static ServicedComponentHelper() { @@ -60,6 +67,7 @@ namespace Spring.EnterpriseServices lock (typeof(ServicedComponentHelper)) { if (isInitialized) return; + isInitialized = true; // this is to ensure, that assemblies placed next to the component assembly can be loaded @@ -70,26 +78,56 @@ namespace Spring.EnterpriseServices // switch to component assembly's directory (affects resolving relative paths during context instantiation!) Environment.CurrentDirectory = componentDirectory; // read in config file if any - FileInfo configFile = new FileInfo(componentAssemblyFile.FullName + ".spring-context.xml"); + FileInfo configFile = new FileInfo(componentAssemblyFile.FullName); if (configFile.Exists) { - ConfigXmlDocument configDoc = new ConfigXmlDocument(); - configDoc.Load(configFile.FullName); - XmlNode configNode = configDoc.SelectSingleNode("//context"); - ServicedComponentContextHandler handler = new ServicedComponentContextHandler(); - lock (ContextRegistry.SyncRoot) + bool isRunningOutOfProcess = IsRunningOutOfProcess(); + +#if NET_2_0 + ExeConfigurationSystem comConfig = new ExeConfigurationSystem(configFile.FullName); + + if (isRunningOutOfProcess) { - // it might accidentially have happend, that the contextregistry has already - // been initialized using the client application's app.config configuration. - // Most of the time this doesn't make sense to read a configuration from a - // different AppDomain, thus we read in our own config file. - ContextRegistry.Clear(); - handler.Create(null, null, configNode); + Trace.WriteLine(string.Format("configuring COM OutProc Server '{0}' using '{1}'", componentAssemblyFile.FullName, componentAssemblyFile.FullName + ".config")); + + // make the config "global" + ConfigurationUtils.SetConfigurationSystem(comConfig, true); + _appContext = ContextRegistry.GetContext(); + if (_appContext == null) + { + throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require section"); + } + } + else + { + Trace.WriteLine(string.Format("configuring COM InProc Server '{0}' using section from file '{1}'", componentAssemblyFile.FullName, componentAssemblyFile.FullName + ".config")); + _appContext = (IApplicationContext)comConfig.GetSection("spring/context"); + if (_appContext == null) + { + throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require section in configuration file"); + } + } +#else + _appContext = (IApplicationContext) ConfigurationReader.GetSection(new FileSystemResource(configFile.FullName + ".config"),"spring/context"); + if (_appContext == null) + { + throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require section in configuration file"); + } +#endif + } + else + { + Trace.WriteLine(string.Format("No configuration file '{0}' for COM component '{1}' found - bypassing configuration", componentAssemblyFile.FullName + ".config", componentAssemblyFile.FullName)); } } } + private static bool IsRunningOutOfProcess() + { + // TODO: checkout a prob. better way to find out, whether we are executing as a com server or library + return AppDomain.CurrentDomain.SetupInformation.ApplicationName == "dllhost.exe"; + } private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { string name = args.Name.Split(',')[0]; @@ -104,7 +142,11 @@ namespace Spring.EnterpriseServices public static object GetObject(ServicedComponent sender, string targetName) { EnsureComponentContextRegistryInitialized(sender.GetType()); - return ContextRegistry.GetContext().GetObject(targetName); + if (_appContext == null) + { + throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require section in configuration file"); + } + return _appContext.GetObject(targetName); } } } diff --git a/src/Spring/Spring.Services/Spring.Services.2008.csproj b/src/Spring/Spring.Services/Spring.Services.2008.csproj index a78a4d3a..38a6c16a 100644 --- a/src/Spring/Spring.Services/Spring.Services.2008.csproj +++ b/src/Spring/Spring.Services/Spring.Services.2008.csproj @@ -78,6 +78,7 @@ System + System.Data @@ -98,6 +99,7 @@ Code + diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/ConfigurationReaderTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/ConfigurationReaderTests.cs index a3a57b6c..842e9edb 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/ConfigurationReaderTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/ConfigurationReaderTests.cs @@ -20,9 +20,11 @@ #region Imports +using System; using System.Collections.Specialized; using System.Configuration; using System.IO; +using System.Runtime.InteropServices; using System.Text; using NUnit.Framework; @@ -45,102 +47,182 @@ namespace Spring.Objects.Factory.Config
- - - - + + + + "; +#if !NET_0 && !NET_1_1 + /// + /// Unfortunately ConfigurationManager doesn't accept uri's. + /// + [Test] + public void ConfigurationManagerCannotReadFromUrl() + { + try + { + ConfigurationManager.OpenExeConfiguration("http://localhost/something.config"); + Assert.Fail(); + } + catch (ConfigurationErrorsException cfgex) + { + Assert.IsInstanceOfType(typeof (ArgumentException), cfgex.InnerException); + } + } +#endif + [Test] public void ReadSunnyDay() { - new StreamHelperDecorator(new StreamHelperCallback(_ReadSunnyDay)).Run(); + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + NameValueCollection props = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo"); + Assert.IsNotNull(props, + "Failed to read in any properties at all (props is null)."); + Assert.AreEqual(2, props.Count, + "Wrong number of properties read in."); + Assert.AreEqual("kiley", + props["rilo"], + "Wrong value for second property"); + Assert.AreEqual("lewis", + props["jenny"], + "Wrong value for second property"); + } + + string machineConfig = RuntimeEnvironment.SystemConfigurationFile; } - private void _ReadSunnyDay(out Stream stream) +#if !NET_1_0 && !NET_1_1 + [Test] + public void GetSectionLocalSectionHandler() { - stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml)); - NameValueCollection props - = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo"); - Assert.IsNotNull(props, "Failed to read in any properties at all (props is null)."); - Assert.AreEqual(2, props.Count, "Wrong number of properties read in."); - Assert.AreEqual("kiley", props["rilo"], "Wrong value for second property"); - Assert.AreEqual("lewis", props["jenny"], "Wrong value for second property"); + string xml = @" + + +
+ + + + + +"; + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml))) + { + ConnectionStringsSection css = ConfigurationReader.GetSection(new InputStreamResource(stream, ""), "connectionStrings"); + Assert.IsNotNull(css, "Failed to read in any properties at all (props is null)."); + Assert.IsNotNull(css.ConnectionStrings["Sales"]); + Assert.AreEqual("System.Data.SqlClient", css.ConnectionStrings["Sales"].ProviderName); + Assert.AreEqual("server=myserver;database=Products;uid=user name;pwd=secure password", css.ConnectionStrings["Sales"].ConnectionString); + } + } + + [Test] + public void GetSectionMachineInheritedSectionHandler() + { + string xml = @" + + + + + +"; + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml))) + { + ConnectionStringsSection css = ConfigurationReader.GetSection(new InputStreamResource(stream, ""), "connectionStrings"); + Assert.IsNotNull(css, "Failed to read in any properties at all (props is null)."); + Assert.IsNotNull(css.ConnectionStrings["Sales"]); + Assert.AreEqual("System.Data.SqlClient", css.ConnectionStrings["Sales"].ProviderName); + Assert.AreEqual("server=myserver;database=Products;uid=user name;pwd=secure password", css.ConnectionStrings["Sales"].ConnectionString); + } + } + +#endif + + [Test] + public void GetSectionSunnyDay() + { + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + NameValueCollection props = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo"); + Assert.IsNotNull(props, + "Failed to read in any properties at all (props is null)."); + Assert.AreEqual(2, props.Count, + "Wrong number of properties read in."); + Assert.AreEqual("kiley", + props["rilo"], + "Wrong value for second property"); + Assert.AreEqual("lewis", + props["jenny"], + "Wrong value for second property"); + } } [Test] public void ReadWithOverrideOfPreviouslyExistingValues() { - new StreamHelperDecorator(new StreamHelperCallback(_ReadWithOverrideOfPreviouslyExistingValues)).Run(); - } - - private void _ReadWithOverrideOfPreviouslyExistingValues(out Stream stream) - { - stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml)); - NameValueCollection defaults = new NameValueCollection(); - defaults.Add("jenny", "agutter"); - NameValueCollection props - = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", defaults); - Assert.IsTrue(ReferenceEquals(defaults, props), "Must have got same collection as was passed in."); - Assert.AreEqual("lewis", props["jenny"], "Wrong value for overridden property (was not overridden"); + using(Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + NameValueCollection defaults = new NameValueCollection(); + defaults.Add("jenny", "agutter"); + NameValueCollection props + = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", defaults); + Assert.IsTrue(ReferenceEquals(defaults, props), "Must have got same collection as was passed in."); + Assert.AreEqual("lewis", props["jenny"], "Wrong value for overridden property (was not overridden"); + } } [Test] public void ReadWithOverrideOfPreviouslyExistingValuesButWithOverrideSwitchedOff() { - new StreamHelperDecorator(new StreamHelperCallback(_ReadWithOverrideOfPreviouslyExistingValuesButWithOverrideSwitchedOff)).Run(); - } - - private void _ReadWithOverrideOfPreviouslyExistingValuesButWithOverrideSwitchedOff(out Stream stream) - { - stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml)); - NameValueCollection defaults = new NameValueCollection(); - defaults.Add("jenny", "agutter"); - NameValueCollection props - = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", defaults, false); - Assert.IsTrue(ReferenceEquals(defaults, props), "Must have got same collection as was passed in."); - Assert.AreEqual("agutter,lewis", props["jenny"], "Wrong value for overridden property (was not overridden"); + using(Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + NameValueCollection defaults = new NameValueCollection(); + defaults.Add("jenny", "agutter"); + NameValueCollection props + = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", defaults, false); + Assert.IsTrue(ReferenceEquals(defaults, props), "Must have got same collection as was passed in."); + Assert.AreEqual("agutter,lewis", props["jenny"], "Wrong value for overridden property (was not overridden"); + } } [Test] public void ReadWithNullExistingValuesPassedIn() { - new StreamHelperDecorator(new StreamHelperCallback(_ReadWithNullExistingValuesPassedIn)).Run(); - } - - private void _ReadWithNullExistingValuesPassedIn(out Stream stream) - { - stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml)); - NameValueCollection props - = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", null); - Assert.IsNotNull(props, "Failed to read in any properties at all (props is null)."); - Assert.AreEqual(2, props.Count, "Wrong number of properties read in."); - Assert.AreEqual("kiley", props["rilo"], "Wrong value for second property"); - Assert.AreEqual("lewis", props["jenny"], "Wrong value for second property"); + using(Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + NameValueCollection props + = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", null); + Assert.IsNotNull(props, "Failed to read in any properties at all (props is null)."); + Assert.AreEqual(2, props.Count, "Wrong number of properties read in."); + Assert.AreEqual("kiley", props["rilo"], "Wrong value for second property"); + Assert.AreEqual("lewis", props["jenny"], "Wrong value for second property"); + } } [Test] public void ReadWithNoConfigSectionSectionDefaultsToNameValueSectionHandler() - { - new StreamHelperDecorator(new StreamHelperCallback(_ReadWithNoConfigSectionSectionDefaultsToNameValueSectionHandler)).Run(); - } - - private void _ReadWithNoConfigSectionSectionDefaultsToNameValueSectionHandler(out Stream stream) { const string NoConfigSectionXml = @" - - - - + + + + "; - stream = new MemoryStream(Encoding.UTF8.GetBytes(NoConfigSectionXml)); - NameValueCollection props - = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", null); - Assert.IsNotNull(props, "Failed to read in any properties at all (props is null)."); - Assert.AreEqual(2, props.Count, "Wrong number of properties read in."); - Assert.AreEqual("kiley", props["rilo"], "Wrong value for second property"); - Assert.AreEqual("lewis", props["jenny"], "Wrong value for second property"); + using(Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(NoConfigSectionXml))) + { + NameValueCollection props + = ConfigurationReader.Read(new InputStreamResource(stream, ""), "foo", null); + Assert.IsNotNull(props, "Failed to read in any properties at all (props is null)."); + Assert.AreEqual(2, props.Count, "Wrong number of properties read in."); + Assert.AreEqual("kiley", props["rilo"], "Wrong value for second property"); + Assert.AreEqual("lewis", props["jenny"], "Wrong value for second property"); + } } [Test] @@ -148,16 +230,13 @@ namespace Spring.Objects.Factory.Config [ExpectedException(typeof(ConfigurationException), "Cannot read properties; config section 'ELNOMBRE' not found.")] #else [ExpectedException(typeof(ConfigurationErrorsException), "Cannot read properties; config section 'ELNOMBRE' not found.")] -#endif +#endif public void TryReadFromNonExistantConfigSection() { - new StreamHelperDecorator(new StreamHelperCallback(_TryReadFromNonExistantConfigSection)).Run(); - } - - private void _TryReadFromNonExistantConfigSection(out Stream stream) - { - stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml)); - ConfigurationReader.Read(new InputStreamResource(stream, ""), "ELNOMBRE", null); + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(SunnyDayXml))) + { + ConfigurationReader.Read(new InputStreamResource(stream, ""), "ELNOMBRE", null); + } } } } \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/TestResourceLoader.cs b/test/Spring/Spring.Core.Tests/TestResourceLoader.cs index d929d822..6280d540 100644 --- a/test/Spring/Spring.Core.Tests/TestResourceLoader.cs +++ b/test/Spring/Spring.Core.Tests/TestResourceLoader.cs @@ -14,7 +14,13 @@ namespace Spring /// Supports obtaining embedded resources from assembly. ///
/// + /// /// The first context argument is always the namespace scope to be used for resolving resource names. + /// + /// + /// Upon first usage, TestResourceLoader registers the "testres://" protocol prefix for loading embedded resources. + /// A testres:// Url must be of the form "testres://./<context-typename>#<ext" - . + /// /// public class TestResourceLoader { @@ -73,6 +79,12 @@ namespace Spring private TestResourceLoader() { } + /// + /// Returns an Uri of the form "testres://./resourcname" that may be passed into etc. + /// + /// + /// + /// public static Uri GetUri(object context, string ext) { string resname = context.GetType().AssemblyQualifiedName + "#" + ext; @@ -131,6 +143,10 @@ namespace Spring } } + /// + /// Returns an embedded assembly resource, who's name is constructed from the given parameters as + /// context.GetType().FullName + ext + /// public static Stream GetStream(object context, string ext) { Type contextType = (context is Type) ? (Type)context : context.GetType(); @@ -140,6 +156,32 @@ namespace Spring return stm; } + /// + /// Exports a resource obtained via to the specified destination. + /// + public static FileInfo ExportResource(object context, string ext, FileInfo destination) + { + Stream istm = GetStream(context, ext); + using(istm) + { + FileStream ostm = destination.OpenWrite(); + using (ostm) + { + byte[] buffer = new byte[2048]; + int bytesRead = istm.Read(buffer, 0, buffer.Length); + while (bytesRead > 0) + { + ostm.Write(buffer, 0, bytesRead); + bytesRead = istm.Read(buffer, 0, buffer.Length); + } + ostm.Flush(); + ostm.Close(); + } + istm.Close(); + } + return destination; + } + /// /// returns an "assembly://" uri for the specified manifest resource, scoped by the namespace of the specified type. /// ("assembly://hint.assemblyname_without_version/hint.Namespace/name") diff --git a/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.config b/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.config new file mode 100644 index 00000000..10e66559 --- /dev/null +++ b/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.config @@ -0,0 +1,26 @@ + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.cs b/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.cs new file mode 100644 index 00000000..e294ebb6 --- /dev/null +++ b/test/Spring/Spring.Services.Tests/EnterpriseServices/ExeConfigurationSystemTests.cs @@ -0,0 +1,45 @@ + +namespace Spring.EnterpriseServices +{ +#if NET_2_0 + using System.Configuration; + using System.Configuration.Internal; + using System.IO; + using Common.Logging; + using Common.Logging.Simple; + using NUnit.Framework; + using Spring.Util; + + [TestFixture] + public class ExeConfigurationSystemTests + { + [Test] + public void SunnyDay() + { + FileInfo resFile = TestResourceLoader.ExportResource(this, ".config", new FileInfo(Path.GetTempFileName()+".config")); + string exePath = resFile.FullName.Substring(0, resFile.FullName.Length - ".config".Length); + Assert.IsTrue(resFile.Exists); + IInternalConfigSystem prevConfig = null; + try + { + ExeConfigurationSystem ccs = new ExeConfigurationSystem(exePath); + prevConfig = ConfigurationUtils.SetConfigurationSystem(ccs, true); + LogSetting settings = (LogSetting) ConfigurationManager.GetSection("common/logging"); + Assert.AreEqual(typeof (TraceLoggerFactoryAdapter), settings.FactoryAdapterType); + + Assert.AreEqual("from custom config!", ConfigurationManager.AppSettings["key"]); + + Assert.IsNull(ConfigurationManager.GetSection("spring/context")); + } + finally + { + if (prevConfig != null) + { + ConfigurationUtils.SetConfigurationSystem(prevConfig, true); + } + resFile.Delete(); + } + } + } +#endif +} diff --git a/test/Spring/Spring.Services.Tests/EnterpriseServices/ServicedComponentExporterTests.cs b/test/Spring/Spring.Services.Tests/EnterpriseServices/ServicedComponentExporterTests.cs index 93d93783..6bc5e436 100644 --- a/test/Spring/Spring.Services.Tests/EnterpriseServices/ServicedComponentExporterTests.cs +++ b/test/Spring/Spring.Services.Tests/EnterpriseServices/ServicedComponentExporterTests.cs @@ -111,7 +111,7 @@ namespace Spring.EnterpriseServices try { // ServiceComponent will obtain its target from root context - ContextRegistry.RegisterContext(appCtx); +// ContextRegistry.RegisterContext(appCtx); IComparable testObject; testObject = (IComparable)Activator.CreateInstance(serviceType); @@ -126,6 +126,7 @@ namespace Spring.EnterpriseServices } } +#if NET_2_0 [Test] public void CanExportAopProxyToServer() { @@ -146,9 +147,9 @@ namespace Spring.EnterpriseServices finally { exporter.UnregisterServicedComponents(assemblyFile); - ContextRegistry.Clear(); } } +#endif private Type ExportObject(EnterpriseServicesExporter exporter, FileInfo assemblyFile, IConfigurableApplicationContext appCtx, string objectName) { diff --git a/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.dll.config b/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.dll.config new file mode 100644 index 00000000..b7fc23cf --- /dev/null +++ b/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.dll.config @@ -0,0 +1,17 @@ + + + + + +
+
+ + + + + + + + + + diff --git a/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.config b/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.config new file mode 100644 index 00000000..4b8a7b34 --- /dev/null +++ b/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.config @@ -0,0 +1,47 @@ + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + System.IComparable + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.spring-context.xml b/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.spring-context.xml deleted file mode 100644 index 6262be52..00000000 --- a/test/Spring/Spring.Services.Tests/ServiceComponentExporterTests.TestServicedComponents.exe.spring-context.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj b/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj index 85ccf814..0b319531 100644 --- a/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj +++ b/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj @@ -72,6 +72,14 @@ prompt + + False + ..\..\..\lib\Net\2.0\antlr.runtime.dll + + + False + ..\..\..\lib\Net\2.0\Common.Logging.dll + False ..\..\..\lib\Net\2.0\DotNetMock.dll @@ -87,6 +95,7 @@ System + System.Data @@ -103,6 +112,8 @@ Code + + @@ -138,6 +149,7 @@ + PreserveNewest @@ -190,9 +202,12 @@ - + Always - + + + Always + Always