SPRNET-1358 : Allow for ignoring of resources not found in PropertyFileVariableSource

SPRNET-1356 : Introduce IPriorityOrdered interface to ensure correct ordering among IObjectFactoryPostProcessors
SPRNET-1355 : TypeAlias usage with other IObjectFactoryPostProcessor object definitions not working.

work started on SPRNET-1262 

fix 2003/2005 solution builds
This commit is contained in:
markpollack
2010-08-19 14:56:55 +00:00
parent e793a01220
commit 2aee3148ca
29 changed files with 615 additions and 118 deletions

View File

@@ -5028,13 +5028,22 @@ cfg.PostProcessObjectFactory(factory);</programlisting></para>
value will be used. <programlisting language="myxml">&lt;object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core"&gt;
&lt;property name="VariableSources"&gt;
&lt;list&gt;
&lt;object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core"&gt;
&lt;property name="Location" value="~\application.properties" /&gt;
&lt;property name="IgnoreMissingResources" value="true"/&gt;
&lt;/object&gt;
&lt;object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"&gt;
&lt;property name="SectionNames" value="CryptedConfiguration" /&gt;
&lt;/object&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/object&gt;
</programlisting>The IVariableSource interface is shown below</para>
</programlisting><note>
<para>The use of the <property>IgnoreMissingResources</property>
property above will mean that if the property file is not found it
will be silently ignored and the resolution will continue to
<classname>ConfigSectionVariableSource</classname>. </para>
</note>The IVariableSource interface is shown below</para>
<programlisting language="csharp">public interface IVariableSource
{

View File

@@ -489,31 +489,57 @@ namespace Spring.Context.Support
/// <exception cref="ObjectsException">In the case of errors.</exception>
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);
}
}

View File

@@ -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

View File

@@ -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
{
/// <summary>
/// Extension of the <see cref="IOrdered"/> interface, expressing a 'priority'
/// ordering: Order values expressed by IPriorityOrdered objects always
/// apply before order values of 'plain' Ordered values.
/// </summary>
/// <remarks>
/// <para>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
/// <see cref="IApplicationContext"/>
/// </para>
/// <para>IPriorityOrdered post-processor objects are initialized in
/// a special phase, ahead of other post-processor objects.</para>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
/// <see cref="VariablePlaceholderConfigurer"/>
/// <see cref="TypeAliasConfigurer"/>
/// <see cref="ResourceHandlerConfigurer"/>
public interface IPriorityOrdered : IOrdered
{
}
}

View File

