ContextRegistry.cs :  » Inversion-of-Control-Dependency-Injection » Spring.net » Spring » Context » Support » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Inversion of Control Dependency Injection » Spring.net 
Spring.net » Spring » Context » Support » ContextRegistry.cs
#region License

/* 
 * Copyright  2002-2005 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

#region Imports

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using Common.Logging;
using Spring.Context.Events;
using Spring.Util;

#endregion

namespace Spring.Context.Support{
    /// <summary> 
    /// Provides access to a central registry of 
    /// <see cref="Spring.Context.IApplicationContext"/>s.
    /// </summary>
    /// <remarks>
    /// <p>
    /// A singleton implementation to access one or more application contexts.  Application
    /// context instances are cached.
    /// </p>
    /// <p>Note that the use of this class or similar is unnecessary except (sometimes) for
    /// a small amount of glue code.  Excessive usage will lead to code that is more tightly
    /// coupled, and harder to modify or test.  Consider refactoring your code to use standard
    /// Dependency Injection techniques or implement the interface IApplicationContextAware to
    /// obtain a reference to an application context.</p>
    /// </remarks>
    /// <author>Mark Pollack</author>
    /// <author>Aleksandar Seovic</author>
    /// <seealso cref="Spring.Context.IApplicationContext"/>
    public sealed class ContextRegistry
    {
        /// <summary>
        /// The shared <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).
        /// </summary>
        private static readonly ILog log = LogManager.GetLogger(typeof(ContextRegistry));

        private static readonly object syncRoot = new Object();
        private static readonly ContextRegistry instance = new ContextRegistry();
        private static string rootContextName = null;

        private IDictionary contextMap = CollectionsUtil.CreateCaseInsensitiveHashtable();

        #region Constructor (s) / Destructor

        // CLOVER:OFF

        /// <summary>
        /// Creates a new instance of the ContextRegistry class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Explicit static constructor to tell C# compiler
        /// not to mark type as beforefieldinit.
        /// </p>
        /// </remarks>
        static ContextRegistry()
        { }

        // CLOVER:ON

        #endregion

        /// <summary>
        /// This event is fired, if ContextRegistry.Clear() is called.<br/>
        /// Clients may register to get informed
        /// </summary>
        /// <remarks>
        /// This event is fired while still holding a lock on the Registry.<br/>
        /// 'sender' parameter is sent as typeof(ContextRegistry), EventArgs are not used
        /// </remarks>
        public static event EventHandler Cleared;

        /// <summary>
        /// Gets an object that should be used to synchronize access to ContextRegistry
        /// from the calling code.
        /// </summary>
        public static object SyncRoot
        {
            get { return syncRoot; }
        }

        /// <summary> 
        /// Registers an instance of an
        /// <see cref="Spring.Context.IApplicationContext"/>. 
        /// </summary> 
        /// <remarks>
        /// <p>
        /// This is usually called via a
        /// <see cref="Spring.Context.Support.ContextHandler"/> inside a .NET
        /// application configuration file. 
        /// </p>
        /// </remarks>
        /// <param name="context">The application context to be registered.</param>
        /// <exception cref="Spring.Context.ApplicationContextException">
        /// If a context has previously been registered using the same name
        /// </exception>
        public static void RegisterContext(IApplicationContext context)
        {
            lock (syncRoot)
            {
                if (instance.contextMap.Contains(context.Name))
                {
                    IApplicationContext ctx = (IApplicationContext)instance.contextMap[context.Name];
                    throw new ApplicationContextException(
                        string.Format("Existing context '{0}' already registered under name '{1}'.",
                                      ctx, context.Name));
                }
                instance.contextMap[context.Name] = context;
                context.ContextEvent += new ApplicationEventHandler(OnContextEvent);

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(String.Format(
                        "Registering context '{0}' under name '{1}'.", context, context.Name));
                }

                #endregion

                if (rootContextName == null)
                {
                    rootContextName = context.Name;
                }
            }
        }

        /// <summary>
        /// Handles events raised by an application context.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void OnContextEvent(object sender, ApplicationEventArgs e)
        {
            ContextEventArgs cea = e as ContextEventArgs;
            if (cea != null
                && cea.Event == ContextEventArgs.ContextEvent.Closed
                && sender is IApplicationContext)
            {
                // we know the context is registered!
                UnregisterContext((IApplicationContext)sender);
            }
        }

        /// <summary>
        /// Removes the context from the registry 
        /// </summary>
        /// <remarks>
        /// Has no effect if the context wasn't registered
        /// </remarks>
        /// <param name="context">the context to remove from the registry</param>
        private static void UnregisterContext(IApplicationContext context)
        {
            AssertUtils.ArgumentNotNull(context, "context");
            lock (syncRoot)
            {
                if (IsContextRegistered(context.Name))
                {
                    instance.contextMap.Remove(context.Name);
                    if (rootContextName == context.Name)
                    {
                        rootContextName = null;
                    }
                }
            }
        }

        /// <summary>
        /// Returns the root application context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The first call to GetContext will create the context 
        /// as specified in the .NET application configuration file 
        /// under the location spring/context.
        /// </p>
        /// </remarks>
        /// <returns>The root application context.</returns>
        public static IApplicationContext GetContext()
        {
            lock (syncRoot)
            {
                InitializeContextIfNeeded();
                if (rootContextName == null)
                {
                    throw new ApplicationContextException(
                        "No context registered. Use the 'RegisterContext' method or the 'spring/context' section from your configuration file.");
                }
                return GetContext(rootContextName);
            }
        }

        /// <summary>
        /// Returns context based on specified name.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The first call to GetContext will create the context 
        /// as specified in the .NET application configuration file 
        /// under the location spring/context.
        /// </p>
        /// </remarks>
        /// <param name="name">The context name.</param>
        /// <returns>The specified context, or null, if context with that name doesn't exists.</returns>
        /// <exception cref="System.ArgumentException">
        /// If the context name is null or empty
        /// </exception>
        public static IApplicationContext GetContext(string name)
        {
            if (StringUtils.IsNullOrEmpty(name))
            {
                throw new ArgumentException(
                    "The context name passed to the GetContext method cannot be null or empty.");
            }
            else
            {
                lock (syncRoot)
                {
                    InitializeContextIfNeeded();
                    IApplicationContext ctx = (IApplicationContext)instance.contextMap[name];
                    if (ctx == null)
                    {
                        throw new ApplicationContextException(String.Format(
                            "No context registered under name '{0}'. Use the 'RegisterContext' method or the 'spring/context' section from your configuration file.",
                            name));
                    }

                    #region Instrumentation

                    if (log.IsDebugEnabled)
                    {
                        log.Debug(String.Format(
                            "Returning context '{0}' registered under name '{1}'.", ctx, name));
                    }

                    #endregion

                    return ctx;
                }
            }
        }

        /// <summary>
        /// Removes all registered
        /// <see cref="Spring.Context.IApplicationContext"/>s from this
        /// registry.
        /// </summary>
        /// <remarks>
        /// Raises the <see cref="ContextRegistry.Cleared"/> event while still holding a lock on <see cref="ContextRegistry.SyncRoot"/>
        /// </remarks>
        public static void Clear()
        {
            lock (syncRoot)
            {
                ArrayList contexts = new ArrayList(instance.contextMap.Values);
                foreach (IApplicationContext ctx in contexts)
                {
                    ctx.Dispose();
                }

                #region Instrumentation

                // contexts will be removed from contextMap during OnContextEvent handler 
                // but someone might choose to override AbstractApplicationContext.Dispose() without 
                // calling base.Dispose() ...
                if (log.IsWarnEnabled)
                {
                    if (instance.contextMap.Count > 0)
                    {
                        log.Warn(
                            String.Format(
                                "Not all contexts were removed from registry during cleanup - did you forget to call base.Dispose() when overriding AbstractApplicationContext.Dispose()?"));
                    }
                }

                #endregion

                instance.contextMap.Clear();
                rootContextName = null;
                // mark section dirty - force re-read from disk next time
                ConfigurationUtils.RefreshSection(AbstractApplicationContext.ContextSectionName);
                DynamicCodeManager.Clear();
                if (Cleared != null)
                {
                    Cleared(typeof(ContextRegistry), EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Allows to check, if a context is already registered
        /// </summary>
        /// <param name="name">The context name.</param>
        /// <returns>true, if the context is already registered. false otherwise</returns>
        public static bool IsContextRegistered(string name)
        {
            lock (instance)
            {
                return (instance.contextMap[name] != null);
            }
        }

        private static bool rootContextCurrentlyInCreation;

        private static void InitializeContextIfNeeded()
        {
            if (rootContextName == null)
            {
                if (rootContextCurrentlyInCreation)
                {
                    throw new InvalidOperationException("root context is currently in creation. You must not call ContextRegistry.GetContext() from e.g. constructors of your singleton objects");
                }

                rootContextCurrentlyInCreation = true;
                try
                {
                    ConfigurationUtils.GetSection(AbstractApplicationContext.ContextSectionName);
                }
                finally
                {
                    rootContextCurrentlyInCreation = false;
                }
            }
        }
    }
}

www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.