diff --git a/doc/reference/src/objects.xml b/doc/reference/src/objects.xml
index c44dd277..ed0ad09a 100644
--- a/doc/reference/src/objects.xml
+++ b/doc/reference/src/objects.xml
@@ -5028,13 +5028,22 @@ cfg.PostProcessObjectFactory(factory);
value will be used. <object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core">
<property name="VariableSources">
<list>
+ <object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core">
+ <property name="Location" value="~\application.properties" />
+ <property name="IgnoreMissingResources" value="true"/>
+ </object>
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
<property name="SectionNames" value="CryptedConfiguration" />
</object>
</list>
</property>
</object>
- The IVariableSource interface is shown below
+
+ The use of the IgnoreMissingResources
+ property above will mean that if the property file is not found it
+ will be silently ignored and the resolution will continue to
+ ConfigSectionVariableSource.
+ The IVariableSource interface is shown below
public interface IVariableSource
{
diff --git a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs
index a695ee88..ce8e612b 100644
--- a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs
+++ b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs
@@ -489,31 +489,57 @@ namespace Spring.Context.Support
/// In the case of errors.
private void InvokeObjectFactoryPostProcessors()
{
- // do NOT include IFactoryObjects; they (typically) need to be instantiated
+ // Do NOT include IFactoryObjects; they (typically) need to be instantiated
// to determine the Type of object that they create, and if they are instantiated
// then we won't be able to do any factory post processin' on 'em...
- string[] factoryProcessorNames
- = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false);
- ArrayList orderedFactoryProcessors = new ArrayList();
- IList nonOrderedFactoryProcessorNames = new ArrayList();
- for (int i = 0; i < factoryProcessorNames.Length; ++i)
+ ArrayList factoryProcessorNames = new ArrayList();
+ string[] names = GetObjectNamesForType(typeof (IObjectFactoryPostProcessor), true, false);
+ foreach (string s in names)
{
- string processorName = factoryProcessorNames[i];
- object processor = GetObject(processorName);
- if (typeof(IOrdered).IsAssignableFrom(GetType(processorName)))
+ factoryProcessorNames.Add(s);
+ }
+
+ ArrayList priorityOrderedFactoryProcessors = new ArrayList();
+ ArrayList orderedFactoryProcessorsNames = new ArrayList();
+ ArrayList nonOrderedFactoryProcessorNames = new ArrayList();
+
+ for (int i = 0; i < factoryProcessorNames.Count; ++i)
+ {
+ string processorName = (string) factoryProcessorNames[i];
+ if (IsTypeMatch(processorName, typeof(IPriorityOrdered)))
{
- orderedFactoryProcessors.Add(processor);
+ priorityOrderedFactoryProcessors.Add(ObjectFactory.GetObject(processorName, typeof(IObjectFactoryPostProcessor)));
}
+ else if (IsTypeMatch(processorName, typeof(IOrdered)))
+ {
+ orderedFactoryProcessorsNames.Add(processorName);
+ }
else
{
- nonOrderedFactoryProcessorNames.Add(processor);
+ nonOrderedFactoryProcessorNames.Add(processorName);
}
}
- // first, invoke those IObjectFactoryPostProcessors that implement IOrdered...
+ // First, invoke the IObjectFactoryPostProcessors that implement IPriorityOrdered.
+ InvokePriorityOrderedObjectFactoryPostProcessors(factoryProcessorNames, priorityOrderedFactoryProcessors);
+
+ // Second, invoke those IObjectFactoryPostProcessors that implement IOrdered...
+ ArrayList orderedFactoryProcessors = new ArrayList();
+ foreach (string orderedFactoryProcessorsName in orderedFactoryProcessorsNames)
+ {
+ orderedFactoryProcessors.Add(ObjectFactory.GetObject(orderedFactoryProcessorsName,
+ typeof (IObjectFactoryPostProcessor)));
+ }
orderedFactoryProcessors.Sort(new OrderComparator());
- ProcessObjectFactoryPostProcessors(orderedFactoryProcessors);
+ InvokeObjectFactoryPostProcessors(orderedFactoryProcessors, ObjectFactory);
+
// and then the unordered ones...
- ProcessObjectFactoryPostProcessors(nonOrderedFactoryProcessorNames);
+ ArrayList nonOrderedPostProcessors = new ArrayList();
+ foreach (string nonOrderedFactoryProcessorName in nonOrderedFactoryProcessorNames)
+ {
+ nonOrderedPostProcessors.Add(ObjectFactory.GetObject(nonOrderedFactoryProcessorName,
+ typeof (IObjectFactoryPostProcessor)));
+ }
+ InvokeObjectFactoryPostProcessors(nonOrderedPostProcessors, ObjectFactory);
#region Instrumentation
@@ -522,18 +548,42 @@ namespace Spring.Context.Support
log.Debug(string.Format(
CultureInfo.InvariantCulture,
"processed {0} IFactoryObjectPostProcessors defined in application context [{1}].",
- factoryProcessorNames.Length,
+ factoryProcessorNames.Count,
Name));
}
#endregion
}
- private void ProcessObjectFactoryPostProcessors(IList objectFactoryPostProcessors)
+ protected virtual void InvokePriorityOrderedObjectFactoryPostProcessors(ArrayList factoryProcessorNames, ArrayList priorityOrderedFactoryProcessors)
+ {
+ priorityOrderedFactoryProcessors.Sort(new OrderComparator());
+ InvokeObjectFactoryPostProcessors(priorityOrderedFactoryProcessors, ObjectFactory);
+
+ // Now will find any additional IObjectFactoryPostProcessors that implement IPriorityOrdered that may have been
+ // resolved due to using TypeAlias
+ string[] factoryProcessorNamesAfterTypeAlias = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false);
+ priorityOrderedFactoryProcessors.Clear();
+ foreach (string factoryProcessorName in factoryProcessorNamesAfterTypeAlias)
+ {
+ if (!factoryProcessorNames.Contains(factoryProcessorName))
+ {
+ if (IsTypeMatch(factoryProcessorName, typeof(IPriorityOrdered)))
+ {
+ priorityOrderedFactoryProcessors.Add(ObjectFactory.GetObject(factoryProcessorName, typeof(IObjectFactoryPostProcessor)));
+ }
+ }
+ }
+ // Second, invoke newly discovered IObjectFactoryPostProcessors that implement IPriorityOrdered.
+ priorityOrderedFactoryProcessors.Sort(new OrderComparator());
+ InvokeObjectFactoryPostProcessors(priorityOrderedFactoryProcessors, ObjectFactory);
+ }
+
+ private void InvokeObjectFactoryPostProcessors(IList objectFactoryPostProcessors, IConfigurableListableObjectFactory objectFactory)
{
foreach (IObjectFactoryPostProcessor processor in objectFactoryPostProcessors)
{
- processor.PostProcessObjectFactory(ObjectFactory);
+ processor.PostProcessObjectFactory(objectFactory);
}
}
diff --git a/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs b/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
index 20ff9f92..09203f0f 100644
--- a/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
+++ b/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
@@ -1,19 +1,19 @@
#region License
-/*
- * Copyright 2002-2004 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.
+/*
+ * Copyright 2002-2004 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
diff --git a/src/Spring/Spring.Core/Core/IPriorityOrdered.cs b/src/Spring/Spring.Core/Core/IPriorityOrdered.cs
new file mode 100644
index 00000000..6781bb3b
--- /dev/null
+++ b/src/Spring/Spring.Core/Core/IPriorityOrdered.cs
@@ -0,0 +1,51 @@
+#region License
+
+/*
+ * Copyright 2002-2010 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
+
+using Spring.Context;
+using Spring.Objects.Factory.Config;
+
+namespace Spring.Core
+{
+ ///
+ /// Extension of the interface, expressing a 'priority'
+ /// ordering: Order values expressed by IPriorityOrdered objects always
+ /// apply before order values of 'plain' Ordered values.
+ ///
+ ///
+ /// This is primarily a special-purpose interface, used for objects
+ /// where it is particularly important to determine 'prioritized'
+ /// objects first, without even obtaining the remaining objects.
+ /// A typical example: Prioritized post-processors in a Spring
+ ///
+ ///
+ /// IPriorityOrdered post-processor objects are initialized in
+ /// a special phase, ahead of other post-processor objects.
+ ///
+ /// Juergen Hoeller
+ /// Mark Pollack (.NET)
+ ///
+ ///
+ ///
+ public interface IPriorityOrdered : IOrdered
+ {
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/AbstractConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/AbstractConfigurer.cs
index 1db97716..c71cb191 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/AbstractConfigurer.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/AbstractConfigurer.cs
@@ -31,7 +31,7 @@ namespace Spring.Objects.Factory.Config
///
/// Mark Pollack
[Serializable]
- public abstract class AbstractConfigurer : IOrdered, IObjectFactoryPostProcessor
+ public abstract class AbstractConfigurer : IPriorityOrdered, IObjectFactoryPostProcessor
{
private int order = Int32.MaxValue; // default: same as non-Ordered
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/CommandLineArgsVariableSource.cs b/src/Spring/Spring.Core/Objects/Factory/Config/CommandLineArgsVariableSource.cs
index e720f8f1..04f31f5c 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/CommandLineArgsVariableSource.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/CommandLineArgsVariableSource.cs
@@ -39,7 +39,9 @@ namespace Spring.Objects.Factory.Config
private string valueSeparator = DEFAULT_VALUE_SEPARATOR;
private string[] commandLineArgs;
- private IDictionary arguments;
+ protected IDictionary arguments;
+
+ private object objectMonitor = new object();
///
/// Default constructor.
@@ -95,11 +97,14 @@ namespace Spring.Objects.Factory.Config
/// true if the variable can be resolved, false otherwise
public bool CanResolveVariable(string name)
{
- if (arguments == null)
+ lock (objectMonitor)
{
- InitArguments();
- }
- return arguments.Contains(name);
+ if (arguments == null)
+ {
+ InitArguments();
+ }
+ return arguments.Contains(name);
+ }
}
///
@@ -112,18 +117,21 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, null otherwise.
///
public string ResolveVariable(string name)
- {
- if (arguments == null)
- {
- InitArguments();
+ {
+ lock (objectMonitor)
+ {
+ if (arguments == null)
+ {
+ InitArguments();
+ }
+ return (string) this.arguments[name];
}
- return (string) this.arguments[name];
}
///
/// Initializes command line arguments dictionary.
///
- private void InitArguments()
+ protected virtual void InitArguments()
{
this.arguments = CollectionsUtil.CreateCaseInsensitiveHashtable(commandLineArgs.Length);
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/ConfigSectionVariableSource.cs b/src/Spring/Spring.Core/Objects/Factory/Config/ConfigSectionVariableSource.cs
index 02e44559..193dc4ab 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/ConfigSectionVariableSource.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/ConfigSectionVariableSource.cs
@@ -35,7 +35,8 @@ namespace Spring.Objects.Factory.Config
public class ConfigSectionVariableSource : IVariableSource
{
private string[] sectionNames;
- private NameValueCollection variables;
+ protected NameValueCollection variables;
+ private readonly object objectMonitor = new object();
///
/// Initializes a new instance of
@@ -100,11 +101,15 @@ namespace Spring.Objects.Factory.Config
/// true if the variable can be resolved, false otherwise
public bool CanResolveVariable(string name)
{
- if (variables == null)
+ lock (objectMonitor)
{
- InitVariables();
- }
- return CollectionUtils.Contains(variables.AllKeys, name);
+ if (variables == null)
+ {
+ variables = new NameValueCollection();
+ InitVariables();
+ }
+ return CollectionUtils.Contains(variables.AllKeys, name);
+ }
}
///
@@ -117,21 +122,24 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, null otherwise.
///
public string ResolveVariable(string name)
- {
- if (variables == null)
- {
- InitVariables();
- }
- return variables.Get(name);
+ {
+ lock (objectMonitor)
+ {
+ if (variables == null)
+ {
+ variables = new NameValueCollection();
+ InitVariables();
+ }
+ return variables.Get(name);
+ }
}
///
/// Initializes properties based on the specified
/// property file locations.
///
- private void InitVariables()
- {
- variables = new NameValueCollection();
+ protected virtual void InitVariables()
+ {
foreach (string sectionName in sectionNames)
{
object section = ConfigurationUtils.GetSection(sectionName);
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyFileVariableSource.cs b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyFileVariableSource.cs
index e4267ed5..e487714b 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyFileVariableSource.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyFileVariableSource.cs
@@ -19,7 +19,6 @@
#endregion
using System;
-using System.Collections;
using System.IO;
using Spring.Core.IO;
using Spring.Util;
@@ -36,7 +35,9 @@ namespace Spring.Objects.Factory.Config
public class PropertyFileVariableSource : IVariableSource
{
private IResource[] locations;
- private Properties properties;
+ protected Properties properties;
+ private readonly object objectMonitor = new object();
+ private bool ignoreMissingResources;
///
/// Gets or sets the locations of the property files
@@ -62,6 +63,18 @@ namespace Spring.Objects.Factory.Config
public IResource Location
{
set { locations = new IResource[] { value} ;}
+ }
+
+ ///
+ /// Sets a value indicating whether to ignore resource locations that do not exist. This will call
+ /// the Exists property.
+ ///
+ ///
+ /// true if one should ignore missing resources; otherwise, false.
+ ///
+ public bool IgnoreMissingResources
+ {
+ set { ignoreMissingResources = value; }
}
///
@@ -72,11 +85,15 @@ namespace Spring.Objects.Factory.Config
/// true if the variable can be resolved, false otherwise
public bool CanResolveVariable(string name)
{
- if (properties == null)
+ lock (objectMonitor)
{
- InitProperties();
- }
- return properties.Contains(name);
+ if (properties == null)
+ {
+ properties = new Properties();
+ InitProperties();
+ }
+ return properties.Contains(name);
+ }
}
///
@@ -89,28 +106,36 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, null otherwise.
///
public string ResolveVariable(string name)
- {
- if (properties == null)
- {
- InitProperties();
+ {
+ lock (objectMonitor)
+ {
+ if (properties == null)
+ {
+ properties = new Properties();
+ InitProperties();
+ }
+ return properties.GetProperty(name);
}
- return properties.GetProperty(name);
}
///
/// Initializes properties based on the specified
/// property file locations.
///
- private void InitProperties()
- {
- properties = new Properties();
- foreach (IResource location in locations)
- {
- using (Stream input = location.InputStream)
- {
- properties.Load(input);
- }
- }
+ protected virtual void InitProperties()
+ {
+ foreach (IResource location in locations)
+ {
+ bool exists = location.Exists;
+ if (!exists && ignoreMissingResources)
+ {
+ continue;
+ }
+ using (Stream input = location.InputStream)
+ {
+ properties.Load(input);
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/RegistryVariableSource.cs b/src/Spring/Spring.Core/Objects/Factory/Config/RegistryVariableSource.cs
index 05c21b8b..326c4e96 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/RegistryVariableSource.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/RegistryVariableSource.cs
@@ -69,7 +69,7 @@ namespace Spring.Objects.Factory.Config
///
/// The variable value if able to resolve, null otherwise.
///
- public string ResolveVariable(string name)
+ public virtual string ResolveVariable(string name)
{
object res = Key.GetValue(name);
if (res is string)
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs
index a4e75065..61f23a4b 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs
@@ -62,7 +62,7 @@ namespace Spring.Objects.Factory.Config
/// will be thrown.
///
/// Mark Pollack
- public class VariablePlaceholderConfigurer : IObjectFactoryPostProcessor, IOrdered
+ public class VariablePlaceholderConfigurer : IObjectFactoryPostProcessor, IPriorityOrdered
{
///
/// The default placeholder prefix.
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs
index 5b802c5d..11c5f49d 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs
@@ -1025,7 +1025,7 @@ namespace Spring.Objects.Factory.Support
}
///
- /// Determines candidate constructors to use for the given bean, checking all registered
+ /// Determines candidate constructors to use for the given object, checking all registered
///
///
/// Raw type of the object.
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorInstantiationInfo.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorInstantiationInfo.cs
new file mode 100644
index 00000000..2eb85091
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorInstantiationInfo.cs
@@ -0,0 +1,63 @@
+#region License
+
+/*
+ * Copyright 2002-2010 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
+
+using System.Reflection;
+
+namespace Spring.Objects.Factory.Support
+{
+ ///
+ /// Collects information on the constructor to use to create the instance and the argument instances to pass into the
+ /// constructor.
+ ///
+ public class ConstructorInstantiationInfo
+ {
+ private ConstructorInfo constructorInfo;
+ private object[] argInstances;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The constructor info.
+ /// The arg instances.
+ public ConstructorInstantiationInfo(ConstructorInfo constructorInfo, object[] argInstances)
+ {
+ this.constructorInfo = constructorInfo;
+ this.argInstances = argInstances;
+ }
+
+ ///
+ /// Gets the constructor info.
+ ///
+ /// The constructor info.
+ public ConstructorInfo ConstructorInfo
+ {
+ get { return constructorInfo; }
+ }
+
+ ///
+ /// Gets the arg instances.
+ ///
+ /// The arg instances.
+ public object[] ArgInstances
+ {
+ get { return argInstances; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs
index 4802736f..3bd97303 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs
@@ -42,7 +42,7 @@ namespace Spring.Objects.Factory.Support
///
/// Juergen Hoeller
/// Mark Pollack
- internal class ConstructorResolver
+ public class ConstructorResolver
{
private readonly ILog log = LogManager.GetLogger(typeof(ConstructorResolver));
@@ -89,8 +89,42 @@ namespace Spring.Objects.Factory.Support
public IObjectWrapper AutowireConstructor(string objectName, RootObjectDefinition rod,
ConstructorInfo[] chosenCtors, object[] explicitArgs)
{
+
ObjectWrapper wrapper = new ObjectWrapper();
+ ConstructorInstantiationInfo constructorInstantiationInfo = GetConstructorInstantiationInfo(
+ objectName, rod, chosenCtors, explicitArgs);
+
+ wrapper.WrappedInstance = instantiationStrategy.Instantiate(rod, objectName, this.objectFactory,
+ constructorInstantiationInfo.ConstructorInfo, constructorInstantiationInfo.ArgInstances);
+
+ #region Instrumentation
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(string.Format(CultureInfo.InvariantCulture, "Object '{0}' instantiated via constructor [{1}].", objectName, constructorInstantiationInfo.ConstructorInfo));
+ }
+
+ #endregion
+
+ return wrapper;
+ }
+
+
+ ///
+ /// Gets the constructor instantiation info given the object definition.
+ ///
+ /// Name of the object.
+ /// The RootObjectDefinition
+ /// The explicitly chosen ctors.
+ /// The explicit chose ctor args.
+ /// A ConstructorInstantiationInfo containg the specified constructor in the RootObjectDefinition or
+ /// one based on type matching.
+ public ConstructorInstantiationInfo GetConstructorInstantiationInfo(string objectName, RootObjectDefinition rod,
+ ConstructorInfo[] chosenCtors, object[] explicitArgs)
+ {
+
+ ObjectWrapper wrapper = new ObjectWrapper();
ConstructorInfo constructorToUse = null;
object[] argsToUse = null;
@@ -198,19 +232,9 @@ namespace Spring.Objects.Factory.Support
throw new ObjectCreationException(rod.ResourceDescription, objectName, "Could not resolve matching constructor.");
}
- wrapper.WrappedInstance = instantiationStrategy.Instantiate(rod, objectName, this.objectFactory, constructorToUse, argsToUse);
-
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format(CultureInfo.InvariantCulture, "Object '{0}' instantiated via constructor [{1}].", objectName, constructorToUse));
- }
-
- #endregion
-
- return wrapper;
+ return new ConstructorInstantiationInfo(constructorToUse, argsToUse);
+
}
///
@@ -636,7 +660,5 @@ namespace Spring.Objects.Factory.Support
}
}
}
-
-
}
diff --git a/src/Spring/Spring.Core/Spring.Core.2003.csproj b/src/Spring/Spring.Core/Spring.Core.2003.csproj
index 19a35adc..38dcc43d 100644
--- a/src/Spring/Spring.Core/Spring.Core.2003.csproj
+++ b/src/Spring/Spring.Core/Spring.Core.2003.csproj
@@ -342,6 +342,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
+
+
+
Code
+
Code
@@ -253,6 +254,7 @@
Code
+
@@ -260,6 +262,7 @@
+
@@ -681,6 +684,7 @@
+
diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj
index eac21748..478fcb42 100644
--- a/src/Spring/Spring.Core/Spring.Core.2008.csproj
+++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj
@@ -274,6 +274,7 @@
+
@@ -690,6 +691,7 @@
+
diff --git a/src/Spring/Spring.Services/ServiceModel/ServiceExporter.cs b/src/Spring/Spring.Services/ServiceModel/ServiceExporter.cs
index be040197..7cebdd51 100644
--- a/src/Spring/Spring.Services/ServiceModel/ServiceExporter.cs
+++ b/src/Spring/Spring.Services/ServiceModel/ServiceExporter.cs
@@ -27,7 +27,7 @@ using System.Reflection;
using System.Reflection.Emit;
using System.ServiceModel;
using System.Net.Security;
-
+using Spring.Objects.Factory.Config;
using Spring.Util;
using Spring.Context;
using Spring.Core.TypeResolution;
@@ -76,7 +76,7 @@ namespace Spring.ServiceModel
///
/// The owning factory.
///
- protected IObjectFactory objectFactory;
+ protected DefaultListableObjectFactory objectFactory;
///
/// The generated WCF service wrapper type.
@@ -260,7 +260,17 @@ namespace Spring.ServiceModel
///
public virtual IObjectFactory ObjectFactory
{
- set { this.objectFactory = value; }
+ set
+ {
+ if (value is DefaultListableObjectFactory)
+ {
+ this.objectFactory = (DefaultListableObjectFactory)value;
+ } else
+ {
+ //TODO verify type of exception thrown
+ throw new ArgumentException("ObjectFactory must of type DefaultListableObjectFactory");
+ }
+ }
}
#endregion
@@ -368,7 +378,7 @@ namespace Spring.ServiceModel
{
IProxyTypeBuilder builder = new ConfigurableServiceProxyTypeBuilder(
TargetName, objectFactory.GetType(TargetName), this.objectName, _useServiceProxyTypeCache,
- Name, Namespace, ConfigurationName, CallbackContract, ProtectionLevel, SessionMode);
+ Name, Namespace, ConfigurationName, CallbackContract, ProtectionLevel, SessionMode, this.objectFactory);
if (ContractInterface != null)
{
@@ -397,12 +407,12 @@ namespace Spring.ServiceModel
private sealed class ConfigurableServiceProxyTypeBuilder : ServiceProxyTypeBuilder
{
private CustomAttributeBuilder serviceContractAttribute;
+ private DefaultListableObjectFactory objectFactory;
- public ConfigurableServiceProxyTypeBuilder(string targetName, Type targetType, string objectName, bool useServiceProxyTypeCache,
- string name, string ns, string configurationName, Type callbackContract, ProtectionLevel protectionLevel, SessionMode sessionMode)
+ public ConfigurableServiceProxyTypeBuilder(string targetName, Type targetType, string objectName, bool useServiceProxyTypeCache, string name, string ns, string configurationName, Type callbackContract, ProtectionLevel protectionLevel, SessionMode sessionMode, DefaultListableObjectFactory objectFactory)
: base(targetName, targetType, objectName, useServiceProxyTypeCache)
{
-
+ this.objectFactory = objectFactory;
if (!StringUtils.HasText(configurationName))
{
name = this.Interfaces[0].Name;
@@ -499,6 +509,84 @@ namespace Spring.ServiceModel
return proxiableInterfaces;
}
+
+ ///
+ /// Applies attributes to the proxy class.
+ ///
+ /// The type builder to use.
+ /// The proxied class.
+ ///
+ ///
+ protected override void ApplyTypeAttributes(TypeBuilder typeBuilder, Type targetType)
+ {
+ foreach (object attr in GetTypeAttributes(targetType))
+ {
+ if (attr is CustomAttributeBuilder)
+ {
+ typeBuilder.SetCustomAttribute((CustomAttributeBuilder)attr);
+ }
+#if NET_2_0
+ else if (attr is CustomAttributeData)
+ {
+ typeBuilder.SetCustomAttribute(
+ ReflectionUtils.CreateCustomAttribute((CustomAttributeData)attr));
+ }
+#endif
+ else if (attr is Attribute)
+ {
+ typeBuilder.SetCustomAttribute(
+ ReflectionUtils.CreateCustomAttribute((Attribute)attr));
+ }
+ else if (attr is IObjectDefinition)
+ {
+ RootObjectDefinition objectDefinition = (RootObjectDefinition) attr;
+
+ //TODO check that object definition is for an Attribute type.
+
+ //Change object definition so it can be instantiated and make prototype scope.
+ objectDefinition.IsAbstract = false;
+ objectDefinition.IsSingleton = false;
+ string objectName = ObjectDefinitionReaderUtils.GenerateObjectName(objectDefinition, objectFactory);
+ objectFactory.RegisterObjectDefinition(objectName, objectDefinition);
+
+
+ //find constructor and constructor arg values to create this attribute.
+ ConstructorResolver constructorResolver = new ConstructorResolver(objectFactory, objectFactory,
+ new SimpleInstantiationStrategy(),
+ new ObjectDefinitionValueResolver(objectFactory));
+
+
+ ConstructorInstantiationInfo ci = constructorResolver.GetConstructorInstantiationInfo(objectName,
+ objectDefinition,
+ null, null);
+
+ if (objectDefinition.PropertyValues.PropertyValues.Length == 0)
+ {
+ CustomAttributeBuilder cab = new CustomAttributeBuilder(ci.ConstructorInfo,
+ ci.ArgInstances);
+ typeBuilder.SetCustomAttribute(cab);
+ }
+ else
+ {
+ object attributeInstance = objectFactory.GetObject(objectName);
+ IObjectWrapper wrappedAttributeInstance = new ObjectWrapper(attributeInstance);
+ PropertyInfo[] namedProperties = wrappedAttributeInstance.GetPropertyInfos();
+ object[] propertyValues = new object[namedProperties.Length];
+ for (int i = 0; i < namedProperties.Length; i++)
+ {
+ propertyValues[i] =
+ wrappedAttributeInstance.GetPropertyValue(namedProperties[i].Name);
+ }
+ CustomAttributeBuilder cab = new CustomAttributeBuilder(ci.ConstructorInfo, ci.ArgInstances,
+ namedProperties, propertyValues);
+ typeBuilder.SetCustomAttribute(cab);
+ }
+
+
+ }
+
+ }
+ }
}
#endregion
diff --git a/src/Spring/Spring.Web/Spring.Web.2003.csproj b/src/Spring/Spring.Web/Spring.Web.2003.csproj
index 5a4c2d03..d9360320 100644
--- a/src/Spring/Spring.Web/Spring.Web.2003.csproj
+++ b/src/Spring/Spring.Web/Spring.Web.2003.csproj
@@ -135,6 +135,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
Code
+
diff --git a/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Config/TypeAliases.xml b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Config/TypeAliases.xml
index df95671a..90bdb50c 100644
--- a/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Config/TypeAliases.xml
+++ b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Config/TypeAliases.xml
@@ -6,10 +6,26 @@
+
+
+
+
+
+
+
+
@@ -20,6 +36,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/ctor-args.xml b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/ctor-args.xml
new file mode 100644
index 00000000..b44d63f1
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/ctor-args.xml
@@ -0,0 +1,19 @@
+
+
+
+ Tests for list and map handling in an XML object definition file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyFileVariableSourceTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyFileVariableSourceTests.cs
index 7b7f62ee..0309671e 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyFileVariableSourceTests.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyFileVariableSourceTests.cs
@@ -18,7 +18,7 @@
#endregion
-#region Imports
+#region
using NUnit.Framework;
using Spring.Core.IO;
@@ -27,7 +27,7 @@ using Spring.Core.IO;
namespace Spring.Objects.Factory.Config
{
- ///
+ ///
/// Unit tests for the PropertyFileVariableSource class.
///
/// Aleksandar Seovic
@@ -50,17 +50,39 @@ namespace Spring.Objects.Factory.Config
Assert.IsNull(vs.ResolveVariable("dummy"));
}
+ [Test]
+ public void TestMissingResourceLocation()
+ {
+ PropertyFileVariableSource vs = new PropertyFileVariableSource();
+ vs.IgnoreMissingResources = true;
+ vs.Locations = new IResource[]
+ {
+ new AssemblyResource(
+ "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/non-existent.properties")
+ ,
+ new AssemblyResource(
+ "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/one.properties")
+ ,
+ };
+
+ // existing vars
+ Assert.AreEqual("Aleks Seovic", vs.ResolveVariable("name"));
+ Assert.AreEqual("32", vs.ResolveVariable("age"));
+ }
+
+
[Test]
public void TestVariablesResolutionWithTwoLocations()
{
PropertyFileVariableSource vs = new PropertyFileVariableSource();
vs.Locations = new IResource[]
- {
- new AssemblyResource(
- "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/one.properties"),
- new AssemblyResource(
- "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/two.properties")
- };
+ {
+ new AssemblyResource(
+ "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/one.properties")
+ ,
+ new AssemblyResource(
+ "assembly://Spring.Core.Tests/Spring.Data.Spring.Objects.Factory.Config/two.properties")
+ };
// existing vars
Assert.AreEqual("Aleksandar Seovic", vs.ResolveVariable("name")); // should be overriden by the second file
@@ -71,4 +93,4 @@ namespace Spring.Objects.Factory.Config
Assert.IsNull(vs.ResolveVariable("dummy"));
}
}
-}
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/TypeAliasConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/TypeAliasConfigurerTests.cs
index c4ed3aff..3e078070 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/TypeAliasConfigurerTests.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/TypeAliasConfigurerTests.cs
@@ -108,8 +108,7 @@ namespace Spring.Objects.Factory.Config
[Test]
public void WithinApplicationContext()
{
- IApplicationContext ctx = new XmlApplicationContext(
- "file://Spring/Objects/Factory/Config/typeAliases.xml");
+ IApplicationContext ctx = new XmlApplicationContext("file://Spring/Objects/Factory/Config/typeAliases.xml");
object obj1 = ctx.GetObject("testObject1");
Assert.IsNotNull(obj1);
@@ -131,6 +130,26 @@ namespace Spring.Objects.Factory.Config
Assert.AreEqual(typeof(TestObject), obj4.GetType());
Assert.AreEqual("Bruno", ((TestObject)obj4).Name);
Assert.AreEqual(30, ((TestObject)obj4).Age);
+
+
+ object obj6 = ctx.GetObject("testObject6");
+ Assert.IsNotNull(obj6);
+ Assert.AreEqual(typeof(TestObject), obj6.GetType());
+ Assert.AreEqual("name from section", ((TestObject)obj6).Name);
+ Assert.AreEqual(27, ((TestObject)obj6).Age);
+
+
+ object obj5 = ctx.GetObject("testObject5");
+ Assert.IsNotNull(obj5);
+ Assert.AreEqual(typeof(TestObject), obj5.GetType());
+ Assert.AreEqual("overide-name", ((TestObject)obj5).Name);
+ Assert.AreEqual(26, ((TestObject)obj5).Age);
+
+ object vpc = ctx.GetObject("vpc");
+ Assert.IsNotNull(vpc);
+ Assert.AreEqual(typeof(VariablePlaceholderConfigurer), vpc.GetType());
+
+
}
private void CreateConfigurerAndTestLinkedList(IDictionary typeAliases)
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs
index 36c32387..7c00612b 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs
@@ -55,6 +55,29 @@ namespace Spring.Objects.Factory.Xml
//XmlConfigurator.Configure();
}
+ [Test]
+ public void WalkThrough()
+ {
+ IResource resource = new ReadOnlyXmlTestResource("ctor-args.xml", GetType());
+ XmlObjectFactory xof = new XmlObjectFactory(resource);
+ TestObject rod = (TestObject)xof.GetObject("rod");
+ Assert.AreEqual(1, rod.Age);
+
+ RootObjectDefinition def = (RootObjectDefinition) xof.GetObjectDefinition("rod");
+ ConstructorResolver resolver = new ConstructorResolver(xof, xof, new SimpleInstantiationStrategy(),
+ new ObjectDefinitionValueResolver(xof));
+ ConstructorInstantiationInfo ci = resolver.GetConstructorInstantiationInfo("rod", def, null, null);
+
+ AbstractObjectDefinition objDef = (AbstractObjectDefinition)xof.GetObjectDefinition("foo");
+ objDef.IsAbstract = false;
+
+ TestObject foo = (TestObject) xof.GetObject("foo");
+
+
+ Assert.AreEqual(2, foo.Age);
+ }
+
+
[Test]
public void RefSubelementsBuildCollection()
{
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
index 018e0c24..e7e34207 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
@@ -821,6 +821,7 @@
+
@@ -860,7 +861,9 @@
-
+
+ Always
+
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll-1.1.config b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll-1.1.config
index ff0f0a9a..0699379e 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll-1.1.config
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll-1.1.config
@@ -28,6 +28,9 @@ limitations under the License.
+
+
+
@@ -58,8 +61,13 @@ limitations under the License.
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll.config b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll.config
index 4ec38fa9..d5fd00d0 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll.config
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.dll.config
@@ -19,7 +19,7 @@ limitations under the License.
-
+
@@ -32,6 +32,9 @@ limitations under the License.
+
+
+
@@ -62,8 +65,13 @@ limitations under the License.
+
+
+
+
+
@@ -185,7 +193,7 @@ limitations under the License.
-
+
diff --git a/test/Spring/Spring.Messaging.Nms.Integration.Tests/Messaging/Nms/Core/NmsTemplateTests.cs b/test/Spring/Spring.Messaging.Nms.Integration.Tests/Messaging/Nms/Core/NmsTemplateTests.cs
index e7ec90b1..6895ea55 100644
--- a/test/Spring/Spring.Messaging.Nms.Integration.Tests/Messaging/Nms/Core/NmsTemplateTests.cs
+++ b/test/Spring/Spring.Messaging.Nms.Integration.Tests/Messaging/Nms/Core/NmsTemplateTests.cs
@@ -18,7 +18,9 @@
#endregion
+using System;
using Apache.NMS;
+using Apache.NMS.ActiveMQ;
using NUnit.Framework;
using Spring.Testing.NUnit;
@@ -41,6 +43,14 @@ namespace Spring.Messaging.Nms.Core
this.PopulateProtectedVariables = true;
}
+ [Test]
+ public void ConnectionThrowException()
+ {
+ ConnectionFactory cf = new ConnectionFactory();
+ cf.BrokerUri = new Uri("tcp://localaaahost:61616");
+ IConnection c = cf.CreateConnection();
+ }
+
[Test]
public void ConvertAndSend()
diff --git a/test/Spring/Spring.Messaging.Tests/Spring.Messaging.Tests.2005.csproj b/test/Spring/Spring.Messaging.Tests/Spring.Messaging.Tests.2005.csproj
index 0ed0f81d..226e0bd1 100644
--- a/test/Spring/Spring.Messaging.Tests/Spring.Messaging.Tests.2005.csproj
+++ b/test/Spring/Spring.Messaging.Tests/Spring.Messaging.Tests.2005.csproj
@@ -86,6 +86,7 @@
+