@@ -31,7 +31,7 @@ namespace Spring.Objects.Factory.Config
/// </summary>
/// <author>Mark Pollack</author>
[Serializable]
public abstract class AbstractConfigurer : IOrdered, IObjectFactoryPostProcessor
public abstract class AbstractConfigurer : IPriorityOrdered, IObjectFactoryPostProcessor
{
private int order = Int32.MaxValue; // default: same as non-Ordered

View File

@@ -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();
/// <summary>
/// Default constructor.
@@ -95,11 +97,14 @@ namespace Spring.Objects.Factory.Config
/// <returns><c>true</c> if the variable can be resolved, <c>false</c> otherwise</returns>
public bool CanResolveVariable(string name)
{
if (arguments == null)
lock (objectMonitor)
{
InitArguments();
}
return arguments.Contains(name);
if (arguments == null)
{
InitArguments();
}
return arguments.Contains(name);
}
}
/// <summary>
@@ -112,18 +117,21 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, <c>null</c> otherwise.
/// </returns>
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];
}
/// <summary>
/// Initializes command line arguments dictionary.
/// </summary>
private void InitArguments()
protected virtual void InitArguments()
{
this.arguments = CollectionsUtil.CreateCaseInsensitiveHashtable(commandLineArgs.Length);

View File

@@ -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();
/// <summary>
/// Initializes a new instance of <see cref="ConfigSectionVariableSource"/>
@@ -100,11 +101,15 @@ namespace Spring.Objects.Factory.Config
/// <returns><c>true</c> if the variable can be resolved, <c>false</c> otherwise</returns>
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);
}
}
/// <summary>
@@ -117,21 +122,24 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, <c>null</c> otherwise.
/// </returns>
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);
}
}
/// <summary>
/// Initializes properties based on the specified
/// property file locations.
/// </summary>
private void InitVariables()
{
variables = new NameValueCollection();
protected virtual void InitVariables()
{
foreach (string sectionName in sectionNames)
{
object section = ConfigurationUtils.GetSection(sectionName);

View File

@@ -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;
/// <summary>
/// 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} ;}
}
/// <summary>
/// Sets a value indicating whether to ignore resource locations that do not exist. This will call
/// the <see cref="IResource"/> Exists property.
/// </summary>
/// <value>
/// <c>true</c> if one should ignore missing resources; otherwise, <c>false</c>.
/// </value>
public bool IgnoreMissingResources
{
set { ignoreMissingResources = value; }
}
/// <summary>
@@ -72,11 +85,15 @@ namespace Spring.Objects.Factory.Config
/// <returns><c>true</c> if the variable can be resolved, <c>false</c> otherwise</returns>
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);
}
}
/// <summary>
@@ -89,28 +106,36 @@ namespace Spring.Objects.Factory.Config
/// The variable value if able to resolve, <c>null</c> otherwise.
/// </returns>
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);
}
/// <summary>
/// Initializes properties based on the specified
/// property file locations.
/// </summary>
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);
}
}
}
}
}

View File

@@ -69,7 +69,7 @@ namespace Spring.Objects.Factory.Config
/// <returns>
/// The variable value if able to resolve, <c>null</c> otherwise.
/// </returns>
public string ResolveVariable(string name)
public virtual string ResolveVariable(string name)
{
object res = Key.GetValue(name);
if (res is string)

View File

@@ -62,7 +62,7 @@ namespace Spring.Objects.Factory.Config
/// will be thrown. </para>
/// </remarks>
/// <author>Mark Pollack</author>
public class VariablePlaceholderConfigurer : IObjectFactoryPostProcessor, IOrdered
public class VariablePlaceholderConfigurer : IObjectFactoryPostProcessor, IPriorityOrdered
{
/// <summary>
/// The default placeholder prefix.

View File

@@ -1025,7 +1025,7 @@ namespace Spring.Objects.Factory.Support
}
/// <summary>
/// Determines candidate constructors to use for the given bean, checking all registered
/// Determines candidate constructors to use for the given object, checking all registered
/// <see cref="SmartInstantiationAwareObjectPostProcessor"/>
/// </summary>
/// <param name="objectType">Raw type of the object.</param>

View File

@@ -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
{
/// <summary>
/// Collects information on the constructor to use to create the instance and the argument instances to pass into the
/// constructor.
/// </summary>
public class ConstructorInstantiationInfo
{
private ConstructorInfo constructorInfo;
private object[] argInstances;
/// <summary>
/// Initializes a new instance of the <see cref="ConstructorInstantiationInfo"/> class.
/// </summary>
/// <param name="constructorInfo">The constructor info.</param>
/// <param name="argInstances">The arg instances.</param>
public ConstructorInstantiationInfo(ConstructorInfo constructorInfo, object[] argInstances)
{
this.constructorInfo = constructorInfo;
this.argInstances = argInstances;
}
/// <summary>
/// Gets the constructor info.
/// </summary>
/// <value>The constructor info.</value>
public ConstructorInfo ConstructorInfo
{
get { return constructorInfo; }
}
/// <summary>
/// Gets the arg instances.
/// </summary>
/// <value>The arg instances.</value>
public object[] ArgInstances
{
get { return argInstances; }
}
}
}

View File

@@ -42,7 +42,7 @@ namespace Spring.Objects.Factory.Support
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack</author>
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;
}
/// <summary>
/// Gets the constructor instantiation info given the object definition.
/// </summary>
/// <param name="objectName">Name of the object.</param>
/// <param name="rod">The RootObjectDefinition</param>
/// <param name="chosenCtors">The explicitly chosen ctors.</param>
/// <param name="explicitArgs">The explicit chose ctor args.</param>
/// <returns>A ConstructorInstantiationInfo containg the specified constructor in the RootObjectDefinition or
/// one based on type matching.</returns>
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);
}
/// <summary>
@@ -636,7 +660,5 @@ namespace Spring.Objects.Factory.Support
}
}
}
}

