diff --git a/src/Spring/Spring.Core/Context/Support/ContextRegistry.cs b/src/Spring/Spring.Core/Context/Support/ContextRegistry.cs index 8af8cb27..0cb4d4ab 100644 --- a/src/Spring/Spring.Core/Context/Support/ContextRegistry.cs +++ b/src/Spring/Spring.Core/Context/Support/ContextRegistry.cs @@ -27,6 +27,8 @@ using System.Configuration; using Common.Logging; using Spring.Context.Events; using Spring.Util; +using Spring.Objects.Factory; +using Spring.Objects.Factory.Support; #endregion @@ -102,6 +104,51 @@ namespace Spring.Context.Support get { return syncRoot; } } + private static void ConstructNestedDefaultContextName(IApplicationContext context) + { + IApplicationContext parent = context.ParentContext; + + Hashtable contexts = new Hashtable(); + + int contextIndex = 0; + + contexts.Add(contextIndex, context); + + while (parent != null) + { + contextIndex++; + contexts.Add(contextIndex, parent); + parent = parent.ParentContext; + } + + string prefix = string.Empty; + + for (int i = contextIndex; i > 0; i--) + { + IApplicationContext contextToUpdate = (IApplicationContext)contexts[i]; + + if (prefix != string.Empty) + prefix = string.Format("{0}/{1}", prefix, contextToUpdate.Name); + else + prefix = contextToUpdate.Name; + + } + + context.Name = string.Format("{0}/{1}", prefix, context.Name); + } + + private static void EnsureHierarchicalNameIfDefault(IApplicationContext context) + { + //if there is no parent context there is no change needed + if (context.ParentContext == null) + return; + + if (context.Name == AbstractApplicationContext.DefaultRootContextName) + ConstructNestedDefaultContextName(context); + + } + + /// /// Registers an instance of an /// . @@ -119,6 +166,9 @@ namespace Spring.Context.Support /// public static void RegisterContext(IApplicationContext context) { + + EnsureHierarchicalNameIfDefault(context); + lock (syncRoot) { if (instance.contextMap.Contains(context.Name)) diff --git a/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs b/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs index 87cf6146..a7dae679 100644 --- a/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs +++ b/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs @@ -254,9 +254,17 @@ namespace Spring.Context _mockName = name; factory = new DefaultListableObjectFactory(); // factory.AddObjectPostProcessor(new ApplicationContextAwareProcessor(this)); - } + } - public MockApplicationContext(string name, IApplicationContext parentContext) : base(name, true, parentContext) + /// + /// Initializes a new instance of the MockApplicationContext class. + /// + public MockApplicationContext(IApplicationContext parentContext) + { + factory = new DefaultListableObjectFactory(parentContext); + } + + public MockApplicationContext(string name, IApplicationContext parentContext) : base(name, true, parentContext) { _mockName = name; factory = new DefaultListableObjectFactory(GetInternalParentObjectFactory()); diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ContextRegistryTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ContextRegistryTests.cs index 4c204b5a..23ba7a03 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ContextRegistryTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ContextRegistryTests.cs @@ -249,6 +249,7 @@ namespace Spring.Context.Support ContextRegistry.RegisterContext(duplicate); } + [Test] public void RemovesContextFromRegistryWhenContextCloses() { @@ -259,5 +260,95 @@ namespace Spring.Context.Support appCtx.Dispose(); Assert.IsFalse(ContextRegistry.IsContextRegistered(appCtx.Name)); } + + [TestFixture] + public class WhenHierarchicalContextsAllHaveDefaultNames + { + private MockApplicationContext _parentContext; + private MockApplicationContext _childContext; + private MockApplicationContext _grandChildContext; + private MockApplicationContext _greatGrandChildContext; + + private string _expectedParentName; + private string _expectedChildName; + private string _expectedGrandChildName; + private string _expectedGreatGrandChildName; + + + [TestFixtureSetUp] + public void InitializeAllTests() + { + _expectedParentName = AbstractApplicationContext.DefaultRootContextName; + _expectedChildName = string.Format("{0}/{1}", _expectedParentName, AbstractApplicationContext.DefaultRootContextName); + _expectedGrandChildName = string.Format("{0}/{1}/{2}",_expectedParentName, _expectedChildName, AbstractApplicationContext.DefaultRootContextName); + _expectedGreatGrandChildName = string.Format("{0}/{1}/{2}/{3}",_expectedParentName, _expectedChildName, _expectedGrandChildName, AbstractApplicationContext.DefaultRootContextName); + } + + [SetUp] + public void Setup() + { + //ensure prior-registered contexts are removed + ContextRegistry.Clear(); + + _parentContext = new MockApplicationContext(); + _parentContext.MockName = "parent"; + + _childContext = new MockApplicationContext(_parentContext); + _childContext.MockName = "child"; + _childContext.ParentContext = _parentContext; + + _grandChildContext = new MockApplicationContext(_childContext); + _grandChildContext.MockName = "grandchild"; + _grandChildContext.ParentContext = _childContext; + + _greatGrandChildContext = new MockApplicationContext(_grandChildContext); + _greatGrandChildContext.MockName = "greatgrandchild"; + _greatGrandChildContext.ParentContext = _grandChildContext; + } + + + [Test] + public void RegisterContext_ConstructsNestedPathBasedNames_IfRegisterdInHierarchicalOrder() + { + ContextRegistry.RegisterContext(_parentContext); + ContextRegistry.RegisterContext(_childContext); + ContextRegistry.RegisterContext(_grandChildContext); + ContextRegistry.RegisterContext(_greatGrandChildContext); + + Assert.AreEqual(_expectedParentName, ContextRegistry.GetContext().Name); + Assert.AreEqual(_expectedChildName, ContextRegistry.GetContext(_expectedChildName).Name); + Assert.AreEqual(_expectedGrandChildName, ContextRegistry.GetContext(_expectedGrandChildName).Name); + Assert.AreEqual(_expectedGreatGrandChildName, ContextRegistry.GetContext(_expectedGreatGrandChildName).Name); + } + + [Test] + public void RegisterContext_ConstructsNestedPathBasedNames_IfRegisteringAMixOfDefaultAndExplicitNamedContexts() + { + //modify the expected names for the decendent contexts for this one test + string childContextInitialName = AbstractApplicationContext.DefaultRootContextName + "_CUSTOM"; + _expectedChildName = string.Format("{0}/{1}", _expectedParentName, childContextInitialName); + _expectedGrandChildName = string.Format("{0}/{1}/{2}", _expectedParentName, _expectedChildName, AbstractApplicationContext.DefaultRootContextName); + _expectedGreatGrandChildName = string.Format("{0}/{1}/{2}/{3}", _expectedParentName, _expectedChildName, _expectedGrandChildName, AbstractApplicationContext.DefaultRootContextName); + + //setup custom child instance for this one test + _childContext = new MockApplicationContext(_expectedChildName); + _childContext.MockName = "child"; + _childContext.ParentContext = _parentContext; + _grandChildContext.ParentContext = _childContext; + + //register contexts in conflict with hierarchical order + ContextRegistry.RegisterContext(_parentContext); + ContextRegistry.RegisterContext(_childContext); + ContextRegistry.RegisterContext(_grandChildContext); + ContextRegistry.RegisterContext(_greatGrandChildContext); + + + Assert.AreEqual(_expectedParentName, ContextRegistry.GetContext(_expectedParentName).Name); + Assert.AreEqual(_expectedChildName, ContextRegistry.GetContext(_expectedChildName).Name); + Assert.AreEqual(_expectedGrandChildName, ContextRegistry.GetContext(_expectedGrandChildName).Name); + Assert.AreEqual(_expectedGreatGrandChildName, ContextRegistry.GetContext(_expectedGreatGrandChildName).Name); + } + } + } }