- /// 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.
- ///
+ /// 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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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