View File

@@ -342,6 +342,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\Support\AbstractXmlApplicationContextArgs.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\Support\ApplicationContextAwareProcessor.cs"
SubType = "Code"
@@ -437,6 +442,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\Support\XmlApplicationContextArgs.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Core\CannotLoadObjectTypeException.cs"
SubType = "Code"
@@ -487,6 +497,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Core\IPriorityOrdered.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Core\MethodArgumentsCriteria.cs"
SubType = "Code"
@@ -2390,6 +2405,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Objects\Factory\Support\ConstructorInstantiationInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Objects\Factory\Support\ConstructorResolver.cs"
SubType = "Code"

View File

@@ -202,6 +202,7 @@
<Compile Include="Context\Support\AbstractXmlApplicationContext.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Context\Support\AbstractXmlApplicationContextArgs.cs" />
<Compile Include="Context\Support\ApplicationContextAwareProcessor.cs">
<SubType>Code</SubType>
</Compile>
@@ -253,6 +254,7 @@
<Compile Include="Context\Support\XmlApplicationContext.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Context\Support\XmlApplicationContextArgs.cs" />
<Compile Include="Core\CannotLoadObjectTypeException.cs" />
<Compile Include="Core\ComposedCriteria.cs" />
<Compile Include="Core\ControlFlowFactory.cs">
@@ -260,6 +262,7 @@
</Compile>
<Compile Include="Core\Conventions.cs" />
<Compile Include="Core\IO\EncodedResource.cs" />
<Compile Include="Core\IPriorityOrdered.cs" />
<Compile Include="Core\MethodArgumentsCriteria.cs" />
<Compile Include="Core\IO\AbstractResource.cs" />
<Compile Include="Core\IO\AssemblyResource.cs" />
@@ -681,6 +684,7 @@
<Compile Include="Objects\Factory\Config\VariableAccessor.cs" />
<Compile Include="Objects\Factory\Config\VariablePlaceholderConfigurer.cs" />
<Compile Include="Objects\Factory\Parsing\ReaderContext.cs" />
<Compile Include="Objects\Factory\Support\ConstructorInstantiationInfo.cs" />
<Compile Include="Objects\Factory\Support\GenericObjectDefinition.cs" />
<Compile Include="Objects\Factory\Support\IAutowireCandidateResolver.cs" />
<Compile Include="Objects\Factory\Support\ConstructorResolver.cs" />

View File

@@ -274,6 +274,7 @@
</Compile>
<Compile Include="Core\Conventions.cs" />
<Compile Include="Core\IO\EncodedResource.cs" />
<Compile Include="Core\IPriorityOrdered.cs" />
<Compile Include="Core\MethodArgumentsCriteria.cs" />
<Compile Include="Core\IO\AbstractResource.cs" />
<Compile Include="Core\IO\AssemblyResource.cs" />
@@ -690,6 +691,7 @@
<Compile Include="Objects\Factory\Config\VariableAccessor.cs" />
<Compile Include="Objects\Factory\Config\VariablePlaceholderConfigurer.cs" />
<Compile Include="Objects\Factory\Parsing\ReaderContext.cs" />
<Compile Include="Objects\Factory\Support\ConstructorInstantiationInfo.cs" />
<Compile Include="Objects\Factory\Support\GenericObjectDefinition.cs" />
<Compile Include="Objects\Factory\Support\IAutowireCandidateResolver.cs" />
<Compile Include="Objects\Factory\Support\ConstructorResolver.cs" />

