PropertyPlaceholderConfigurer.cs :  » Inversion-of-Control-Dependency-Injection » Spring.net » Spring » Objects » Factory » Config » 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 » Objects » Factory » Config » PropertyPlaceholderConfigurer.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.Globalization;
using Common.Logging;
using Spring.Collections;

#endregion

namespace Spring.Objects.Factory.Config{
  /// <summary>
  /// Resolves placeholder values in one or more object definitions.
  /// </summary>
  /// <remarks>
  /// <p>
  /// The default placeholder syntax follows the NAnt style: <c>${...}</c>.
  /// Instances of this class can be configured in the same way as any other
  /// object in a Spring.NET container, and so custom placeholder prefix
  /// and suffix values can be set via the <see cref="PlaceholderPrefix"/>
  /// and <see cref="PlaceholderSuffix"/> properties.
  /// </p>
  /// <example>
  /// <p>
  /// The following example XML context definition defines an object that has
  /// a number of placeholders. The placeholders can easily be distinguished
  /// by the presence of the <c>${}</c> characters.
  /// </p>
  /// <code escaped="true">
  /// <object id="connStringProvider"
  ///    type="MyNamespace.OracleConnectionStringProvider, MyAssembly">
  ///    <property name="dataSource" value="${database.datasource}"/>
  ///    <property name="userId" value="${database.userid}"/>
  ///    <property name="password" value="${database.password}"/>
  ///    <property name="integratedSecurity"
  ///      value="${database.integratedsecurity}"/>
  /// </object>
  /// </code>
  /// <p>
  /// The associated XML configuration file for the above example containing the
  /// values for the placeholders would contain a snippet such as ..
  /// </p>
  /// <code escaped="true">
  ///  <name-values>
  ///    <add key="database.datasource" value="MyOracleDB"/>
  ///    <add key="database.userid" value="sa"/>
  ///    <add key="database.password" value="g0ly4dk1n"/>
  ///    <add key="database.integratedsecurity" value="true"/>
  /// </name-values>
  /// </code>
  /// <p>
  /// The preceding XML snippet listing the various property keys and their
  /// associated values needs to be inserted into the .NET config file of
  /// your application (or Web.config file for your ASP.NET web application,
  /// as the case may be), like so...
  /// </p>
  /// <code escaped="true">
  ///  <name-values>
  ///    <add key="database.datasource" value="MyOracleDB"/>
  ///    <add key="database.userid" value="sa"/>
  ///    <add key="database.password" value="g0ly4dk1n"/>
  ///    <add key="database.integratedsecurity" value="true"/>
  /// </name-values>
  /// </code>
  /// </example>
  /// <p>
  /// <see cref="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer"/>
  /// checks simple property values, lists, dictionaries, sets, constructor
  /// values, object type name, and object names in
  /// runtime object references (
  /// <see cref="Spring.Objects.Factory.Config.RuntimeObjectReference"/>).
  /// Furthermore, placeholder values can also cross-reference other
  /// placeholders, in the manner of the following example where the
  /// <c>rootPath</c> property is cross-referenced by the <c>subPath</c>
  /// property.
  /// </p>
  /// <example>
  /// <code escaped="true">
  /// <name-values>
  ///    <add key="rootPath" value="myrootdir"/>
  ///    <add key="subPath" value="${rootPath}/subdir"/>
  /// </name-values>
  /// </code>
  /// </example>
  /// <p>
  /// In contrast to the
  /// <see cref="Spring.Objects.Factory.Config.PropertyOverrideConfigurer"/>
  /// class, this configurer only permits the replacement of explicit
  /// placeholders in object definitions. Therefore, the original definition
  /// cannot specify any default values for its object properties, and the
  /// placeholder configuration file is expected to contain an entry for each
  /// defined placeholder. That is, if an object definition contains a
  /// placeholder <c>${foo}</c>, there should be an associated
  /// <c>&lt;add key="foo" value="..."/&gt;</c> entry in the
  /// referenced placeholder configuration file. Default property values
  /// can be defined via the inherited
  /// <see cref="Spring.Objects.Factory.Config.PropertyResourceConfigurer.Properties"/>
  /// collection to overcome any perceived limitation of this feature.
  /// </p>
  /// <p>
  /// If a configurer cannot resolve a placeholder, and the value of the
  /// <see cref="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer.IgnoreUnresolvablePlaceholders"/>
  /// property is currently set to <see langword="false"/>, an
  /// <see cref="Spring.Objects.Factory.ObjectDefinitionStoreException"/>
  /// will be thrown. If you want to resolve properties from multiple configuration
  /// resources, simply specify multiple resources via the
  /// <see cref="Spring.Objects.Factory.Config.PropertyResourceConfigurer.Locations"/>
  /// property. Finally, please note that you can also define multiple
  /// <see cref="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer"/>
  /// instances, each with their own custom placeholder syntax.
  /// </p>
  /// </remarks>
  /// <author>Juergen Hoeller</author>
  /// <author>Simon White (.NET)</author>
  /// <seealso cref="Spring.Objects.Factory.Config.PropertyResourceConfigurer"/>
  /// <seealso cref="Spring.Objects.Factory.Config.PropertyOverrideConfigurer"/>
  /// <seealso cref="Spring.Objects.Factory.Config.IObjectDefinition"/>
    [Serializable]
    public class PropertyPlaceholderConfigurer : PropertyResourceConfigurer
  {
    /// <summary>
    /// The default placeholder prefix.
    /// </summary>
    public static readonly string DefaultPlaceholderPrefix = "${";

