From 4005e9eff6b0f02dbfd0e161d5e46e0189ab8721 Mon Sep 17 00:00:00 2001 From: Thomas Trageser Date: Sat, 23 Mar 2013 18:58:08 +0000 Subject: [PATCH] SPRNET-1543 Changed the default behaviour for GetObjectDefinionNames back to not include ancestors, added additional method that allows via bool parmeter to include parent factories. Other areas get the default inlucde where unit tests needed this options. Consumer of GetObjectDefinitionsNames are checked for potential NPE --- .../InheritanceBasedAopConfigurer.cs | 3 +- .../Support/AbstractApplicationContext.cs | 16 ++++- .../Config/ISingletonObjectRegistry.cs | 6 +- .../Config/PropertyPlaceholderConfigurer.cs | 20 ++++++- .../Config/VariablePlaceholderConfigurer.cs | 42 ++++++++----- .../Objects/Factory/IListableObjectFactory.cs | 12 +++- .../Objects/Factory/ObjectFactoryUtils.cs | 12 ++-- .../Factory/Support/AbstractObjectFactory.cs | 4 +- .../Support/DefaultListableObjectFactory.cs | 55 +++++++++-------- .../Support/IObjectDefinitionRegistry.cs | 16 ++++- .../Support/StaticListableObjectFactory.cs | 14 +++++ .../Support/ApplicationObjectSupportTests.cs | 5 ++ .../AbstractListableObjectFactoryTests.cs | 4 +- .../PropertyPlaceholderConfigurerTests.cs | 54 +++++++++++++---- .../VariablePlaceholderConfigurerTests.cs | 39 ++++++++++++ .../DefaultListableObjectFactoryTests.cs | 60 +++++++++++++++++++ .../Factory/ObjectFactoryUtilsTests.cs | 9 +-- .../Validation/HelperClasses.cs | 5 ++ 18 files changed, 295 insertions(+), 81 deletions(-) diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs index 3269320b..7c98814c 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs @@ -182,8 +182,7 @@ namespace Spring.Aop.Framework.AutoProxy string name = objectDefinitionNames[i]; if (IsObjectNameMatch(name)) { - IConfigurableObjectDefinition definition = - factory.GetObjectDefinition(name) as IConfigurableObjectDefinition; + var definition = factory.GetObjectDefinition(name) as IConfigurableObjectDefinition; if (definition == null || IsInfrastructureType(definition.ObjectType, name)) { diff --git a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs index 85944326..57776920 100644 --- a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs +++ b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs @@ -1338,7 +1338,21 @@ namespace Spring.Context.Support /// public IList GetObjectDefinitionNames() { - return ObjectFactory.GetObjectDefinitionNames(); + return GetObjectDefinitionNames(false); + } + + /// + /// Return the names of all objects defined in this factory, if includeAncestorsis true + /// includes all parent factories. + /// + /// to include parent factories into result + /// + /// The names of all objects defined in this factory, if includeAncestors is true includes all + /// objects defined in parent factories, or an empty array if none are defined. + /// + public IList GetObjectDefinitionNames(bool includeAncestors) + { + return ObjectFactory.GetObjectDefinitionNames(includeAncestors); } /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/ISingletonObjectRegistry.cs b/src/Spring/Spring.Core/Objects/Factory/Config/ISingletonObjectRegistry.cs index e1019486..311346ed 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/ISingletonObjectRegistry.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/ISingletonObjectRegistry.cs @@ -20,6 +20,8 @@ using System.Collections.Generic; +using Spring.Objects.Factory.Support; + namespace Spring.Objects.Factory.Config { /// @@ -138,8 +140,8 @@ namespace Spring.Objects.Factory.Config /// /// The list of names as String array (never null). /// - /// - /// + /// + /// IList SingletonNames { get; diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs index a0c862cd..13dd40e9 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs @@ -161,6 +161,7 @@ namespace Spring.Objects.Factory.Config private string placeholderPrefix = DefaultPlaceholderPrefix; private string placeholderSuffix = DefaultPlaceholderSuffix; private EnvironmentVariableMode environmentVariableMode = EnvironmentVariableMode.Fallback; + private bool includeAncestors; /// /// Initializes the new instance @@ -171,6 +172,7 @@ namespace Spring.Objects.Factory.Config } #region Properties + /// /// The placeholder prefix (the default is ${). /// @@ -214,6 +216,11 @@ namespace Spring.Objects.Factory.Config set { environmentVariableMode = value; } } + public bool IncludeAncestors + { + set { includeAncestors = value; } + } + #endregion /// @@ -233,12 +240,19 @@ namespace Spring.Objects.Factory.Config PlaceholderResolveHandlerAdapter resolveAdapter = new PlaceholderResolveHandlerAdapter(this, props); ObjectDefinitionVisitor visitor = new ObjectDefinitionVisitor(resolveAdapter.ParseAndResolveVariables); - IList objectDefinitionNames = factory.GetObjectDefinitionNames(); + IList objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); for (int i = 0; i < objectDefinitionNames.Count; ++i) { string name = objectDefinitionNames[i]; - IObjectDefinition definition = factory.GetObjectDefinition(name); - try + IObjectDefinition definition = factory.GetObjectDefinition(name, includeAncestors); + + if (definition == null) + { + logger.ErrorFormat("'{0}' can't be found in factorys' '{1}' object definition (includeAncestor {2})", name, factory, includeAncestors); + continue; + } + + try { visitor.VisitObjectDefinition(definition); } diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs index bbb18561..bdade2da 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs @@ -1,19 +1,19 @@ #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. +/* + * 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 @@ -79,6 +79,7 @@ namespace Spring.Objects.Factory.Config private int order = Int32.MaxValue; // default: same as non-Ordered + private bool includeAncestors; private bool ignoreUnresolvablePlaceholders; private string placeholderPrefix = DefaultPlaceholderPrefix; private string placeholderSuffix = DefaultPlaceholderSuffix; @@ -160,6 +161,11 @@ namespace Spring.Objects.Factory.Config set { ignoreUnresolvablePlaceholders = value; } } + public bool IncludeAncestors + { + set { includeAncestors = value; } + } + #endregion #region IObjectFactoryPostProcessor Members @@ -246,11 +252,15 @@ namespace Spring.Objects.Factory.Config TextProcessor tp = new TextProcessor(this, compositeVariableSource); ObjectDefinitionVisitor visitor = new ObjectDefinitionVisitor(new ObjectDefinitionVisitor.ResolveHandler(tp.ParseAndResolveVariables)); - IList objectDefinitionNames = factory.GetObjectDefinitionNames(); + IList objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); for (int i = 0; i < objectDefinitionNames.Count; ++i) { string name = objectDefinitionNames[i]; - IObjectDefinition definition = factory.GetObjectDefinition( name ); + IObjectDefinition definition = factory.GetObjectDefinition( name, includeAncestors ); + + if (definition == null) + continue; + try { visitor.VisitObjectDefinition( definition ); diff --git a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs index c7a832b6..98650096 100644 --- a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs @@ -96,6 +96,17 @@ namespace Spring.Objects.Factory /// IList GetObjectDefinitionNames(); + /// + /// Return the names of all objects defined in this factory, if includeAncestors is true + /// includes all parent factories. + /// + /// to include parent factories in result + /// + /// The names of all objects defined in this factory, if includeAncestors is true includes all + /// objects defined in parent factories, or an empty array if none are defined. + /// + IList GetObjectDefinitionNames(bool includeAncestors); + /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. @@ -121,7 +132,6 @@ namespace Spring.Objects.Factory /// IList GetObjectNamesForType(Type type); - /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. diff --git a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs index 99887898..41b8fe7c 100644 --- a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs @@ -142,7 +142,7 @@ namespace Spring.Objects.Factory /// If this isn't also an /// , /// this method will return the same as it's own - /// + /// /// method. /// /// @@ -197,11 +197,8 @@ namespace Spring.Objects.Factory ///

/// /// - /// If this isn't also an - /// , - /// this method will return the same as it's own - /// - /// method. + /// If this isn't also an , + /// this method will return the same as it's own method. /// /// /// The that objects must match. @@ -209,8 +206,7 @@ namespace Spring.Objects.Factory /// /// The array of object names, or an empty array if none. /// - public static IList ObjectNamesForTypeIncludingAncestors( - IListableObjectFactory factory, Type type) + public static IList ObjectNamesForTypeIncludingAncestors(IListableObjectFactory factory, Type type) { return factory.GetObjectNamesForType(type); } diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs index 4cd65361..2f47c01b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs @@ -2739,8 +2739,8 @@ namespace Spring.Objects.Factory.Support /// /// /// - /// - /// + /// + /// public IList SingletonNames { get diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs index f1504089..8f7083c7 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs @@ -181,7 +181,7 @@ namespace Spring.Objects.Factory.Support /// ///

/// Called by autowiring. If a subclass cannot obtain information about object - /// names by , a corresponding exception should be thrown. + /// -pnames by , a corresponding exception should be thrown. ///

///
/// @@ -275,31 +275,16 @@ namespace Spring.Objects.Factory.Support return (objectType != null && type.IsAssignableFrom(objectType)); } - private bool IsObjectDefinitionTypeMatch(string name, Type checkedType) + private bool IsObjectDefinitionTypeMatch(string name, Type checkedType, bool includeAncestor = false) { if (checkedType == null) { return true; } - RootObjectDefinition rod = GetMergedObjectDefinition(name, false); + RootObjectDefinition rod = GetMergedObjectDefinition(name, includeAncestor); return (rod.HasObjectType && checkedType.IsAssignableFrom(rod.ObjectType)); } - /* - /// - /// Merges the object definitions. - /// - /// Object definition name. - /// The parent definition. - /// The child definition. - /// Merged object definition. - protected override RootObjectDefinition MergeObjectDefinitions(string name, IObjectDefinition parentDefinition, - IObjectDefinition childDefinition) - { - RootObjectDefinition rootDefinition = base.MergeObjectDefinitions(name, parentDefinition, childDefinition); - RegisterObjectDefinition(name, rootDefinition); - return rootDefinition; - } - */ + #endregion #region Fields @@ -598,6 +583,7 @@ namespace Spring.Objects.Factory.Support #region IListableObjectFactory Members + /// /// Return the names of all objects defined in this factory. /// @@ -607,14 +593,28 @@ namespace Spring.Objects.Factory.Support /// /// public IList GetObjectDefinitionNames() + { + return GetObjectDefinitionNames(false); + } + + /// + /// Return the names of all objects defined in this factory, if includeAncestors is true + /// includes all parent factories. + /// + /// to include parent factories in result + /// + /// The names of all objects defined in this factory, if includeAncestors is true includes all + /// objects defined in parent factories, or an empty array if none are defined. + /// + public IList GetObjectDefinitionNames(bool includeAncestors) { IList results = new List(objectDefinitionNames); var listableObjectFactory = ParentObjectFactory as IListableObjectFactory; - if (listableObjectFactory != null) + if (includeAncestors && listableObjectFactory != null) { - foreach (var name in listableObjectFactory.GetObjectDefinitionNames()) + foreach (var name in listableObjectFactory.GetObjectDefinitionNames(includeAncestors)) { if (!results.Contains(name)) { @@ -640,16 +640,21 @@ namespace Spring.Objects.Factory.Support /// /// public IList GetObjectDefinitionNames(Type type) + { + return GetObjectDefinitionNames(type, false); + } + + public IList GetObjectDefinitionNames(Type type, bool includeAncestor) { List matches = new List(); - foreach (string name in objectDefinitionNames) + foreach (string name in GetObjectDefinitionNames(includeAncestor)) { - if (IsObjectDefinitionTypeMatch(name, type)) + if (IsObjectDefinitionTypeMatch(name, type, includeAncestor)) { matches.Add(name); } } - return matches; + return matches; } /// @@ -1013,7 +1018,7 @@ namespace Spring.Objects.Factory.Support protected List DoGetObjectNamesForType(Type type, bool includeNonSingletons, bool allowEagerInit) { List result = new List(); - IList objectNames = GetObjectDefinitionNames(); + IList objectNames = GetObjectDefinitionNames(true); foreach (string s in objectNames) { string objectName = s; diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs b/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs index 25ca92cc..e2eebc12 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs @@ -71,8 +71,20 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this registry, or an empty array /// if none defined /// - IList GetObjectDefinitionNames (); - + IList GetObjectDefinitionNames(); + + /// + /// Return the names of all objects defined in this registry. + /// If includeAncestors is true it includes all objects in the defined parent factories. + /// + /// to include parent factories in result + /// + /// The names of all objects defined in this registry, if includeAncestors is true it includes + /// all objects in the defined parent factories, or an empty array if none defined + /// + IList GetObjectDefinitionNames(bool includeAncestors); + + /// /// Check if this registry contains a object definition with the given name. /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs index 445fbd52..ec5b1295 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs @@ -557,6 +557,20 @@ namespace Spring.Objects.Factory.Support return names; } + /// + /// Return the names of all objects defined in this factory, if includeAncestors is true + /// includes all parent factories. + /// + /// to include parent factories in result + /// + /// The names of all objects defined in this factory, if includeAncestors is true includes all + /// objects defined in parent factories, or an empty array if none are defined. + /// + public IList GetObjectDefinitionNames(bool includeAncestors) + { + throw new NotSupportedException("StaticListableObjectFactory does not contain object definitions."); + } + /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs index b2141921..2294ad81 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs @@ -114,6 +114,11 @@ namespace Spring.Context.Support return null; } + public IList GetObjectDefinitionNames(bool includeAncestors) + { + return null; + } + public string[] GetObjectDefinitionNames(Type type) { return null; diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs index 6288fcdc..15d70b9e 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs @@ -63,7 +63,7 @@ namespace Spring.Objects.Factory { protected internal void AssertCount (int count) { - IList defnames = ListableObjectFactory.GetObjectDefinitionNames(); + IList defnames = ListableObjectFactory.GetObjectDefinitionNames(true); Assert.IsTrue ( defnames.Count == count, string.Format ("We should have {0} objects, not {1}.", count, defnames.Count)); @@ -78,7 +78,7 @@ namespace Spring.Objects.Factory { public virtual void AssertTestObjectCount (int count) { IList defnames = - ListableObjectFactory.GetObjectNamesForType (typeof (TestObject)); + ListableObjectFactory.GetObjectNamesForType(typeof (TestObject)); Assert.IsTrue ( defnames.Count == count, string.Format ("We should have {0} objects for class {1}, not {2}.", count, typeof (TestObject).FullName, defnames.Count)); diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs index 02e5a183..61549b9f 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs @@ -104,7 +104,7 @@ namespace Spring.Objects.Factory.Config cfg.Location = mockResource; cfg.ConfigSections = new string[] { "" }; IConfigurableListableObjectFactory mockFactory = (IConfigurableListableObjectFactory)mocks.DynamicMock(typeof(IConfigurableListableObjectFactory)); - Expect.Call(mockFactory.GetObjectDefinitionNames()).Return(new string[] {}); + Expect.Call(mockFactory.GetObjectDefinitionNames(false)).Return(new string[] {}); mocks.ReplayAll(); cfg.PostProcessObjectFactory(mockFactory); @@ -148,8 +148,8 @@ namespace Spring.Objects.Factory.Config RootObjectDefinition def = new RootObjectDefinition(typeof(TestObject), pvs); IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof(IConfigurableListableObjectFactory)); - Expect.Call(mock.GetObjectDefinitionNames()).Return(new string [] {defName}); - Expect.Call(mock.GetObjectDefinition(defName)).Return(def); + Expect.Call(mock.GetObjectDefinitionNames(false)).Return(new string [] {defName}); + Expect.Call(mock.GetObjectDefinition(defName, false)).Return(def); Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments(); mocks.ReplayAll(); @@ -165,6 +165,38 @@ namespace Spring.Objects.Factory.Config mocks.VerifyAll(); } + [Test] + public void IncludingAncestors() + { + const string defName = "foo"; + const string placeholder = "${name}"; + MutablePropertyValues pvs = new MutablePropertyValues(); + + + const string theProperty = "name"; + pvs.Add(theProperty, placeholder); + RootObjectDefinition def = new RootObjectDefinition(typeof(TestObject), pvs); + + IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory)mocks.CreateMock(typeof(IConfigurableListableObjectFactory)); + Expect.Call(mock.GetObjectDefinitionNames(true)).Return(new string[] { defName }); + Expect.Call(mock.GetObjectDefinition(defName, true)).Return(def); + Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments(); + mocks.ReplayAll(); + + PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); + cfg.IncludeAncestors = true; + + NameValueCollection defaultProperties = new NameValueCollection(); + const string expectedName = "Rick Evans"; + defaultProperties.Add(theProperty, expectedName); + cfg.Properties = defaultProperties; + cfg.PostProcessObjectFactory(mock); + Assert.AreEqual(expectedName, def.PropertyValues.GetPropertyValue(theProperty).Value, + "Property placeholder value was not replaced with the resolved value."); + + mocks.VerifyAll(); + } + /// /// Fallback is the default mode. Check if the PROCESSOR_ARCHITECTURE /// variable is replaced. @@ -390,8 +422,8 @@ namespace Spring.Objects.Factory.Config properties.Add("foo", expectedName); IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof (IConfigurableListableObjectFactory)); - Expect.Call(mock.GetObjectDefinitionNames()).Return(new string[] {"foo"}); - Expect.Call(mock.GetObjectDefinition(null)).IgnoreArguments().Return(def); + Expect.Call(mock.GetObjectDefinitionNames(false)).Return(new string[] {"foo"}); + Expect.Call(mock.GetObjectDefinition(null, false)).IgnoreArguments().Return(def); mocks.ReplayAll(); PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); @@ -421,8 +453,8 @@ namespace Spring.Objects.Factory.Config properties.Add("hope.floats", expectedName); IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof (IConfigurableListableObjectFactory)); - Expect.Call(mock.GetObjectDefinitionNames()).Return(new string[] {"foo"}); - Expect.Call(mock.GetObjectDefinition(null)).IgnoreArguments().Return(def); + Expect.Call(mock.GetObjectDefinitionNames(false)).Return(new string[] {"foo"}); + Expect.Call(mock.GetObjectDefinition(null, false)).IgnoreArguments().Return(def); Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments(); mocks.ReplayAll(); @@ -451,8 +483,8 @@ namespace Spring.Objects.Factory.Config properties.Add("hope.floats", expectedName); IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof (IConfigurableListableObjectFactory)); - Expect.Call(mock.GetObjectDefinitionNames()).Return(new string[] {"foo"}); - Expect.Call(mock.GetObjectDefinition(null)).IgnoreArguments().Return(def); + Expect.Call(mock.GetObjectDefinitionNames(false)).Return(new string[] {"foo"}); + Expect.Call(mock.GetObjectDefinition(null, false)).IgnoreArguments().Return(def); Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments(); mocks.ReplayAll(); @@ -549,8 +581,8 @@ namespace Spring.Objects.Factory.Config RootObjectDefinition def = new RootObjectDefinition(typeof(TestObject), pvs); IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof(IConfigurableListableObjectFactory)); - Expect.Call(mock.GetObjectDefinitionNames()).Return(new string [] {defName}); - Expect.Call(mock.GetObjectDefinition(defName)).Return(def); + Expect.Call(mock.GetObjectDefinitionNames(false)).Return(new string [] {defName}); + Expect.Call(mock.GetObjectDefinition(defName, false)).Return(def); Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments(); mocks.ReplayAll(); diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs index 508ff850..d56fec8d 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs @@ -20,7 +20,12 @@ using System; using System.Collections; +using System.Collections.Specialized; + using NUnit.Framework; + +using Rhino.Mocks; + using Spring.Context.Support; using Spring.Objects.Factory.Support; @@ -33,6 +38,13 @@ namespace Spring.Objects.Factory.Config [TestFixture] public class VariablePlaceholderConfigurerTests { + private MockRepository mocks; + + [SetUp] + public void SetUp() + { + mocks = new MockRepository(); + } [Test] public void ThrowsOnMissingVariableSources() @@ -276,5 +288,32 @@ namespace Spring.Objects.Factory.Config Assert.AreEqual("Erich", tb1.Name); Assert.AreEqual("${nickname}", tb1.Nickname); } + + [Test] + public void InlcludeAncestors() + { + const string defName = "foo"; + const string placeholder = "${name}"; + MutablePropertyValues pvs = new MutablePropertyValues(); + + + const string theProperty = "name"; + pvs.Add(theProperty, placeholder); + RootObjectDefinition def = new RootObjectDefinition(typeof(TestObject), pvs); + + IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory)mocks.CreateMock(typeof(IConfigurableListableObjectFactory)); + Expect.Call(mock.GetObjectDefinitionNames(true)).Return(new string[] { defName }); + Expect.Call(mock.GetObjectDefinition(defName, true)).Return(def); + mocks.ReplayAll(); + + VariablePlaceholderConfigurer vpc = new VariablePlaceholderConfigurer(); + vpc.IgnoreUnresolvablePlaceholders = true; + vpc.VariableSource = new DictionaryVariableSource(new string[] { "name", "Erich" }); + vpc.IncludeAncestors = true; + + vpc.PostProcessObjectFactory(mock); + + mocks.VerifyAll(); + } } } \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs index 94869bd5..b99c2f59 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs @@ -1773,6 +1773,66 @@ namespace Spring.Objects.Factory #endregion + [Test] + public void GetObjectDefinitionNamesOnlyFromChild() + { + DefaultListableObjectFactory parent = new DefaultListableObjectFactory(); + parent.RegisterObjectDefinition("testChild", new RootObjectDefinition(typeof(TestObject), null)); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(parent); + child.RegisterObjectDefinition("testParent", new RootObjectDefinition(typeof(NestedTestObject), null)); + + var names = child.GetObjectDefinitionNames(); + + Assert.That(names, Has.Count.EqualTo(1), "GetObjectDefinitionNames() should only return object definition names from this factory"); + + names = child.GetObjectDefinitionNames(false); + + Assert.That(names, Has.Count.EqualTo(1), "GetObjectDefinitionNames(false) should only return object definition names from this factory"); + } + + [Test] + public void GetObjectDefinitionNamesIncludingParent() + { + DefaultListableObjectFactory parent = new DefaultListableObjectFactory(); + parent.RegisterObjectDefinition("testChild", new RootObjectDefinition(typeof(TestObject), null)); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(parent); + child.RegisterObjectDefinition("testParent", new RootObjectDefinition(typeof(NestedTestObject), null)); + + var names = child.GetObjectDefinitionNames(true); + + Assert.That(names, Has.Count.EqualTo(2), "GetObjectDefinitionNames(true) should return object definition names from this factory and parents"); + } + + [Test] + public void GetObjectDefinitionNamesByTypeExcludingParent() + { + DefaultListableObjectFactory parent = new DefaultListableObjectFactory(); + parent.RegisterObjectDefinition("testChild", new RootObjectDefinition(typeof(TestObject), null)); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(parent); + child.RegisterObjectDefinition("testParent", new RootObjectDefinition(typeof(NestedTestObject), null)); + + var names1 = child.GetObjectDefinitionNames(typeof(NestedTestObject)); + var names2 = child.GetObjectDefinitionNames(typeof(TestObject)); + + Assert.That(names1, Has.Count.EqualTo(1), "Should return only child object definitions"); + Assert.That(names2, Has.Count.EqualTo(0), "Should not return the parent object definitions"); + } + + [Test] + public void GetObjectDefinitionNamesByTypeIncludingParent() + { + DefaultListableObjectFactory parent = new DefaultListableObjectFactory(); + parent.RegisterObjectDefinition("testChild", new RootObjectDefinition(typeof(TestObject), null)); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(parent); + child.RegisterObjectDefinition("testParent", new RootObjectDefinition(typeof(NestedTestObject), null)); + + var names1 = child.GetObjectDefinitionNames(typeof(NestedTestObject), true); + var names2 = child.GetObjectDefinitionNames(typeof(TestObject), true); + + Assert.That(names1, Has.Count.EqualTo(1), "Should return child object definitions"); + Assert.That(names2, Has.Count.EqualTo(1), "Should return the parent object definitions"); + } + [Test] public void GetObjectNamesForTypeFindsFactoryObjects() { diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs index 7f0aafe2..6328c212 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs @@ -46,12 +46,9 @@ namespace Spring.Objects.Factory [SetUp] public void SetUp() { - IObjectFactory grandparent - = new XmlObjectFactory(new ReadOnlyXmlTestResource("root.xml", GetType())); - IObjectFactory parent - = new XmlObjectFactory(new ReadOnlyXmlTestResource("middle.xml", GetType()), grandparent); - IConfigurableListableObjectFactory child - = new XmlObjectFactory(new ReadOnlyXmlTestResource("leaf.xml", GetType()), parent); + IObjectFactory grandparent = new XmlObjectFactory(new ReadOnlyXmlTestResource("root.xml", GetType())); + IObjectFactory parent = new XmlObjectFactory(new ReadOnlyXmlTestResource("middle.xml", GetType()), grandparent); + IConfigurableListableObjectFactory child = new XmlObjectFactory(new ReadOnlyXmlTestResource("leaf.xml", GetType()), parent); _factory = child; } diff --git a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs index d77d56d2..fc7200aa 100644 --- a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs +++ b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs @@ -97,6 +97,11 @@ namespace Spring.Validation return new List(this.objects.Keys); } + public IList GetObjectDefinitionNames(bool includeAncestor) + { + return new List(this.objects.Keys); + } + public IList GetObjectDefinitions() { return new List(this.objects.Values);