View File

@@ -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
/// <summary>
/// The owning factory.
/// </summary>
protected IObjectFactory objectFactory;
protected DefaultListableObjectFactory objectFactory;
/// <summary>
/// The generated WCF service wrapper type.
@@ -260,7 +260,17 @@ namespace Spring.ServiceModel
/// </exception>
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;
}
/// <summary>
/// Applies attributes to the proxy class.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="targetType">The proxied class.</param>
/// <see cref="IProxyTypeBuilder.ProxyTargetAttributes"/>
/// <see cref="IProxyTypeBuilder.TypeAttributes"/>
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

View File

@@ -135,6 +135,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\Support\WebApplicationContextArgs.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\Support\WebContextHandler.cs"
SubType = "Code"

View File

@@ -107,6 +107,7 @@
<Compile Include="Context\Support\WebApplicationContext.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Context\Support\WebApplicationContextArgs.cs" />
<Compile Include="Context\Support\WebContextHandler.cs" />
<Compile Include="Context\Support\WebSupportModule.cs" />
<Compile Include="Core\IO\WebResource.cs" />

View File

@@ -6,10 +6,26 @@
<dictionary>
<entry key="TestObject" value="Spring.Objects.TestObject, Spring.Core.Tests" />
<entry key="intAlias" value="System.Int32" />
<entry key="TVariablePlaceholderConfigurer" value="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core"/>
</dictionary>
</property>
</object>
<object id="vpc" type="TVariablePlaceholderConfigurer">
<property name="VariableSources">
<list>
<object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core">
<property name="SectionNames" value="PropertyPlaceholderConfigurerSectionTest" />
</object>
</list>
</property>
</object>
<object lazy-init="true" type="Spring.Objects.Factory.Config.PropertyOverrideConfigurer, Spring.Core">
<property name="Order" value="2000"/>
<property name="ConfigSections" value="${prop.override.section}" />
</object>
<object id="testObject1" type="TestObject"/>
<object id="baseTestObject" type="TestObject" abstract="true"/>
@@ -20,6 +36,18 @@
<constructor-arg name="age" value="26"/>
</object>
<object id="testObject5" type="TestObject">
<constructor-arg name="name" value="Joe"/>
<constructor-arg name="age" value="26"/>
</object>
<object id="testObject6" type="TestObject">
<constructor-arg name="name" value="${test.name.1}"/>
<constructor-arg name="age" value="27"/>
</object>
<!-- SPRNET-1119 -->
<object id="testObject4" type="TestObject">
<constructor-arg name="name" value="Bruno"/>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<objects xmlns="http://www.springframework.net">
<description>
Tests for list and map handling in an XML object definition file.
</description>
<object id="foo" type="Spring.Objects.TestObject, Spring.Core.Tests" abstract="true">
<constructor-arg index="0" value="foo"/>
<constructor-arg index="1" value="2"/>
</object>
<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
<constructor-arg index="0" value="rod"/>
<constructor-arg index="1" value="1"/>
</object>
</objects>

View File

@@ -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
{
/// <summary>
/// <summary>
/// Unit tests for the PropertyFileVariableSource class.
/// </summary>
/// <author>Aleksandar Seovic</author>
@@ -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"));
}
}
}
}

View File

@@ -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)

View File