    /// <summary>
    /// The default placeholder suffix.
    /// </summary>
    public static readonly string DefaultPlaceholderSuffix = "}";


    private readonly ILog logger;


    private bool ignoreUnresolvablePlaceholders = false;
    private string placeholderPrefix = DefaultPlaceholderPrefix;
    private string placeholderSuffix = DefaultPlaceholderSuffix;
    private EnvironmentVariableMode environmentVariableMode = EnvironmentVariableMode.Fallback;

        /// <summary>
        /// Initializes the new instance
        /// </summary>
      public PropertyPlaceholderConfigurer()
      {
            logger = LogManager.GetLogger(this.GetType());
      }

      #region Properties 
        /// <summary>
    /// The placeholder prefix (the default is <c>${</c>).
    /// </summary>
    /// <seealso cref="DefaultPlaceholderPrefix"/>
    public string PlaceholderPrefix
    {
      set { placeholderPrefix = value; }
    }

    /// <summary>
    /// The placeholder suffix (the default is <c>}</c>)
    /// </summary>
    /// <seealso cref="DefaultPlaceholderSuffix"/>
    public string PlaceholderSuffix
    {
      set { placeholderSuffix = value; }
    }

    /// <summary>
    /// Indicates whether unresolved placeholders should be ignored.
    /// </summary>
    public bool IgnoreUnresolvablePlaceholders
    {
            get { return ignoreUnresolvablePlaceholders; }
            set { ignoreUnresolvablePlaceholders = value; }
    }

    /// <summary>
    /// Controls how environment variables will be used to 
    /// replace property placeholders.
    /// </summary>
    /// <remarks>
    /// <p>
    /// See the overview of the
    /// <see cref="Spring.Objects.Factory.Config.EnvironmentVariableMode"/>
    /// enumeration for the available options.
    /// </p>
    /// </remarks>
    public EnvironmentVariableMode EnvironmentVariableMode
    {
      set { environmentVariableMode = value; }
        }

        #endregion

        /// <summary>
    /// Apply the given properties to the supplied
    /// <see cref="Spring.Objects.Factory.Config.IConfigurableListableObjectFactory"/>.
    /// </summary>
    /// <param name="factory">
    /// The <see cref="Spring.Objects.Factory.Config.IConfigurableListableObjectFactory"/>
    /// used by the application context.
    /// </param>
    /// <param name="props">The properties to apply.</param>
    /// <exception cref="Spring.Objects.ObjectsException">
    /// If an error occured.
    /// </exception>
    protected override void ProcessProperties(IConfigurableListableObjectFactory factory, NameValueCollection props)
    {
            PlaceholderResolveHandlerAdapter resolveAdapter = new PlaceholderResolveHandlerAdapter(this, props);
            ObjectDefinitionVisitor visitor = new ObjectDefinitionVisitor(new ObjectDefinitionVisitor.ResolveHandler(resolveAdapter.ParseAndResolveVariables));

      string[] objectDefinitionNames = factory.GetObjectDefinitionNames();
      for (int i = 0; i < objectDefinitionNames.Length; ++i)
      {
        string name = objectDefinitionNames[i];
        IObjectDefinition definition = factory.GetObjectDefinition(name);
        try
        {
                    visitor.VisitObjectDefinition(definition);
        }
        catch (ObjectDefinitionStoreException ex)
        {
          throw new ObjectDefinitionStoreException(
            definition.ResourceDescription, name, ex.Message);
        }
      }
    }






