#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.IO;
using System.Threading;
using Common.Logging;
using Spring.Objects;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Util;
#endregion
namespace Spring.Context.Support{
/// <summary>
/// Convenient abstract superclass for
/// <see cref="Spring.Context.IApplicationContext"/> implementations that
/// draw their configuration from XML documents containing object
/// definitions as understood by an
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Griffin Caprio (.NET)</author>
public abstract class AbstractXmlApplicationContext : AbstractApplicationContext
{
private DefaultListableObjectFactory _objectFactory;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
protected AbstractXmlApplicationContext()
: this(null, true, null)
{ }
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/> class
/// with the given parent context.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
/// <param name="name">The application context name.</param>
/// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
/// <param name="parentContext">The parent context.</param>
protected AbstractXmlApplicationContext(string name, bool caseSensitive,
IApplicationContext parentContext)
: base(name, caseSensitive, parentContext)
{ }
/// <summary>
/// An array of resource locations, referring to the XML object
/// definition files that this context is to be built with.
/// </summary>
/// <remarks>
/// <p>
/// Examples of the format of the various strings that would be
/// returned by accessing this property can be found in the overview
/// documentation of with the <see cref="XmlApplicationContext"/>
/// class.
/// </p>
/// </remarks>
/// <returns>
/// An array of resource locations, or <see langword="null"/> if none.
/// </returns>
protected abstract string[] ConfigurationLocations { get; }
/// <summary>
/// Instantiates and populates the underlying
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> with the object
/// definitions yielded up by the <see cref="ConfigurationLocations"/>
/// method.
/// </summary>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered while refreshing the object factory.
/// </exception>
/// <exception cref="ApplicationContextException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.RefreshObjectFactory()"/>
protected override void RefreshObjectFactory()
{
// Shut down previous object factory, if any.
DefaultListableObjectFactory oldObjectFactory = _objectFactory;
_objectFactory = null;
if (oldObjectFactory != null)
{
oldObjectFactory.Dispose();
}
try
{
DefaultListableObjectFactory objectFactory = CreateObjectFactory();
LoadObjectDefinitions(objectFactory);
_objectFactory = objectFactory;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Refreshed ObjectFactory for application context '{0}'.",
Name));
}
#endregion
}
catch (IOException ex)
{
throw new ApplicationContextException(
string.Format(
"I/O error parsing XML resource for application context '{0}'.",
Name), ex);
}
catch (UriFormatException ex)
{
throw new ApplicationContextException(
string.Format(
"Error parsing resource locations [{0}] for application context '{1}'.",
StringUtils.ArrayToCommaDelimitedString(ConfigurationLocations),
Name), ex);
}
}
/// <summary>
/// Initialize the object definition reader used for loading the object
/// definitions of this context.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation of this method is a no-op; i.e. it does
/// nothing. Can be overridden in subclasses to provide custom
/// initialization of the supplied
/// <paramref name="objectDefinitionReader"/>; for example, a derived
/// class may want to turn off XML validation.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The object definition reader used by this context.
/// </param>
protected virtual void InitObjectDefinitionReader(
XmlObjectDefinitionReader objectDefinitionReader)
{ }
/// <summary>
/// Load the object definitions with the given
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <remarks>
/// <p>
/// The lifecycle of the object factory is handled by
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext.RefreshObjectFactory"/>;
/// therefore this method is just supposed to load and / or register
/// object definitions.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The reader containing object definitions.</param>
/// <exception cref="ObjectsException">
/// In case of object registration errors.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
protected virtual void LoadObjectDefinitions(
XmlObjectDefinitionReader objectDefinitionReader)
{
string[] locations = ConfigurationLocations;
if (locations != null)
{
objectDefinitionReader.LoadObjectDefinitions(ConfigurationLocations);
}
}
/// <summary>
/// Loads the object definitions into the given object factory, typically through
/// delegating to one or more object definition readers.
/// </summary>
/// <param name="objectFactory">The object factory to lead object definitions into</param>
/// <see cref="XmlObjectDefinitionReader"/>
/// <see cref="PropertiesObjectDefinitionReader"/>
protected virtual void LoadObjectDefinitions(DefaultListableObjectFactory objectFactory)
{
//Create a new XmlObjectDefinitionReader for the given ObjectFactory
XmlObjectDefinitionReader objectDefinitionReader = CreateXmlObjectDefinitionReader(objectFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
objectDefinitionReader.ResourceLoader = this;
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the object definitions.
InitObjectDefinitionReader(objectDefinitionReader);
LoadObjectDefinitions(objectDefinitionReader);
}
/// <summary>
/// Create a new reader instance for importing object definitions into the specified <paramref name="objectFactory"/>.
/// </summary>
/// <param name="objectFactory">the <see cref="DefaultListableObjectFactory"/> to be associated with the reader</param>
/// <returns>a new <see cref="XmlObjectDefinitionReader"/> instance.</returns>
protected virtual XmlObjectDefinitionReader CreateXmlObjectDefinitionReader(DefaultListableObjectFactory objectFactory)
{
return new XmlObjectDefinitionReader(objectFactory);
}
/// <summary>
/// Customizes the internal object factory used by this context.
/// </summary>
/// <remarks>Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// <p>
/// The default implementation is empty. Can be overriden in subclassses to customize
/// DefaultListableBeanFatory's standard settings.
/// </p></remarks>
/// <param name="objectFactory">The newly created object factory for this context</param>
protected virtual void CustomizeObjectFactory(DefaultListableObjectFactory objectFactory)
{
// noop
}
/// <summary>
/// Create an internal object factory for this context.
/// </summary>
/// <remarks>
/// <p>
/// Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// This default implementation creates a
/// <see cref="Spring.Objects.Factory.Support.DefaultListableObjectFactory"/>
/// with the internal object factory of this context's parent serving
/// as the parent object factory. Can be overridden in subclasse,s
/// for example to customize DefaultListableBeanFactory's settings.
/// </p>
/// </remarks>
/// <returns>The object factory for this context.</returns>
protected virtual DefaultListableObjectFactory CreateObjectFactory()
{
return new DefaultListableObjectFactory(IsCaseSensitive, GetInternalParentObjectFactory());
}
/// <summary>
/// Subclasses must return their internal object factory here.
/// </summary>
/// <returns>
/// The internal object factory for the application context.
/// </returns>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.ObjectFactory"/>
public override IConfigurableListableObjectFactory ObjectFactory
{
get { return _objectFactory; }
}
/// <summary>
/// Determine whether the given object name is already in use within this context's object factory,
/// i.e. whether there is a local object or alias registered under this name.
/// </summary>
public override bool IsObjectNameInUse(string objectName)
{
return _objectFactory.IsObjectNameInUse(objectName);
}
}
}
|