@@ -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()
{

View File

@@ -821,6 +821,7 @@
<Content Include="Data\Spring\Objects\Factory\Xml\array-autowire.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMergingGeneric.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\collectionMerging.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\ctor-args.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\objectNameGeneration.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\simple-constructor-arg.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\expressions.xml" />
@@ -860,7 +861,9 @@
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithThreeRequiredPropertiesOmitted.xml" />
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithAllRequiredPropertiesProvided.xml" />
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithCustomAttribute.xml" />
<Content Include="Spring.Core.Tests.dll.config" />
<Content Include="Spring.Core.Tests.dll.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Resources\Spring.Context.Tests.de-AT.resx" />
<EmbeddedResource Include="Resources\Spring.Context.Tests.de.resx" />
<EmbeddedResource Include="Validation\ValidationNamespaceParserTests_WhenConfigFileIsNotValid.xml" />

View File

@@ -28,6 +28,9 @@ limitations under the License.
</sectionGroup>
<section name="PropertyPlaceholderConfigurerSectionTest" type="System.Configuration.NameValueSectionHandler"/>
<section name="PropertyOverideSectionTest" type="System.Configuration.NameValueSectionHandler"/>
<sectionGroup name='PropertyPlaceholderConfigurerSectionGroupTest'>
<section name="PropertyPlaceholderConfigurerSectionGroupTestSection" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
@@ -58,8 +61,13 @@ limitations under the License.
<PropertyPlaceholderConfigurerSectionTest>
<add key="test.name.1" value="name from section"/>
<add key="prop.override.section" value="PropertyOverideSectionTest"/>
</PropertyPlaceholderConfigurerSectionTest>
<PropertyOverideSectionTest>
<add key="testObject5.name" value="overide-name"/>
</PropertyOverideSectionTest>
<PropertyPlaceholderConfigurerSectionGroupTest>
<PropertyPlaceholderConfigurerSectionGroupTestSection>
<add key="test.name.2" value="name from sectiongroup/section"/>

View File

@@ -19,7 +19,7 @@ limitations under the License.
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
<section name="objects" type="Spring.Objects.Factory.Xml.ObjectFactorySectionHandler, Spring.Core" />
<section name="DaoConfiguration" type="System.Configuration.NameValueSectionHandler"/>
<section name="DatabaseConfiguration" type="System.Configuration.NameValueSectionHandler"/>
@@ -32,6 +32,9 @@ limitations under the License.
</sectionGroup>
<section name="PropertyPlaceholderConfigurerSectionTest" type="System.Configuration.NameValueSectionHandler"/>
<section name="PropertyOverideSectionTest" type="System.Configuration.NameValueSectionHandler"/>
<sectionGroup name='PropertyPlaceholderConfigurerSectionGroupTest'>
<section name="PropertyPlaceholderConfigurerSectionGroupTestSection" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
@@ -62,8 +65,13 @@ limitations under the License.
<PropertyPlaceholderConfigurerSectionTest>
<add key="test.name.1" value="name from section"/>
<add key="prop.override.section" value="PropertyOverideSectionTest"/>
</PropertyPlaceholderConfigurerSectionTest>
<PropertyOverideSectionTest>
<add key="testObject5.name" value="overide-name"/>
</PropertyOverideSectionTest>
<PropertyPlaceholderConfigurerSectionGroupTest>
<PropertyPlaceholderConfigurerSectionGroupTestSection>
<add key="test.name.2" value="name from sectiongroup/section"/>
@@ -185,7 +193,7 @@ limitations under the License.
<add name="mySqlDataSource" connectionString="mySqlServerConnectionString"/>
<add name="myOracleDataSource" connectionString="myOracleConnectionString" providerName="System.Data.OracleClient"/>
</connectionStrings>
<objects xmlns='http://www.springframework.net'>
<object name="foo" type="Spring.Objects.TestObject, Spring.Core.Tests" />
<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">

View File

@@ -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()

View File

@@ -86,6 +86,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Messaging\Core\MessageQueueMetadataCacheTests.cs" />
<Compile Include="Messaging\Core\MessageQueueUtils.cs" />
<Compile Include="Messaging\Core\ThreadingTests.cs" />
<Compile Include="Messaging\Listener\Adapter\MessageListenerAdapterTests.cs" />
<Compile Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.cs" />