    /// <summary>
    /// Parse values recursively to be able to resolve cross-references between
    /// placeholder values.
    /// </summary>
    /// <param name="properties">
    /// The map of constructor arguments / property values.
    /// </param>
    /// <param name="strVal">The string to be resolved.</param>
        /// <param name="visitedPlaceholders">The placeholders that have already been visited
        /// during the current resolution attempt (used to detect circular references
        /// between placeholders). Only non-null if we're parsing a nested placeholder.</param>
    /// <exception cref="Spring.Objects.ObjectsException">
    /// If an error occurs.
    /// </exception>
    /// <returns>The resolved string.</returns>
    public virtual string ParseString(
      NameValueCollection properties, string strVal, ISet visitedPlaceholders)
    {
      int startIndex = strVal.IndexOf(placeholderPrefix);
      while (startIndex != -1)
      {
        int endIndex = strVal.IndexOf(
          placeholderSuffix, startIndex + placeholderPrefix.Length);
        if (endIndex != -1)
        {
          int pos = startIndex + placeholderPrefix.Length;
          string placeholder = strVal.Substring(pos, endIndex - pos);
                    if (visitedPlaceholders.Contains(placeholder))
                    {
                        throw new ObjectDefinitionStoreException(
                                    string.Format(
                                        CultureInfo.InvariantCulture,
                                        "Circular placeholder reference '{0}' detected " +
                                            "in property definitions [{1}].",
                                        placeholder, properties));
                    }
            visitedPlaceholders.Add(placeholder);
          string resolvedValue = ResolvePlaceholder(placeholder, properties, environmentVariableMode);
          if (resolvedValue != null)
          {
                        resolvedValue = ParseString(properties, resolvedValue, visitedPlaceholders);

            #region Instrumentation

            if (logger.IsDebugEnabled)
            {
              logger.Debug(string.Format(
                CultureInfo.InvariantCulture,
                "Resolving placeholder '{0}' to '{1}'.", placeholder, resolvedValue));
            }

            #endregion

            strVal = strVal.Substring(0, startIndex) + resolvedValue + strVal.Substring(endIndex + 1);
            startIndex = strVal.IndexOf(placeholderPrefix, startIndex + resolvedValue.Length);
          }
          else if (ignoreUnresolvablePlaceholders)
          {
            // simply return the unprocessed value...
            return strVal;
          }
          else
          {
            throw new ObjectDefinitionStoreException(string.Format(
                CultureInfo.InvariantCulture,
                "Could not resolve placeholder '{0}'.", placeholder));
          }
            visitedPlaceholders.Remove(placeholder);
        }
        else
        {
          startIndex = -1;
        }
      }
      return strVal;
    }

    /// <summary>
    /// Resolve the given placeholder using the given name value collection,
    /// performing an environment variables check according to the given mode.
    /// </summary>
    /// <remarks>
    /// <p>
    /// The default implementation delegates to 
    /// <see cref="ResolvePlaceholder(string, NameValueCollection)"/>
    /// before/afer the environment variable check. Subclasses can override
    /// this for custom resolution strategies, including customized points
    /// for the environment properties check.
    /// </p>
    /// </remarks>
    /// <param name="placeholder">The placeholder to resolve</param>
    /// <param name="props">
    /// The merged name value collection of this configurer.
    /// </param>
    /// <param name="mode">The environment variable mode.</param>
    /// <returns>
    /// The resolved value or <see langword="null"/> if none.
    /// </returns>
    /// <seelso cref="Spring.Objects.Factory.Config.EnvironmentVariableMode"/>
    protected virtual string ResolvePlaceholder(string placeholder,
                                                NameValueCollection props,
                                                EnvironmentVariableMode mode)
    {
      string propertyValue = null;
      if (mode == Spring.Objects.Factory.Config.EnvironmentVariableMode.Override)
      {
        propertyValue = Environment.GetEnvironmentVariable(placeholder);
      }
      if (propertyValue == null)
      {
        propertyValue = ResolvePlaceholder(placeholder, props);
      }
      if (propertyValue == null
        && mode == Spring.Objects.Factory.Config.EnvironmentVariableMode.Fallback)
      {
        propertyValue = Environment.GetEnvironmentVariable(placeholder);
      }
      return propertyValue;
    }

    /// <summary>
    /// Resolve the given placeholder using the given name value collection.
    /// </summary>
    /// <remarks>
    /// <p>
    /// This (the default) implementation simply looks up the value of the
    /// supplied <paramref name="placeholder"/> key.
    /// </p>
    /// <p>
    /// Subclasses can override this for customized placeholder-to-key
    /// mappings or custom resolution strategies, possibly just using the
    /// given name value collection as fallback.
    /// </p>
    /// </remarks>
    /// <param name="placeholder">The placeholder to resolve.</param>
    /// <param name="props">
    /// The merged name value collection of this configurer.
    /// </param>
    /// <returns>The resolved value.</returns>
    protected virtual string ResolvePlaceholder(
      string placeholder, NameValueCollection props)
    {
      return props[placeholder];
    }

        #region Helper class

        private class PlaceholderResolveHandlerAdapter
        {
            private readonly PropertyPlaceholderConfigurer ppc;
            private readonly NameValueCollection props;

            public PlaceholderResolveHandlerAdapter(PropertyPlaceholderConfigurer outerPPC, NameValueCollection props)
            {
                ppc = outerPPC;
                this.props = props;
            }

            public string ParseAndResolveVariables(string name)
            {
                return ppc.ParseString(props, name, new HashedSet());
            }
        }

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