removed HttpContext deps

further Spring/J syncs (introduced INamespaceParserResolver (just internal yet))
fixed ParserContext.ContainingObjectDefinition handling
fixed SPRNET-1211
This commit is contained in:
eeichinger
2009-05-25 03:07:01 +00:00
parent 34fea21fdd
commit 2a203a7f7c
44 changed files with 2397 additions and 975 deletions

View File

@@ -17,6 +17,8 @@ Spring.Core
<v:action ...>
<v:validator ...>
2. XmlReaderContext constructor now requires an IObjectDefinitionFactory to be specified. Thus XmlReaderContext.ObjectDefinitionFactory
is read only now.
Changes (1.1.2 to 1.2 RC1 or greater)

View File

@@ -226,7 +226,7 @@ namespace Spring.Context.Support
protected virtual void LoadObjectDefinitions(DefaultListableObjectFactory objectFactory)
{
//Create a new XmlObjectDefinitionReader for the given ObjectFactory
XmlObjectDefinitionReader objectDefinitionReader = new XmlObjectDefinitionReader(objectFactory);
XmlObjectDefinitionReader objectDefinitionReader = CreateXmlObjectDefinitionReader(objectFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
@@ -236,6 +236,16 @@ namespace Spring.Context.Support
// 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>

View File

@@ -251,6 +251,16 @@ namespace Spring.Context.Support
public void RegisterAlias(string name, string theAlias)
{
objectFactory.RegisterAlias(name, theAlias);
}
/// <summary>
/// Determines whether the given object name is already in use within this factory,
/// i.e. whether there is a local object or alias registered under this name or
/// an inner object created with this name.
/// </summary>
public bool IsObjectNameInUse(string objectName)
{
return objectFactory.IsObjectNameInUse(objectName);
}
#endregion

View File

@@ -232,7 +232,7 @@ namespace Spring.Objects.Factory.Support
if (log.IsDebugEnabled)
{
log.Debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
log.Debug("Loaded " + loadCount + " object definitions from location [" + location + "]");
}
return loadCount;
}

View File

@@ -45,6 +45,12 @@ namespace Spring.Objects.Factory.Support
/// <author>Rick Evans (.NET)</author>
public interface IObjectDefinitionRegistry
{
/// <summary>
/// Determine whether the given object name is already in use within this registry,
/// i.e. whether there is a local object or alias registered under this name.
/// </summary>
bool IsObjectNameInUse(string objectName);
/// <summary>
/// Return the number of objects defined in the registry.
/// </summary>

View File

@@ -0,0 +1,43 @@
#region License
/*
* Copyright 2002-2009 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
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Default implementation of the <see cref="INamespaceParserResolver"/> interface.
/// Resolves namespace URIs to implementation types based on mappings.
/// </summary>
/// <author>Erich Eichinger</author>
/// <seealso cref="INamespaceParser"/>
/// <seealso cref="DefaultObjectDefinitionDocumentReader"/>
internal class DefaultNamespaceHandlerResolver : INamespaceParserResolver
{
/// <summary>
/// Resolve the namespace URI and return the corresponding <see cref="INamespaceParser"/>
/// implementation.
/// </summary>
/// <param name="namespaceUri">the namespace URI to get the matching parser for.</param>
/// <returns>the matching parser or <c>null</c></returns>
public INamespaceParser Resolve(string namespaceUri)
{
return NamespaceParserRegistry.GetParser(namespaceUri);
}
}
}

View File

@@ -352,8 +352,7 @@ namespace Spring.Objects.Factory.Xml
/// <returns>a new <see cref="ObjectDefinitionParserHelper"/> instance</returns>
protected virtual ObjectDefinitionParserHelper CreateHelper(XmlReaderContext readerContext, XmlElement root)
{
ObjectDefinitionParserHelper helper = new ObjectDefinitionParserHelper(readerContext);
helper.InitDefaults(root);
ObjectDefinitionParserHelper helper = new ObjectDefinitionParserHelper(readerContext, root);
return helper;
}

View File

@@ -30,7 +30,7 @@ namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Strategy interface for parsing XML object definitions.
/// Strategy interface for parsing XML object definitions. Equivalent to Spring/Java's <c>NamespaceHandler</c> interface.
/// </summary>
/// <remarks>
/// <p>
@@ -38,7 +38,7 @@ namespace Spring.Objects.Factory.Xml
/// for actually parsing a DOM document or
/// <see cref="System.Xml.XmlElement"/> fragment.
/// </p>
/// </remarks>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
/// <author>Sandu Turcan (.NET)</author>

View File

@@ -0,0 +1,43 @@
#region License
/*
* Copyright 2002-2009 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
using System;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Used by <see cref="DefaultObjectDefinitionDocumentReader"/> to locate
/// <see cref="INamespaceParser"/> implementations for a particular namespace URI.
/// </summary>
/// <remarks>TODO (EE): clarify naming of INamespaceParser (SPR/NET) vs. INamespaceHandler (SPR/Java), thus internal for now</remarks>
/// <author>Erich Eichinger</author>
/// <seealso cref="XmlObjectDefinitionReader.NamespaceParserResolver"/>
/// <seealso cref="XmlObjectDefinitionReader.CreateDefaultNamespaceParserResolver"/>
/// <seealso cref="XmlReaderContext.NamespaceParserResolver"/>
internal interface INamespaceParserResolver
{
/// <summary>
/// Lookup a <see cref="INamespaceParser"/> for the given namespace URI.
/// </summary>
/// <param name="namespaceUri">the namespace URI</param>
/// <returns>the located namespace handler or <c>null</c></returns>
INamespaceParser Resolve(string namespaceUri);
}
}

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright <20> 2002-2007 the original author or authors.
*
@@ -14,163 +14,182 @@
* 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
using System;
*/
#endregion
using System;
using System.Collections;
using System.Globalization;
using System.Xml;
using Common.Logging;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Stateful class used to parse XML object definitions.
/// </summary>
using System.Globalization;
using System.Reflection;
using System.Xml;
using Common.Logging;
using Spring.Collections;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Stateful class used to parse XML object definitions.
/// </summary>
/// <remarks>Not all parsing code has been refactored into this class. See
/// BeanDefinitionParserDelegate in Java for how this class should evolve.</remarks>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
public class ObjectDefinitionParserHelper
{
#region Fields
/// <summary>
/// The shared <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).
/// </summary>
protected static readonly ILog log =
LogManager.GetLogger(typeof(ObjectDefinitionParserHelper));
private DocumentDefaultsDefinition defaults;
private XmlReaderContext readerContext;
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="ObjectDefinitionParserHelper"/> class.
/// </summary>
/// <param name="readerContext">The reader context.</param>
public ObjectDefinitionParserHelper(XmlReaderContext readerContext)
{
AssertUtils.ArgumentNotNull(readerContext, "readerContext");
this.readerContext = readerContext;
}
/// <summary>
/// Gets the defaults definition object, or <code>null</code> if the
/// default have not yet been initialized.
/// </summary>
/// <value>The defaults.</value>
public DocumentDefaultsDefinition Defaults
{
get { return defaults; }
}
/// <summary>
/// Gets the reader context.
/// </summary>
/// <value>The reader context.</value>
public XmlReaderContext ReaderContext
{
get { return readerContext; }
}
/// <summary>
/// Initialize the default lazy-init, dependency check, and autowire settings.
/// </summary>
/// <param name="root">The root element</param>
public void InitDefaults(XmlElement root)
{
DocumentDefaultsDefinition ddd = new DocumentDefaultsDefinition();
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Loading object definitions...");
}
#endregion
ddd.LazyInit = GetAttributeValue(root, ObjectDefinitionConstants.DefaultLazyInitAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default lazy init '{0}'.",
ddd.LazyInit));
}
/// BeanDefinitionParserDelegate in Java for how this class should evolve.</remarks>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
public class ObjectDefinitionParserHelper
{
#region Fields
/// <summary>
/// The shared <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).
/// </summary>
protected readonly ILog log;
private DocumentDefaultsDefinition defaults;
private readonly XmlReaderContext readerContext;
private readonly ObjectsNamespaceParser objectsNamespaceParser;
private readonly ISet usedNames = new HashedSet();
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="ObjectDefinitionParserHelper"/> class.
/// </summary>
/// <param name="readerContext">The reader context.</param>
public ObjectDefinitionParserHelper(XmlReaderContext readerContext)
:this(readerContext, null)
{}
/// <summary>
/// Initializes a new instance of the <see cref="ObjectDefinitionParserHelper"/> class.
/// </summary>
/// <param name="readerContext">The reader context.</param>
/// <param name="root">The root element of the definition document to parse</param>
public ObjectDefinitionParserHelper(XmlReaderContext readerContext, XmlElement root)
{
log = LogManager.GetLogger(this.GetType());
this.readerContext = readerContext;
this.objectsNamespaceParser = (ObjectsNamespaceParser) readerContext.NamespaceParserResolver.Resolve(ObjectsNamespaceParser.Namespace);
if (root != null)
{
InitDefaults(root);
}
}
/// <summary>
/// Gets the defaults definition object, or <code>null</code> if the
/// default have not yet been initialized.
/// </summary>
/// <value>The defaults.</value>
public DocumentDefaultsDefinition Defaults
{
get { return defaults; }
}
/// <summary>
/// Gets the reader context.
/// </summary>
/// <value>The reader context.</value>
public XmlReaderContext ReaderContext
{
get { return readerContext; }
}
/// <summary>
/// Initialize the default lazy-init, dependency check, and autowire settings.
/// </summary>
/// <param name="root">The root element</param>
public void InitDefaults(XmlElement root)
{
DocumentDefaultsDefinition ddd = new DocumentDefaultsDefinition();
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Loading object definitions...");
}
#endregion
ddd.DependencyCheck = GetAttributeValue(root, ObjectDefinitionConstants.DefaultDependencyCheckAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default dependency check '{0}'.",
ddd.DependencyCheck));
}
ddd.LazyInit = GetAttributeValue(root, ObjectDefinitionConstants.DefaultLazyInitAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default lazy init '{0}'.",
ddd.LazyInit));
}
#endregion
ddd.Autowire = GetAttributeValue(root, ObjectDefinitionConstants.DefaultAutowireAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default autowire '{0}'.",
ddd.Autowire));
}
#endregion
defaults = ddd;
}
/// <summary>
/// Determines whether the Spring object namespace is equal to the the specified namespace URI.
/// </summary>
/// <param name="namespaceUri">The namespace URI.</param>
/// <returns>
/// <c>true</c> if is the default Spring namespace; otherwise, <c>false</c>.
/// </returns>
public bool IsDefaultNamespace(string namespaceUri)
{
return
(!StringUtils.HasLength(namespaceUri) || ObjectsNamespaceParser.Namespace.Equals(namespaceUri));
}
/// <summary>
/// Decorates the object definition if required.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="holder">The holder.</param>
/// <returns></returns>
public ObjectDefinitionHolder DecorateObjectDefinitionIfRequired(XmlElement element, ObjectDefinitionHolder holder)
{
//TODO decoration processing.
return holder;
ddd.DependencyCheck = GetAttributeValue(root, ObjectDefinitionConstants.DefaultDependencyCheckAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default dependency check '{0}'.",
ddd.DependencyCheck));
}
#endregion
ddd.Autowire = GetAttributeValue(root, ObjectDefinitionConstants.DefaultAutowireAttribute);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Default autowire '{0}'.",
ddd.Autowire));
}
#endregion
defaults = ddd;
}
/// <summary>
/// Determines whether the Spring object namespace is equal to the the specified namespace URI.
/// </summary>
/// <param name="namespaceUri">The namespace URI.</param>
/// <returns>
/// <c>true</c> if is the default Spring namespace; otherwise, <c>false</c>.
/// </returns>
public bool IsDefaultNamespace(string namespaceUri)
{
return
(!StringUtils.HasLength(namespaceUri) || ObjectsNamespaceParser.Namespace.Equals(namespaceUri));
}
/// <summary>
/// Decorates the object definition if required.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="holder">The holder.</param>
/// <returns></returns>
public ObjectDefinitionHolder DecorateObjectDefinitionIfRequired(XmlElement element, ObjectDefinitionHolder holder)
{
//TODO decoration processing.
return holder;
}
/// <summary>
@@ -194,7 +213,7 @@ namespace Spring.Objects.Factory.Xml
/// as the canonical name, registering all others as aliases.
/// </para>
/// </remarks>
public ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element)
public ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element)
{
return ParseObjectDefinitionElement(element, null);
}
@@ -221,11 +240,8 @@ namespace Spring.Objects.Factory.Xml
/// as the canonical name, registering all others as aliases.
/// </para>
/// </remarks>
public ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element, IObjectDefinition containingDefinition)
public ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element, IObjectDefinition containingDefinition)
{
// TODO: move code from ObjectsNamespaceParser into this class to eliminate ONP
ObjectsNamespaceParser parser = (ObjectsNamespaceParser) NamespaceParserRegistry.GetParser(ObjectsNamespaceParser.Namespace);
string id = GetAttributeValue(element, ObjectDefinitionConstants.IdAttribute);
string nameAttr = GetAttributeValue(element, ObjectDefinitionConstants.NameAttribute);
ArrayList aliases = new ArrayList();
@@ -238,13 +254,26 @@ namespace Spring.Objects.Factory.Xml
string objectName = id;
if (StringUtils.IsNullOrEmpty(objectName))
{
// TODO (EE): pass parserContext to CalculateId as well (resolving relative Urls in WebApps is parserContext-dependent) (EE)
objectName = parser.CalculateId(element, aliases);
if (aliases.Count > 0)
{
objectName = (string) aliases[0];
aliases.RemoveAt(0);
if (log.IsDebugEnabled)
{
log.Debug(string.Format("No XML 'id' specified using '{0}' as object name and '{1}' as aliases", objectName, string.Join(",", (string[]) aliases.ToArray(typeof(string)))));
}
}
}
objectName = PostProcessObjectNameAndAliases(objectName, aliases, element, containingDefinition);
if (containingDefinition == null)
{
CheckNameUniqueness(objectName, aliases, element);
}
ParserContext parserContext = new ParserContext(this, containingDefinition);
IConfigurableObjectDefinition definition = parser.ParseObjectDefinitionElement(element, objectName, parserContext);
IConfigurableObjectDefinition definition = objectsNamespaceParser.ParseObjectDefinitionElement(element, objectName, parserContext);
if (definition != null)
{
if (StringUtils.IsNullOrEmpty(objectName))
@@ -252,11 +281,20 @@ namespace Spring.Objects.Factory.Xml
if (containingDefinition != null)
{
objectName =
ObjectDefinitionReaderUtils.GenerateObjectName(definition, parserContext.Registry, true);
ObjectDefinitionReaderUtils.GenerateObjectName(definition, readerContext.Registry, true);
}
else
{
objectName = ObjectDefinitionReaderUtils.GenerateObjectName(definition, parserContext.Registry);
objectName = readerContext.GenerateObjectName(definition);
// Register an alias for the plain object type name, if possible.
string objectTypeName = definition.ObjectTypeName;
if (objectTypeName != null
&& objectName.StartsWith(objectTypeName)
&& objectName.Length>objectTypeName.Length
&& !readerContext.Registry.IsObjectNameInUse(objectTypeName))
{
aliases.Add(objectTypeName);
}
}
#region Instrumentation
@@ -264,17 +302,76 @@ namespace Spring.Objects.Factory.Xml
if (log.IsDebugEnabled)
{
log.Debug(string.Format(
"Neither XML '{0}' nor '{1}' specified - using object " +
"class name [{2}] as the id.",
id, ObjectDefinitionConstants.IdAttribute, ObjectDefinitionConstants.NameAttribute));
"Neither XML '{0}' nor '{1}' specified - using generated object name [{2}]",
ObjectDefinitionConstants.IdAttribute, ObjectDefinitionConstants.NameAttribute, objectName));
}
#endregion
}
string[] aliasesArray = (string[])aliases.ToArray(typeof(string));
return new ObjectDefinitionHolder(definition, objectName, aliasesArray);
return CreateObjectDefinitionHolder(element, definition, objectName, aliasesArray);
}
return null;
return null;
}
/// <summary>
/// Create an <see cref="ObjectDefinitionHolder"/> instance from the given <paramref name="definition"/> and <paramref name="objectName"/>.
/// </summary>
/// <remarks>
/// This method may be used as a last resort to post-process an object definition before it gets added to the registry.
/// </remarks>
protected virtual ObjectDefinitionHolder CreateObjectDefinitionHolder(XmlElement element, IConfigurableObjectDefinition definition, string objectName, string[] aliasesArray)
{
return new ObjectDefinitionHolder(definition, objectName, aliasesArray);
}
/// <summary>
/// Allows deriving classes to post process the name and aliases for the current element. By default
/// does nothing and returns the unmodified <paramref name="objectName"/>.
/// </summary>
/// <remarks>
/// The <paramref name="aliases"/> list passed in may be modified by an implementation of this method to reflect special needs.
/// </remarks>
/// <param name="objectName">the object name obtained by the default algorithm from 'id' and 'name' attributes so far.</param>
/// <param name="aliases">the object aliases obtained by the default algorithm from 'name' attribute so far.</param>
/// <param name="element">the currently processed element.</param>
/// <param name="containingDefinition">the containing object definition, may be <c>null</c></param>
/// <returns>the new object name to be used.</returns>
protected virtual string PostProcessObjectNameAndAliases(string objectName, ArrayList aliases, XmlElement element, IObjectDefinition containingDefinition)
{
if (!StringUtils.HasText(objectName) && aliases.Count == 0)
{
string result = this.objectsNamespaceParser.CalculateId(element, aliases);
if (result != null)
{
return result;
}
}
return objectName;
}
/// <summary>
/// Validate that the specified object name and aliases have not been used already.
/// </summary>
protected virtual void CheckNameUniqueness(string objectName, ArrayList aliases, XmlElement element)
{
string foundName = null;
if (StringUtils.HasText(objectName) && this.usedNames.Contains(objectName))
{
foundName = objectName;
}
if (foundName == null)
{
foundName = (string) CollectionUtils.FindFirstMatch(this.usedNames, aliases);
}
if(foundName != null)
{
Error("Object name '" + foundName + "' is already used in this file", element);
}
this.usedNames.Add(objectName);
this.usedNames.AddAll(aliases);
}
/// <summary>
@@ -321,37 +418,37 @@ namespace Spring.Objects.Factory.Xml
return StringUtils.Split(
value, ObjectDefinitionConstants.ObjectNameDelimiters, true, true);
}
/// <summary>
/// Determines whether the string represents a 'true' boolean value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// <c>true</c> if is 'true' string value; otherwise, <c>false</c>.
/// </returns>
public bool IsTrueStringValue(string value)
{
return ObjectDefinitionConstants.TrueValue.Equals(value.ToLower(CultureInfo.CurrentCulture));
}
/// <summary>
/// Convenience method to create a builder for a root object definition.
/// </summary>
/// <param name="objectTypeName">Name of the object type.</param>
/// <returns>A builder for a root object definition.</returns>
public ObjectDefinitionBuilder CreateRootObjectDefinitionBuilder(string objectTypeName)
{
return ObjectDefinitionBuilder.RootObjectDefinition(this.readerContext.ObjectDefinitionFactory, objectTypeName);
}
/// <summary>
/// Convenience method to create a builder for a root object definition.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>a builder for a root object definition</returns>
public ObjectDefinitionBuilder CreateRootObjectDefinitionBuilder(Type objectType)
{
return ObjectDefinitionBuilder.RootObjectDefinition(this.readerContext.ObjectDefinitionFactory, objectType);
/// <summary>
/// Determines whether the string represents a 'true' boolean value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// <c>true</c> if is 'true' string value; otherwise, <c>false</c>.
/// </returns>
public bool IsTrueStringValue(string value)
{
return ObjectDefinitionConstants.TrueValue.Equals(value.ToLower(CultureInfo.CurrentCulture));
}
/// <summary>
/// Convenience method to create a builder for a root object definition.
/// </summary>
/// <param name="objectTypeName">Name of the object type.</param>
/// <returns>A builder for a root object definition.</returns>
public ObjectDefinitionBuilder CreateRootObjectDefinitionBuilder(string objectTypeName)
{
return ObjectDefinitionBuilder.RootObjectDefinition(this.readerContext.ObjectDefinitionFactory, objectTypeName);
}
/// <summary>
/// Convenience method to create a builder for a root object definition.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>a builder for a root object definition</returns>
public ObjectDefinitionBuilder CreateRootObjectDefinitionBuilder(Type objectType)
{
return ObjectDefinitionBuilder.RootObjectDefinition(this.readerContext.ObjectDefinitionFactory, objectType);
}
/// <summary>
@@ -385,14 +482,14 @@ namespace Spring.Objects.Factory.Xml
return element.GetAttribute(attributeName);
}
return defaultValue;
}
}
/// <summary>
/// Report a parser error.
/// </summary>
protected virtual void Error(string message, XmlElement element)
protected virtual void Error(string message, XmlElement element)
{
this.ReaderContext.ReportFatalException(element, message);
}
}
}
}
}
}

View File

@@ -384,54 +384,7 @@ namespace Spring.Objects.Factory.Xml
[Obsolete("not used anymore - ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead", false)]
protected ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element, ParserContext parserContext, bool nestedDefinition)
{
string id = GetAttributeValue(element, ObjectDefinitionConstants.IdAttribute);
string nameAttr = GetAttributeValue(element, ObjectDefinitionConstants.NameAttribute);
ArrayList aliases = new ArrayList();
if (StringUtils.HasText(nameAttr))
{
aliases.AddRange(GetObjectNames(nameAttr));
}
// if we ain't got an id, check if object is page definition or assign any existing (first) alias...
string objectName = id;
if (StringUtils.IsNullOrEmpty(objectName))
{
// TODO (EE): pass parserContext to CalculateId as well (resolving relative Urls in WebApps is parserContext-dependent) (EE)
objectName = CalculateId(element, aliases);
}
IConfigurableObjectDefinition definition = ParseObjectDefinitionElement(element, objectName, parserContext);
if (definition != null)
{
if (StringUtils.IsNullOrEmpty(objectName))
{
if (nestedDefinition)
{
objectName =
ObjectDefinitionReaderUtils.GenerateObjectName(definition, parserContext.Registry, true);
}
else
{
objectName = ObjectDefinitionReaderUtils.GenerateObjectName(definition, parserContext.Registry);
}
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format(
"Neither XML '{0}' nor '{1}' specified - using object " +
"class name [{2}] as the id.",
id, ObjectDefinitionConstants.IdAttribute, ObjectDefinitionConstants.NameAttribute));
}
#endregion
}
string[] aliasesArray = (string[])aliases.ToArray(typeof(string));
return new ObjectDefinitionHolder(definition, objectName, aliasesArray);
}
return null;
return parserContext.ParserHelper.ParseObjectDefinitionElement(element, parserContext.ContainingObjectDefinition);
}
/// <summary>
@@ -453,32 +406,10 @@ namespace Spring.Objects.Factory.Xml
/// <returns>
/// A calculated object definition id.
/// </returns>
[Obsolete("This method will be dropped, override ObjectDefinitionParserHelper.PostProcessObjectNameAndAliases instead", false)]
protected internal virtual string CalculateId(XmlElement element, ArrayList aliases)
{
string id = null;
if (aliases.Count > 0)
{
string firstAlias = aliases[0] as string;
aliases.RemoveAt(0);
id = firstAlias;
}
#region Instrumentation
if (log.IsDebugEnabled)
{
StringBuilder buffer = new StringBuilder();
foreach (string alias in aliases)
{
buffer.Append(alias).Append(",");
}
log.Debug(string.Format("No XML 'id' specified - using '{0}' as the id and '{1}' as aliases.",
id, buffer.ToString()));
}
#endregion
return id;
return null;
}
/// <summary>
@@ -514,12 +445,12 @@ namespace Spring.Objects.Factory.Xml
= parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition(
typeName, parent, parserContext.ReaderContext.Reader.Domain);
ParserContext childParserContext = new ParserContext(parserContext.ParserHelper, od);
MutablePropertyValues pvs = ParsePropertyElements(id, element, parserContext);
ConstructorArgumentValues arguments
= ParseConstructorArgSubElements(id, element, parserContext);
EventValues events = ParseEventHandlerSubElements(id, element, parserContext);
MethodOverrides methodOverrides = ParseMethodOverrideSubElements(id, element, parserContext);
MutablePropertyValues pvs = ParsePropertyElements(id, element, childParserContext);
ConstructorArgumentValues arguments = ParseConstructorArgSubElements(id, element, childParserContext);
EventValues events = ParseEventHandlerSubElements(id, element, childParserContext);
MethodOverrides methodOverrides = ParseMethodOverrideSubElements(id, element, childParserContext);
bool isPage = StringUtils.HasText(typeName) && typeName != null && typeName.ToLower().EndsWith(".aspx");
if (!isPage)
@@ -540,13 +471,13 @@ namespace Spring.Objects.Factory.Xml
string dependencyCheck = GetAttributeValue(element, ObjectDefinitionConstants.DependencyCheckAttribute);
if (ObjectDefinitionConstants.DefaultValue.Equals(dependencyCheck))
{
dependencyCheck = parserContext.ParserHelper.Defaults.DependencyCheck;
dependencyCheck = childParserContext.ParserHelper.Defaults.DependencyCheck;
}
od.DependencyCheck = GetDependencyCheck(dependencyCheck);
string autowire = GetAttributeValue(element, ObjectDefinitionConstants.AutowireAttribute);
if (ObjectDefinitionConstants.DefaultValue.Equals(autowire))
{
autowire = parserContext.ParserHelper.Defaults.Autowire;
autowire = childParserContext.ParserHelper.Defaults.Autowire;
}
od.AutowireMode = GetAutowireMode(autowire);
string initMethodName = GetAttributeValue(element, ObjectDefinitionConstants.InitMethodAttribute);
@@ -567,12 +498,12 @@ namespace Spring.Objects.Factory.Xml
if (ObjectDefinitionConstants.DefaultValue.Equals(lazyInit) && od.IsSingleton)
{
// just apply default to singletons, as lazy-init has no meaning for prototypes...
lazyInit = parserContext.ParserHelper.Defaults.LazyInit;
lazyInit = childParserContext.ParserHelper.Defaults.LazyInit;
}
od.IsLazyInit = IsTrueStringValue(lazyInit);
// try to get the line info
string resourceDescription = parserContext.ParserHelper.ReaderContext.Resource.Description;
string resourceDescription = childParserContext.ParserHelper.ReaderContext.Resource.Description;
if (StringUtils.HasText(resourceDescription))
{
int line = ConfigurationUtils.GetLineNumber(element);
@@ -940,7 +871,7 @@ namespace Spring.Objects.Factory.Xml
{
case ObjectDefinitionConstants.ObjectElement:
{
return ParseObjectDefinitionElement(element, parserContext, true);
return parserContext.ParserHelper.ParseObjectDefinitionElement(element, parserContext.ContainingObjectDefinition);
}
case ObjectDefinitionConstants.RefElement:
{
@@ -986,35 +917,38 @@ namespace Spring.Objects.Factory.Xml
"Unknown subelement of <property>: <" + element.Name + ">");
}
}
// it may match another Parser
INamespaceParser otherParser = GetParser(element.NamespaceURI);
if (otherParser != null)
{
// The other parser uses nestings tags and thus returns the definition
// of the parsed object.
return otherParser.ParseElement(element, new ParserContext(parserContext.ParserHelper));
}
throw new ObjectDefinitionStoreException(
parserContext.ReaderContext.Resource,
name,
"Unknown subelement of <property>: <" + element.Name + ">");
return parserContext.ParserHelper.ParseCustomElement(element, parserContext.ContainingObjectDefinition);
// parserContext.ParserHelper.parse
// // it may match another Parser
// INamespaceParser otherParser = parserContext. (element.NamespaceURI);
// if (otherParser != null)
// {
// // The other parser uses nestings tags and thus returns the definition
// // of the parsed object.
// return otherParser.ParseElement(element, new ParserContext(parserContext.ParserHelper));
// }
//
// throw new ObjectDefinitionStoreException(
// parserContext.ReaderContext.Resource,
// name,
// "Unknown subelement of <property>: <" + element.Name + ">");
}
private static INamespaceParser GetParser(string nspace)
{
// finds the configuration parser for the given namespace
try
{
return NamespaceParserRegistry.GetParser(nspace);
}
catch (Exception)
{
// The parser for the given namespace is not found
return null;
}
}
// private static INamespaceParser GetParser(string nspace)
// {
// // finds the configuration parser for the given namespace
// try
// {
// return NamespaceParserRegistry.GetParser(nspace);
// }
// catch (Exception)
// {
// // The parser for the given namespace is not found
// return null;
// }
// }
private static object ParseIdReference(XmlElement element, ObjectDefinitionParserHelper parserHelper, string name)
{

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright 2002-2005 the original author or authors.
*
@@ -14,56 +14,57 @@
* 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.Xml;
using System.Xml.Schema;
using Spring.Core.IO;
using Spring.Objects.Factory.Support;
using Spring.Util;
#endregion
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Object definition reader for Spring's default XML object definition format.
/// </summary>
/// <remarks>
/// <p>
/// Typically applied to a
/// <see cref="Spring.Objects.Factory.Support.DefaultListableObjectFactory"/> instance.
/// </p>
/// <p>
/// This class registers each object definition with the given object factory superclass,
/// and relies on the latter's implementation of the
/// <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/> interface.
/// </p>
/// <p>
/// It supports singletons, prototypes, and references to either of these kinds of object.
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public class XmlObjectDefinitionReader : AbstractObjectDefinitionReader
{
*/
#endregion
#region Imports
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using Spring.Core.IO;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
#endregion
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Object definition reader for Spring's default XML object definition format.
/// </summary>
/// <remarks>
/// <p>
/// Typically applied to a
/// <see cref="Spring.Objects.Factory.Support.DefaultListableObjectFactory"/> instance.
/// </p>
/// <p>
/// This class registers each object definition with the given object factory superclass,
/// and relies on the latter's implementation of the
/// <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/> interface.
/// </p>
/// <p>
/// It supports singletons, prototypes, and references to either of these kinds of object.
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public class XmlObjectDefinitionReader : AbstractObjectDefinitionReader
{
#region Utility Classes
/// <summary>
/// For retrying the parse process
/// </summary>
private class RetryParseException : Exception
/// </summary>
private class RetryParseException : Exception
{
public RetryParseException()
{}
}
{ }
}
#if !NET_2_0
private class ValidationEventHandlerWrapper
{
@@ -85,208 +86,266 @@ namespace Spring.Objects.Factory.Xml
_owner.HandleValidation(_sender,args);
}
}
#endif
#endif
#endregion
#region Fields
[NonSerialized]
private XmlResolver resolver;
private Type documentReaderType = typeof (DefaultObjectDefinitionDocumentReader);
#endregion
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
public XmlObjectDefinitionReader(IObjectDefinitionRegistry registry)
: this(registry, new XmlUrlResolver())
{}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
/// <param name="resolver">
/// The <see cref="System.Xml.XmlResolver"/>to be used for parsing.
/// </param>
public XmlObjectDefinitionReader(IObjectDefinitionRegistry registry, XmlResolver resolver) : base(registry)
{
Resolver = resolver;
}
#endregion
#region Properties
/// <summary>
/// The <see cref="System.Xml.XmlResolver"/>to be used for parsing.
/// </summary>
public XmlResolver Resolver
{
get { return resolver; }
set { resolver = value; }
}
/// <summary>
/// Sets the IObjectDefinitionDocumentReader implementation to use, responsible for
/// the actual reading of the XML object definition document.stype of the document reader.
/// </summary>
/// <value>The type of the document reader.</value>
public Type DocumentReaderType
{
set
{
if (value == null || !typeof(IObjectDefinitionDocumentReader).IsAssignableFrom(value))
{
throw new ArgumentException(
"DocumentReaderType must be an implementation of the IObjectDefinitionReader interface.");
}
documentReaderType = value;
}
}
#endregion
#region Methods
/// <summary>
/// Load object definitions from the supplied XML <paramref name="resource"/>.
/// </summary>
/// <param name="resource">
/// The XML resource for the object definitions that are to be loaded.
/// </param>
/// <returns>
/// The number of object definitions that were loaded.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of loading or parsing errors.
/// </exception>
public override int LoadObjectDefinitions(IResource resource)
{
if (resource == null)
{
throw new ObjectDefinitionStoreException
("Resource cannot be null: expected an XML resource.");
}
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Loading XML object definitions from " + resource);
}
#endregion
try
{
Stream stream = resource.InputStream;
if (stream == null)
{
throw new ObjectDefinitionStoreException(
"InputStream is null from Resource = [" + resource + "]");
}
try
{
return DoLoadObjectDefinitions(stream, resource);
}
finally
{
#region Close stream
try
{
stream.Close();
}
catch (IOException ex)
{
#region Instrumentation
if (log.IsWarnEnabled)
{
log.Warn("Could not close stream.", ex);
}
#endregion
}
#endregion
}
}
catch (IOException ex)
{
throw new ObjectDefinitionStoreException(
"IOException parsing XML document from " + resource.Description, ex);
}
}
/// <summary>
/// Actually load object definitions from the specified XML file.
/// </summary>
/// <param name="stream">The input stream to read from.</param>
/// <param name="resource">The resource for the XML data.</param>
/// <returns></returns>
protected virtual int DoLoadObjectDefinitions(Stream stream, IResource resource)
{
try
{
// create local copy of data
byte[] xmlData = IOUtils.ToByteArray( stream );
#region Fields
[NonSerialized]
private XmlResolver resolver;
private Type documentReaderType;
private INamespaceParserResolver namespaceParserResolver;
private IObjectDefinitionFactory objectDefinitionFactory;
#endregion
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
public XmlObjectDefinitionReader(IObjectDefinitionRegistry registry)
: this(registry, new XmlUrlResolver())
{ }
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
/// <param name="resolver">
/// The <see cref="System.Xml.XmlResolver"/>to be used for parsing.
/// </param>
public XmlObjectDefinitionReader(IObjectDefinitionRegistry registry, XmlResolver resolver)
: this(registry, resolver, new DefaultObjectDefinitionFactory())
{
Resolver = resolver;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
/// <param name="resolver">
/// The <see cref="System.Xml.XmlResolver"/>to be used for parsing.
/// </param>
/// <param name="objectDefinitionFactory">the <see cref="IObjectDefinitionFactory"/> to use for creating new <see cref="IObjectDefinition"/>s</param>
protected XmlObjectDefinitionReader(IObjectDefinitionRegistry registry, XmlResolver resolver, IObjectDefinitionFactory objectDefinitionFactory)
: base(registry)
{
Resolver = resolver;
this.objectDefinitionFactory = objectDefinitionFactory;
}
#endregion
#region Properties
/// <summary>
/// The <see cref="System.Xml.XmlResolver"/>to be used for parsing.
/// </summary>
public XmlResolver Resolver
{
get { return resolver; }
set { resolver = value; }
}
/// <summary>
/// Sets the IObjectDefinitionDocumentReader implementation to use, responsible for
/// the actual reading of the XML object definition document.stype of the document reader.
/// </summary>
/// <value>The type of the document reader.</value>
public Type DocumentReaderType
{
set
{
if (value == null || !typeof(IObjectDefinitionDocumentReader).IsAssignableFrom(value))
{
throw new ArgumentException(
"DocumentReaderType must be an implementation of the IObjectDefinitionReader interface.");
}
documentReaderType = value;
}
}
/// <summary>
/// Specify a <see cref="INamespaceParserResolver"/> to use. If none is specified a default
/// instance will be created by <see cref="CreateDefaultNamespaceParserResolver"/>
/// </summary>
internal INamespaceParserResolver NamespaceParserResolver
{
get
{
if (this.namespaceParserResolver == null)
{
this.namespaceParserResolver = CreateDefaultNamespaceParserResolver();
}
return this.namespaceParserResolver;
}
set
{
if (this.namespaceParserResolver != null)
{
throw new InvalidOperationException("NamespaceParserResolver is already set");
}
this.namespaceParserResolver = value;
}
}
/// <summary>
/// Specify a <see cref="IObjectDefinitionFactory"/> for creating instances of <see cref="AbstractObjectDefinition"/>.
/// </summary>
protected IObjectDefinitionFactory ObjectDefinitionFactory
{
get
{
return this.objectDefinitionFactory;
}
}
#endregion
#region Methods
/// <summary>
/// Load object definitions from the supplied XML <paramref name="resource"/>.
/// </summary>
/// <param name="resource">
/// The XML resource for the object definitions that are to be loaded.
/// </param>
/// <returns>
/// The number of object definitions that were loaded.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of loading or parsing errors.
/// </exception>
public override int LoadObjectDefinitions(IResource resource)
{
if (resource == null)
{
throw new ObjectDefinitionStoreException
("Resource cannot be null: expected an XML resource.");
}
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Loading XML object definitions from " + resource);
}
#endregion
try
{
Stream stream = resource.InputStream;
if (stream == null)
{
throw new ObjectDefinitionStoreException(
"InputStream is null from Resource = [" + resource + "]");
}
try
{
return DoLoadObjectDefinitions(stream, resource);
}
finally
{
#region Close stream
try
{
stream.Close();
}
catch (IOException ex)
{
#region Instrumentation
if (log.IsWarnEnabled)
{
log.Warn("Could not close stream.", ex);
}
#endregion
}
#endregion
}
}
catch (IOException ex)
{
throw new ObjectDefinitionStoreException(
"IOException parsing XML document from " + resource.Description, ex);
}
}
/// <summary>
/// Actually load object definitions from the specified XML file.
/// </summary>
/// <param name="stream">The input stream to read from.</param>
/// <param name="resource">The resource for the XML data.</param>
/// <returns></returns>
protected virtual int DoLoadObjectDefinitions(Stream stream, IResource resource)
{
try
{
// create local copy of data
byte[] xmlData = IOUtils.ToByteArray(stream);
XmlDocument doc;
// loop until no unregistered, wellknown namespaces left
while(true)
while (true)
{
XmlReader reader = null;
try
{
MemoryStream xmlDataStream = new MemoryStream(xmlData);
reader = CreateValidatingReader(xmlDataStream);
doc = new ConfigXmlDocument();
doc.Load(reader);
break;
reader = CreateValidatingReader(xmlDataStream);
doc = new ConfigXmlDocument();
doc.Load(reader);
break;
}
catch(RetryParseException)
catch (RetryParseException)
{
if (reader != null) reader.Close();
if (reader != null)
reader.Close();
}
}
return RegisterObjectDefinitions(doc, resource);
}
catch (XmlException ex)
{
throw new ObjectDefinitionStoreException(resource.Description,
"Line " + ex.LineNumber + " in XML document from " +
resource + " is not well formed. " + ex.Message, ex);
}
catch (XmlSchemaException ex)
{
throw new ObjectDefinitionStoreException(resource.Description,
"Line " + ex.LineNumber + " in XML document from " +
resource + " violates the schema. " + ex.Message, ex);
}
catch(ObjectDefinitionStoreException)
{
throw;
}
catch (Exception ex)
{
throw new ObjectDefinitionStoreException("Unexpected exception parsing XML document from " + resource.Description + "Inner exception message= " + ex.Message, ex);
}
return RegisterObjectDefinitions(doc, resource);
}
catch (XmlException ex)
{
throw new ObjectDefinitionStoreException(resource.Description,
"Line " + ex.LineNumber + " in XML document from " +
resource + " is not well formed. " + ex.Message, ex);
}
catch (XmlSchemaException ex)
{
throw new ObjectDefinitionStoreException(resource.Description,
"Line " + ex.LineNumber + " in XML document from " +
resource + " violates the schema. " + ex.Message, ex);
}
catch (ObjectDefinitionStoreException)
{
throw;
}
catch (Exception ex)
{
throw new ObjectDefinitionStoreException("Unexpected exception parsing XML document from " + resource.Description + "Inner exception message= " + ex.Message, ex);
}
}
private XmlReader CreateValidatingReader(MemoryStream stream)
@@ -297,7 +356,7 @@ namespace Spring.Objects.Factory.Xml
reader = XmlUtils.CreateReader(stream);
}
else
{
{
#if !NET_2_0
// only because 1.0/1.1 don't pass the sender into the handler callback...
ValidationEventHandlerWrapper validationEventHandlerWrapper = new ValidationEventHandlerWrapper(this);
@@ -305,116 +364,134 @@ namespace Spring.Objects.Factory.Xml
new ValidationEventHandler(validationEventHandlerWrapper.HandleValidation));
validationEventHandlerWrapper.Reader = reader;
#else
reader = XmlUtils.CreateValidatingReader(stream, Resolver, NamespaceParserRegistry.GetSchemas(), HandleValidation);
#endif
}
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Using the following XmlReader implementation : " + reader.GetType());
reader = XmlUtils.CreateValidatingReader(stream, Resolver, NamespaceParserRegistry.GetSchemas(), HandleValidation);
#endif
}
return reader;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Using the following XmlReader implementation : " + reader.GetType());
}
return reader;
#endregion
}
/// <summary>
/// Validation callback for a validating XML reader.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">Any data pertinent to the event.</param>
private void HandleValidation(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
{
XmlSchemaException ex = args.Exception;
XmlReader xmlReader = (XmlReader) sender;
}
/// <summary>
/// Validation callback for a validating XML reader.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="args">Any data pertinent to the event.</param>
private void HandleValidation(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
{
XmlSchemaException ex = args.Exception;
XmlReader xmlReader = (XmlReader)sender;
if (!NamespaceParserRegistry.GetSchemas().Contains(xmlReader.NamespaceURI)
#if NET_2_0
&& ex is XmlSchemaValidationException
&& ex is XmlSchemaValidationException
#endif
)
)
{
// try wellknown parsers
bool registered = NamespaceParserRegistry.RegisterWellknownNamespaceParserType(xmlReader.NamespaceURI);
if (registered)
{
{
throw new RetryParseException();
}
}
}
#if !NET_2_0
// ignore validation errors for well-known 'xml' namespace. This seems to be a bug in net 1.0 + 1.1
if (ex.Message.IndexOf("http://www.w3.org/XML/1998/namespace:") > -1)
{
return;
}
#endif
throw ex;
}
else
{
#region Instrumentation
if (log.IsWarnEnabled)
{
log.Warn(
"Ignored XML validation warning: " + args.Message,
args.Exception);
}
#endregion
}
}
/// <summary>
/// Register the object definitions contained in the given DOM document.
/// </summary>
/// <param name="doc">The DOM document.</param>
/// <param name="resource">
/// The original resource from where the <see cref="System.Xml.XmlDocument"/>
/// was read.
/// </param>
/// <returns>
/// The number of object definitions that were registered.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of parsing errors.
/// </exception>
public int RegisterObjectDefinitions(
XmlDocument doc, IResource resource)
{
IObjectDefinitionDocumentReader documentReader = CreateObjectDefinitionDocumentReader();
//TODO make void return and get object count from registry.
int countBefore = Registry.ObjectDefinitionCount;
documentReader.RegisterObjectDefinitions(doc, CreateReaderContext(resource));
return Registry.ObjectDefinitionCount - countBefore;
}
/// <summary>
/// Creates the <see cref="IObjectDefinitionDocumentReader"/> to use for actually
/// reading object definitions from an XML document.
/// </summary>
/// <remarks>Default implementation instantiates the specified 'documentReaderType'.</remarks>
/// <returns></returns>
protected virtual IObjectDefinitionDocumentReader CreateObjectDefinitionDocumentReader()
{
return (IObjectDefinitionDocumentReader) ObjectUtils.InstantiateType(documentReaderType);
}
/// <summary>
/// Creates the <see cref="XmlReaderContext"/> to be passed along
/// during the object definition reading process.
/// </summary>
/// <param name="resource">The underlying <see cref="IResource"/> that is currently processed.</param>
/// <returns>A new <see cref="XmlReaderContext"/></returns>
protected virtual XmlReaderContext CreateReaderContext(IResource resource)
{
return new XmlReaderContext(resource, this);
}
#endregion
}
}
#endif
throw ex;
}
else
{
#region Instrumentation
if (log.IsWarnEnabled)
{
log.Warn(
"Ignored XML validation warning: " + args.Message,
args.Exception);
}
#endregion
}
}
/// <summary>
/// Register the object definitions contained in the given DOM document.
/// </summary>
/// <param name="doc">The DOM document.</param>
/// <param name="resource">
/// The original resource from where the <see cref="System.Xml.XmlDocument"/>
/// was read.
/// </param>
/// <returns>
/// The number of object definitions that were registered.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of parsing errors.
/// </exception>
public int RegisterObjectDefinitions(
XmlDocument doc, IResource resource)
{
IObjectDefinitionDocumentReader documentReader = CreateObjectDefinitionDocumentReader();
//TODO make void return and get object count from registry.
int countBefore = Registry.ObjectDefinitionCount;
XmlReaderContext readerContext = CreateReaderContext(resource);
readerContext.NamespaceParserResolver = this.NamespaceParserResolver;
documentReader.RegisterObjectDefinitions(doc, readerContext);
return Registry.ObjectDefinitionCount - countBefore;
}
/// <summary>
/// Creates the <see cref="IObjectDefinitionDocumentReader"/> to use for actually
/// reading object definitions from an XML document.
/// </summary>
/// <remarks>Default implementation instantiates the specified <see cref="DocumentReaderType"/>
/// or <see cref="DefaultObjectDefinitionDocumentReader"/> if no reader type is specified.</remarks>
/// <returns></returns>
protected virtual IObjectDefinitionDocumentReader CreateObjectDefinitionDocumentReader()
{
if (documentReaderType == null)
{
return new DefaultObjectDefinitionDocumentReader();
}
return (IObjectDefinitionDocumentReader)ObjectUtils.InstantiateType(documentReaderType);
}
/// <summary>
/// Creates the <see cref="XmlReaderContext"/> to be passed along
/// during the object definition reading process.
/// </summary>
/// <param name="resource">The underlying <see cref="IResource"/> that is currently processed.</param>
/// <returns>A new <see cref="XmlReaderContext"/></returns>
protected virtual XmlReaderContext CreateReaderContext(IResource resource)
{
return new XmlReaderContext(resource, this, this.objectDefinitionFactory);
}
/// <summary>
/// Create a <see cref="INamespaceParserResolver"/> instance for handling custom namespaces.
/// </summary>
/// <remarks>
/// TODO (EE): make protected virtual, see remarks on <see cref="INamespaceParserResolver"/>
/// </remarks>
private INamespaceParserResolver CreateDefaultNamespaceParserResolver()
{
return new DefaultNamespaceHandlerResolver();
}
#endregion
}
}

View File

@@ -29,18 +29,14 @@ using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// Extension of <see cref="ReaderContext"/> specific to use with an
/// XmlObjectDefinitionReader.
/// Extension of <see cref="ReaderContext"/> specific to use with an XmlObjectDefinitionReader.
/// Provides access to <see cref="NamespaceParserResolver"/> configured in <see cref="XmlObjectDefinitionReader"/>
/// </summary>
/// <remarks>In future will contain access to IXmlParserRegistry</remarks>
public class XmlReaderContext : ReaderContext
{
//TODO: Should have a ref to NamespaceParserRegistry, i.e. NamespaceHandlerResolver here....
private IObjectDefinitionReader reader;
private IObjectDefinitionFactory objectDefinitionFactory = new DefaultObjectDefinitionFactory();
private readonly IObjectDefinitionReader reader;
private readonly IObjectDefinitionFactory objectDefinitionFactory;
private INamespaceParserResolver namespaceParserResolver;
/// <summary>
/// The maximum length of any XML fragment displayed in the error message
@@ -54,18 +50,32 @@ namespace Spring.Objects.Factory.Xml
/// </remarks>
private const int MaxXmlErrorFragmentLength = 255;
/// <summary>
/// Initializes a new instance of the <see cref="XmlReaderContext"/> class.
/// </summary>
/// <param name="resource">The resource.</param>
/// <param name="reader">The reader.</param>
public XmlReaderContext(IResource resource, IObjectDefinitionReader reader)
: this(resource, reader, new DefaultObjectDefinitionFactory())
{}
/// <summary>
/// Initializes a new instance of the <see cref="XmlReaderContext"/> class.
/// </summary>
/// <param name="resource">The resource.</param>
/// <param name="reader">The reader.</param>
public XmlReaderContext(IResource resource, IObjectDefinitionReader reader) : base(resource)
/// <param name="objectDefinitionFactory">The factory to use for creating new <see cref="IObjectDefinition"/> instances.</param>
internal XmlReaderContext(IResource resource, IObjectDefinitionReader reader, IObjectDefinitionFactory objectDefinitionFactory)
: base(resource)
{
this.reader = reader;
if (reader is XmlObjectDefinitionReader)
{
this.namespaceParserResolver = ((XmlObjectDefinitionReader) reader).NamespaceParserResolver;
}
this.objectDefinitionFactory = objectDefinitionFactory;
}
/// <summary>
/// Gets the reader.
/// </summary>
@@ -96,7 +106,6 @@ namespace Spring.Objects.Factory.Xml
}
}
/// <summary>
/// Gets or sets the object definition factory.
/// </summary>
@@ -104,10 +113,16 @@ namespace Spring.Objects.Factory.Xml
public IObjectDefinitionFactory ObjectDefinitionFactory
{
get { return objectDefinitionFactory; }
set { objectDefinitionFactory = value; }
}
/// <summary>
/// Get the <see cref="INamespaceParserResolver"/> instance to lookup parsers for custom namespaces.
/// </summary>
internal INamespaceParserResolver NamespaceParserResolver
{
get { return namespaceParserResolver; }
set { namespaceParserResolver = value; }
}
/// <summary>
/// Generates the name of the object.

View File

@@ -600,6 +600,8 @@
<Compile Include="Objects\Factory\Xml\AbstractObjectDefinitionParser.cs" />
<Compile Include="Objects\Factory\Xml\AbstractSimpleObjectDefinitionParser.cs" />
<Compile Include="Objects\Factory\Xml\AbstractSingleObjectDefinitionParser.cs" />
<Compile Include="Objects\Factory\Xml\DefaultNamespaceHandlerResolver.cs" />
<Compile Include="Objects\Factory\Xml\INamespaceParserResolver.cs" />
<Compile Include="Objects\Factory\Xml\NamespaceParserAttribute.cs" />
<Compile Include="Objects\Factory\Xml\ObjectFactorySectionHandler.cs" />
<Compile Include="Objects\Factory\Xml\DocumentDefaultsDefinition.cs" />

View File

@@ -72,9 +72,10 @@ namespace Spring.Util
/// <returns><see lang="true"/> if the element is in the collection, <see lang="false"/> otherwise.</returns>
public static bool Contains(ICollection collection, Object element)
{
// TODO (EE): does not match Spring/J behavior. Change to IEnumerable and enumerable may be null
if (collection == null)
{
throw new ArgumentNullException("Collection cannot be null.");
throw new ArgumentNullException("collection", "Collection cannot be null.");
}
MethodInfo method;
method = collection.GetType().GetMethod("contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
@@ -92,17 +93,32 @@ namespace Spring.Util
/// <param name="element">The object to add to the collection.</param>
public static void Add(ICollection collection, object element)
{
if (collection == null)
Add((IEnumerable)collection, element);
}
/// <summary>
/// Adds the specified <paramref name="element"/> to the specified <paramref name="enumerable"/> .
/// </summary>
/// <param name="enumerable">The enumerable to add the element to.</param>
/// <param name="element">The object to add to the collection.</param>
public static void Add(IEnumerable enumerable, object element)
{
if (enumerable == null)
{
throw new ArgumentNullException("Collection cannot be null.");
throw new ArgumentNullException("enumerable", "Collection cannot be null.");
}
if (enumerable is IList)
{
((IList)enumerable).Add(element);
return;
}
MethodInfo method;
method = collection.GetType().GetMethod("add", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
method = enumerable.GetType().GetMethod("add", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
if (null == method)
{
throw new InvalidOperationException("Collection type " + collection.GetType() + " does not implement a Add() method.");
throw new InvalidOperationException("Enumerable type " + enumerable.GetType() + " does not implement a Add() method.");
}
method.Invoke(collection, new Object[] { element });
method.Invoke(enumerable, new Object[] { element });
}
/// <summary>
@@ -113,9 +129,13 @@ namespace Spring.Util
/// <returns>true if the target collection contains all the elements of the specified collection.</returns>
public static bool ContainsAll(ICollection targetCollection, ICollection sourceCollection)
{
if (targetCollection == null || sourceCollection == null)
if (targetCollection == null)
{
throw new ArgumentNullException("Collection cannot be null.");
throw new ArgumentNullException("targetCollection", "Collection cannot be null.");
}
if (sourceCollection == null)
{
throw new ArgumentNullException("sourceCollection", "Collection cannot be null.");
}
if (sourceCollection.Count == 0 && targetCollection.Count > 1)
return true;
@@ -213,6 +233,47 @@ namespace Spring.Util
return array;
}
/// <summary>
/// Returns the first element contained in both, <paramref name="source"/> and <paramref name="candidates"/>.
/// </summary>
/// <remarks>The implementation assumes that <paramref name="candidates"/> &lt;&lt;&lt; <paramref name="source"/></remarks>
/// <param name="source">the source enumerable. may be <c>null</c></param>
/// <param name="candidates">the list of candidates to match against <paramref name="source"/> elements. may be <c>null</c></param>
/// <returns>the first element found in both enumerables or <c>null</c></returns>
public static object FindFirstMatch(IEnumerable source, IEnumerable candidates)
{
if (IsEmpty(source) || IsEmpty(candidates))
{
return null;
}
IList candidateList = candidates as IList;
if (candidateList == null)
{
if (candidates is ICollection)
{
candidateList = new ArrayList((ICollection)candidates);
}
else
{
candidateList = new ArrayList();
foreach (object el in candidates)
{
candidateList.Add(el);
}
}
}
foreach (object sourceElement in source)
{
if (candidateList.Contains(sourceElement))
{
return sourceElement;
}
}
return null;
}
/// <summary>
/// Finds a value of the given type in the given collection.
/// </summary>
@@ -268,6 +329,31 @@ namespace Spring.Util
return null;
}
/// <summary>
/// Determines whether the specified collection is null or empty.
/// </summary>
/// <param name="enumerable">The collection to check.</param>
/// <returns>
/// <c>true</c> if the specified collection is empty or null; otherwise, <c>false</c>.
/// </returns>
public static bool IsEmpty(IEnumerable enumerable)
{
if (enumerable == null)
return true;
if (enumerable is ICollection)
{
return (0 == ((ICollection)enumerable).Count);
}
IEnumerator it = enumerable.GetEnumerator();
if (!it.MoveNext())
{
return true;
}
return false;
}
/// <summary>
/// Determines whether the specified collection is null or empty.
/// </summary>
@@ -337,11 +423,11 @@ namespace Spring.Util
ehancedInput.Sort(Entry.GetComparer(comparer));
for (int i = 0; i < ehancedInput.Count; i++ )
for (int i = 0; i < ehancedInput.Count; i++)
{
ehancedInput[i] = ((Entry) ehancedInput[i]).Value;
ehancedInput[i] = ((Entry)ehancedInput[i]).Value;
}
return ehancedInput;
}

View File

@@ -123,7 +123,15 @@ namespace Spring.Validation.Config
string parent = GetAttributeValue(element, ObjectDefinitionConstants.ParentAttribute);
string name = "validator: " + (StringUtils.HasText(id) ? id : this.definitionCount.ToString());
MutablePropertyValues properties = new MutablePropertyValues();
IConfigurableObjectDefinition od
= parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition(
typeName, parent, parserContext.ReaderContext.Reader.Domain);
od.PropertyValues = properties;
od.IsSingleton = true;
od.IsLazyInit = true;
ParseAttributeIntoProperty(element, ValidatorDefinitionConstants.TestAttribute, properties, "Test");
ParseAttributeIntoProperty(element, ValidatorDefinitionConstants.WhenAttribute, properties, "When");
@@ -141,6 +149,7 @@ namespace Spring.Validation.Config
ManagedList nestedValidators = new ManagedList();
ManagedList actions = new ManagedList();
ParserContext childParserContext = new ParserContext(parserContext.ParserHelper, od);
foreach (XmlNode node in element.ChildNodes)
{
XmlElement child = node as XmlElement;
@@ -150,19 +159,19 @@ namespace Spring.Validation.Config
{
case ValidatorDefinitionConstants.PropertyElement:
string propertyName = GetAttributeValue(child, ValidatorDefinitionConstants.PropertyNameAttribute);
properties.Add(propertyName, base.ParsePropertyValue(child, name, parserContext));
properties.Add(propertyName, base.ParsePropertyValue(child, name, childParserContext));
break;
case ValidatorDefinitionConstants.MessageElement:
actions.Add(ParseErrorMessageAction(child, parserContext));
actions.Add(ParseErrorMessageAction(child, childParserContext));
break;
case ValidatorDefinitionConstants.ActionElement:
actions.Add(ParseGenericAction(child, parserContext));
actions.Add(ParseGenericAction(child, childParserContext));
break;
case ValidatorDefinitionConstants.ReferenceElement:
nestedValidators.Add(ParseValidatorReference(child, parserContext));
nestedValidators.Add(ParseValidatorReference(child, childParserContext));
break;
default:
nestedValidators.Add(ParseAndRegisterValidator(child, parserContext));
nestedValidators.Add(ParseAndRegisterValidator(child, childParserContext));
break;
}
}
@@ -176,14 +185,6 @@ namespace Spring.Validation.Config
properties.Add("Actions", actions);
}
IConfigurableObjectDefinition od
= parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition(
typeName, parent, parserContext.ReaderContext.Reader.Domain);
od.PropertyValues = properties;
od.IsSingleton = true;
od.IsLazyInit = true;
return od;
}

View File

@@ -27,6 +27,7 @@ using System.IO;
using System.Reflection;
using System.Web;
using System.Web.Hosting;
using System.Xml;
using Common.Logging;
using Spring.Collections;
using Spring.Objects;
@@ -106,10 +107,7 @@ namespace Spring.Context.Support
// remember creation info for debug output
this._constructionTimeStamp = DateTime.Now;
if (HttpContext.Current != null)
{
this._constructionUrl = HttpContext.Current.Request.RawUrl;
}
this._constructionUrl = VirtualEnvironment.CurrentVirtualPathAndQuery;
if (log.IsDebugEnabled)
{
log.Debug("created instance " + this.ToString());
@@ -217,7 +215,7 @@ namespace Spring.Context.Support
{
get
{
string requestUrl = HttpContext.Current.Request.FilePath;
string requestUrl = VirtualEnvironment.CurrentVirtualFilePath;
return GetContextInternal(requestUrl);
}
}
@@ -351,7 +349,7 @@ namespace Spring.Context.Support
/// <param name="objectDefinitionReader">Reader to initialize.</param>
protected override void InitObjectDefinitionReader(XmlObjectDefinitionReader objectDefinitionReader)
{
NamespaceParserRegistry.RegisterParser(typeof(WebObjectsNamespaceParser));
// NamespaceParserRegistry.RegisterParser(typeof(WebObjectsNamespaceParser));
}
/// <summary>
@@ -369,6 +367,16 @@ namespace Spring.Context.Support
/// </summary>
/// <returns>Web object factory to use.</returns>
protected override DefaultListableObjectFactory CreateObjectFactory()
{
string contextPath = GetContextPathWithTrailingSlash();
return new WebObjectFactory(contextPath, this.CaseSensitive, GetInternalParentObjectFactory());
}
/// <summary>
/// Returns the application-relative virtual path of this context (without leading '~'!).
/// </summary>
/// <returns></returns>
private string GetContextPathWithTrailingSlash()
{
string contextPath = this.Name;
if (contextPath == DefaultRootContextName)
@@ -379,7 +387,16 @@ namespace Spring.Context.Support
{
contextPath = contextPath + "/";
}
return new WebObjectFactory(contextPath, this.CaseSensitive, GetInternalParentObjectFactory());
return contextPath;
}
/// <summary>
/// Create a reader instance capable of handling web objects (Pages,Controls) for importing o
/// bject definitions into the specified <paramref name="objectFactory"/>.
/// </summary>
protected override XmlObjectDefinitionReader CreateXmlObjectDefinitionReader(DefaultListableObjectFactory objectFactory)
{
return new WebObjectDefinitionReader(GetContextPathWithTrailingSlash(), objectFactory, new XmlUrlResolver());
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Web;
using Spring.Core;
@@ -97,27 +98,22 @@ namespace Spring.DataBinding
/// </param>
public override void BindSourceToTarget(object source, object target, IValidationErrors validationErrors, IDictionary variables)
{
HttpRequest request;
if (HttpContext.Current == null || (HttpContext.Current.Request) == null)
{
throw new InvalidOperationException("Cannot perform Request data binding without a valid HTTP request.");
}
request = HttpContext.Current.Request;
NameValueCollection parameters = VirtualEnvironment.RequestParams;
IList targetList = targetExpression.GetValue(target) as IList;
if (targetList == null)
{
throw new ArgumentException("Target property has to be initialized to an instance of IList interface.");
}
if (request.Params.GetValues(requestParams[0]) != null)
if (parameters.GetValues(requestParams[0]) != null)
{
int valueCount = request.Params.GetValues(requestParams[0]).Length;
int valueCount = parameters.GetValues(requestParams[0]).Length;
for (int i = 0; i < valueCount; i++)
{
IDictionary vars = new Hashtable();
foreach (string paramName in requestParams)
{
vars[paramName] = request.Params.GetValues(paramName)[i];
vars[paramName] = parameters.GetValues(paramName)[i];
}
object targetItem;

View File

@@ -58,7 +58,8 @@ namespace Spring.Objects.Factory.Support
/// The <see cref="Spring.Objects.MutablePropertyValues"/> to be applied to
/// a new instance of the object.
/// </param>
public ChildWebObjectDefinition(string parentName, Type type, ConstructorArgumentValues arguments, MutablePropertyValues properties) : base(parentName, type, arguments, properties)
public ChildWebObjectDefinition(string parentName, Type type, ConstructorArgumentValues arguments, MutablePropertyValues properties)
: base(parentName, type, arguments, properties)
{}
/// <summary>
@@ -76,7 +77,8 @@ namespace Spring.Objects.Factory.Support
/// The <see cref="Spring.Objects.MutablePropertyValues"/> to be applied to
/// a new instance of the object.
/// </param>
public ChildWebObjectDefinition(string parentName, string typeName, ConstructorArgumentValues arguments, MutablePropertyValues properties) : base(parentName, typeName, arguments, properties)
public ChildWebObjectDefinition(string parentName, string typeName, ConstructorArgumentValues arguments, MutablePropertyValues properties)
: base(parentName, typeName, arguments, properties)
{}
/// <summary>
@@ -93,7 +95,7 @@ namespace Spring.Objects.Factory.Support
public ChildWebObjectDefinition(string parentName, string pageName, MutablePropertyValues properties)
: base(parentName, WebObjectUtils.GetPageType(pageName), null, properties)
{
_pageName = WebUtils.CombineVirtualPaths(HttpContext.Current.Request.CurrentExecutionFilePath, pageName);
_pageName = WebUtils.CombineVirtualPaths(VirtualEnvironment.CurrentExecutionFilePath, pageName);
}
#endregion

View File

@@ -0,0 +1,33 @@
#region License
/*
* Copyright 2002-2009 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
using System;
namespace Spring.Objects.Factory.Support
{
/// <summary>
/// </summary>
/// <author>Erich Eichinger</author>
internal interface IWebObjectNameGenerator
{
string CreatePageDefinitionName(string virtualPath);
string CreateControlDefinitionName(string virtualPath);
}
}

View File

@@ -116,7 +116,7 @@ namespace Spring.Objects.Factory.Support
MutablePropertyValues properties)
: base(WebObjectUtils.GetPageType(pageName), null, properties)
{
_pageName = WebUtils.CombineVirtualPaths(HttpContext.Current.Request.CurrentExecutionFilePath, pageName);
_pageName = WebUtils.CombineVirtualPaths(VirtualEnvironment.CurrentExecutionFilePath, pageName);
}
/// <summary>

View File

@@ -127,6 +127,14 @@ namespace Spring.Objects.Factory.Support
#endregion
/// <summary>
/// Returns the virtual path this object factory is associated with.
/// </summary>
public string ContextPath
{
get { return contextPath; }
}
#region Convenience accessors for Http* objects
/// <summary>

View File

@@ -27,9 +27,11 @@ using System.Web.UI;
#endif
using System;
using System.IO;
using System.Web;
//using System.Web;
using Common.Logging;
using Spring.Util;
using IHttpHandler = System.Web.IHttpHandler;
using HttpException = System.Web.HttpException;
namespace Spring.Objects.Factory.Support
{
@@ -91,16 +93,16 @@ namespace Spring.Objects.Factory.Support
s_log.Debug( "creating page instance '" + pageUrl + "'" );
}
HttpContext ctx = HttpContext.Current;
if (ctx == null)
{
throw new ObjectCreationException(
"Unable to instantiate page. HttpContext is not defined." );
}
IHttpHandler page = null;
// HttpContext ctx = HttpContext.Current;
// if (ctx == null)
// {
// throw new ObjectCreationException(
// "Unable to instantiate page. HttpContext is not defined." );
// }
IHttpHandler page;
try
{
page = CreateHandler( ctx, pageUrl );
page = CreateHandler( pageUrl );
}
catch (HttpException httpEx)
{
@@ -132,25 +134,26 @@ namespace Spring.Objects.Factory.Support
/// <summary>
/// Creates the raw handler instance without any exception handling
/// </summary>
/// <param name="ctx"></param>
/// <param name="pageUrl"></param>
/// <returns></returns>
internal static IHttpHandler CreateHandler( HttpContext ctx, string pageUrl )
internal static IHttpHandler CreateHandler( string pageUrl )
{
IHttpHandler page;
#if NET_1_1
string physicalPath = ctx.Server.MapPath(pageUrl);
s_log.Debug(string.Format("constructing page virtual path '{0}' from physical file '{1}'", pageUrl, physicalPath));
page = PageParser.GetCompiledPageInstance(pageUrl, physicalPath, ctx);
#else
string rootedVPath = WebUtils.CombineVirtualPaths( ctx.Request.CurrentExecutionFilePath, pageUrl );
if (s_log.IsDebugEnabled)
{
s_log.Debug( "page vpath is " + rootedVPath );
}
page = BuildManager.CreateInstanceFromVirtualPath( rootedVPath, typeof( IHttpHandler ) ) as IHttpHandler;
#endif
// HttpContext ctx = HttpContext.Current;
//#if NET_1_1
// string physicalPath = ctx.Server.MapPath(pageUrl);
// s_log.Debug(string.Format("constructing page virtual path '{0}' from physical file '{1}'", pageUrl, physicalPath));
// page = PageParser.GetCompiledPageInstance(pageUrl, physicalPath, ctx);
//#else
// string rootedVPath = WebUtils.CombineVirtualPaths( ctx.Request.CurrentExecutionFilePath, pageUrl );
// if (s_log.IsDebugEnabled)
// {
// s_log.Debug( "page vpath is " + rootedVPath );
// }
//
// page = BuildManager.CreateInstanceFromVirtualPath( rootedVPath, typeof( IHttpHandler ) ) as IHttpHandler;
//#endif
page = VirtualEnvironment.CreateInstanceFromVirtualPath(pageUrl, typeof (IHttpHandler)) as IHttpHandler;
return page;
}
@@ -188,11 +191,11 @@ namespace Spring.Objects.Factory.Support
{
AssertUtils.ArgumentHasText( pageUrl, "pageUrl" );
HttpContext ctx = HttpContext.Current;
if (ctx == null)
{
throw new ObjectCreationException( "Unable to get page type. HttpContext is not defined." );
}
// HttpContext ctx = HttpContext.Current;
// if (ctx == null)
// {
// throw new ObjectCreationException( "Unable to get page type. HttpContext is not defined." );
// }
try
{
@@ -209,10 +212,10 @@ namespace Spring.Objects.Factory.Support
/// <summary>
/// Calls the underlying ASP.NET infrastructure to obtain the compiled page type
/// relative to the current <see cref="HttpRequest.CurrentExecutionFilePath"/>.
/// relative to the current <see cref="System.Web.HttpRequest.CurrentExecutionFilePath"/>.
/// </summary>
/// <param name="pageUrl">
/// The filename of the ASPX page relative to the current <see cref="HttpRequest.CurrentExecutionFilePath"/>
/// The filename of the ASPX page relative to the current <see cref="System.Web.HttpRequest.CurrentExecutionFilePath"/>
/// </param>
/// <returns>
/// The <see cref="System.Type"/> of the ASPX page
@@ -225,18 +228,18 @@ namespace Spring.Objects.Factory.Support
s_log.Debug( "getting page type for " + pageUrl );
}
string rootedVPath = WebUtils.CombineVirtualPaths( HttpContext.Current.Request.CurrentExecutionFilePath, pageUrl );
string rootedVPath = WebUtils.CombineVirtualPaths( VirtualEnvironment.CurrentExecutionFilePath, pageUrl );
if (s_log.IsDebugEnabled)
{
s_log.Debug( "page vpath is " + rootedVPath );
}
Type pageType = null;
#if NET_2_0
pageType = BuildManager.GetCompiledType( rootedVPath ); // requires rooted virtual path!
#else
pageType = CreatePageInstance(pageUrl).GetType();
#endif
Type pageType = VirtualEnvironment.GetCompiledType(rootedVPath);
//#if NET_2_0
// pageType = BuildManager.GetCompiledType( rootedVPath ); // requires rooted virtual path!
//#else
// pageType = CreatePageInstance(pageUrl).GetType();
//#endif
if (s_log.IsDebugEnabled)
{
@@ -257,27 +260,28 @@ namespace Spring.Objects.Factory.Support
s_log.Debug( "getting control type for " + controlName );
}
HttpContext ctx = HttpContext.Current;
if (ctx == null)
{
throw new ObjectCreationException( "Unable to get control type. HttpContext is not defined." );
}
// HttpContext ctx = HttpContext.Current;
// if (ctx == null)
// {
// throw new ObjectCreationException( "Unable to get control type. HttpContext is not defined." );
// }
string rootedVPath = WebUtils.CombineVirtualPaths( ctx.Request.CurrentExecutionFilePath, controlName );
string rootedVPath = WebUtils.CombineVirtualPaths( VirtualEnvironment.CurrentExecutionFilePath, controlName );
if (s_log.IsDebugEnabled)
{
s_log.Debug( "control vpath is " + rootedVPath );
}
Type controlType = null;
Type controlType;
try
{
#if NET_2_0
controlType = BuildManager.GetCompiledType( rootedVPath ); // requires rooted virtual path!
#else
controlType = (Type) miGetCompiledUserControlType.Invoke(null, new object[] { rootedVPath, null, ctx });
#endif
//#if NET_2_0
// controlType = BuildManager.GetCompiledType( rootedVPath ); // requires rooted virtual path!
//#else
// controlType = (Type) miGetCompiledUserControlType.Invoke(null, new object[] { rootedVPath, null, ctx });
//#endif
controlType = VirtualEnvironment.GetCompiledType(rootedVPath);
}
catch (HttpException httpEx)
{

View File

@@ -0,0 +1,49 @@
#region License
/*
* Copyright 2002-2009 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
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// An <see cref="DefaultObjectDefinitionDocumentReader"/> capable of handling web objects (Pages,Controls).
/// </summary>
/// <author>Erich Eichinger</author>
internal class WebObjectDefinitionDocumentReader : DefaultObjectDefinitionDocumentReader
{
private readonly IWebObjectNameGenerator webObjectNameGenerator;
public WebObjectDefinitionDocumentReader(IWebObjectNameGenerator webObjectNameGenerator)
{
AssertUtils.ArgumentNotNull(webObjectNameGenerator, "webObjectNameGenerator");
this.webObjectNameGenerator = webObjectNameGenerator;
}
/// <summary>
/// Creates an <see cref="WebObjectDefinitionParserHelper"/> instance for the given
/// <paramref name="readerContext"/> and <paramref name="root"/> element.
/// </summary>
protected override ObjectDefinitionParserHelper CreateHelper(XmlReaderContext readerContext, System.Xml.XmlElement root)
{
return new WebObjectDefinitionParserHelper(webObjectNameGenerator, readerContext, root);
}
}
}

View File

@@ -0,0 +1,149 @@
#region License
/*
* Copyright 2002-2009 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
using System;
using System.Xml;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// An <see cref="ObjectDefinitionParserHelper"/> capable of handling web objects (Pages,Controls)
/// </summary>
/// <author>Erich Eichinger</author>
internal class WebObjectDefinitionParserHelper : ObjectDefinitionParserHelper
{
private readonly IWebObjectNameGenerator webObjectNameGenerator;
/// <summary>
/// Initializes a new instance of the <see cref="WebObjectDefinitionParserHelper"/> class.
/// </summary>
/// <param name="webObjectNameGenerator">used for generating object definition names from web object types (page, control)</param>
/// <param name="readerContext">The reader context.</param>
/// <param name="root">The root element of the xml document to parse</param>
public WebObjectDefinitionParserHelper(IWebObjectNameGenerator webObjectNameGenerator, XmlReaderContext readerContext, XmlElement root)
: base(readerContext, root)
{
AssertUtils.ArgumentNotNull(webObjectNameGenerator, "webObjectNameGenerator");
this.webObjectNameGenerator = webObjectNameGenerator;
}
protected override string PostProcessObjectNameAndAliases(string objectName, System.Collections.ArrayList aliases, XmlElement element, IObjectDefinition containingDefinition)
{
string url = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
string strTypeName = url.ToLower();
if (strTypeName.EndsWith(".aspx"))
{
if (!StringUtils.HasText(objectName))
{
objectName = webObjectNameGenerator.CreatePageDefinitionName(url);
}
// adjust aliases if necessary
for (int ai = 0; ai < aliases.Count; ai++)
{
string alias = (string)aliases[ai];
if (alias != null && alias.Length > 0 && alias[0] == '~')
{
aliases[ai] = "/" + alias.Substring(1).TrimStart('/', '\\');
}
}
}
else if (strTypeName.EndsWith(".ascx") || strTypeName.EndsWith(".master"))
{
if (!StringUtils.HasText(objectName))
{
objectName = webObjectNameGenerator.CreateControlDefinitionName(url);
}
}
return objectName;
}
protected override ObjectDefinitionHolder CreateObjectDefinitionHolder(XmlElement element, IConfigurableObjectDefinition definition, string objectName, string[] aliasesArray)
{
IWebObjectDefinition webDefinition = definition as IWebObjectDefinition;
if (webDefinition != null)
{
webDefinition.Scope = GetScope(element.GetAttribute(ObjectDefinitionConstants.ScopeAttribute));
// force request and session scoped objects to be lazily initialized...
if (webDefinition.Scope != ObjectScope.Application)
{
definition.IsLazyInit = true;
}
string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
if (typeName.EndsWith(".ascx") || typeName.EndsWith(".master"))
{
definition.IsAbstract = true;
}
}
ObjectDefinitionHolder holder = base.CreateObjectDefinitionHolder(element, definition, objectName, aliasesArray);
return holder;
}
/// <summary>
/// Gets the scope out of the supplied <paramref name="value"/>.
/// </summary>
/// <remarks>
/// <p>
/// If the supplied <paramref name="value"/> is invalid
/// (i.e. it does not resolve to one of the
/// <see cref="Spring.Objects.Factory.Support.ObjectScope"/> values),
/// then the return value of this method call will be
/// <see cref="Spring.Objects.Factory.Support.ObjectScope.Default"/>;
/// no exception will be raised (although the value of the invalid
/// scope <paramref name="value"/> will be logged).
/// </p>
/// </remarks>
/// <param name="value">The string containing the scope name.</param>
/// <returns>The scope.</returns>
/// <seealso cref="Spring.Objects.Factory.Support.ObjectScope"/>
private ObjectScope GetScope(string value)
{
ObjectScope scope = ObjectScope.Default;
if (StringUtils.HasText(value))
{
try
{
scope = (ObjectScope)Enum.Parse(typeof(ObjectScope), value, true);
}
catch (ArgumentException ex)
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Error while parsing object scope : '{0}' is an invalid value.",
value), ex);
}
#endregion
}
}
return scope;
}
}
}

View File

@@ -0,0 +1,108 @@
#region License
/*
* Copyright 2002-2009 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
using System.Web;
using System.Xml;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Objects.Factory.Xml
{
/// <summary>
/// An <see cref="XmlObjectDefinitionReader"/> capable of handling web object definitions (Pages, Controls)
/// </summary>
/// <author>Erich Eichinger</author>
public class WebObjectDefinitionReader : XmlObjectDefinitionReader, IWebObjectNameGenerator
{
private readonly string contextVirtualPath;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/> class.
/// </summary>
/// <param name="contextVirtualPath">the (rooted) virtual path to resolve relative virtual paths.</param>
/// <param name="registry">
/// The <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry"/>
/// instance that this reader works on.
/// </param>
/// <param name="resolver">the <see cref="XmlResolver"/> to use for resolving entities.</param>
public WebObjectDefinitionReader(string contextVirtualPath, IObjectDefinitionRegistry registry, XmlResolver resolver)
: base(registry, resolver, new WebObjectDefinitionFactory())
{
this.contextVirtualPath = contextVirtualPath;
}
/// <summary>
/// Creates the <see cref="IObjectDefinitionDocumentReader"/> to use for actually
/// reading object definitions from an XML document.
/// </summary>
protected override IObjectDefinitionDocumentReader CreateObjectDefinitionDocumentReader()
{
return new WebObjectDefinitionDocumentReader(this);
}
string IWebObjectNameGenerator.CreatePageDefinitionName(string virtualPath)
{
return CreatePageDefinitionName(virtualPath);
}
string IWebObjectNameGenerator.CreateControlDefinitionName(string virtualPath)
{
return CreateControlDefinitionName(virtualPath);
}
/// <summary>
/// Create an object definition name for the given control path
/// </summary>
protected virtual string CreateControlDefinitionName(string virtualPath)
{
string objectName;
objectName = WebObjectUtils.GetControlType(virtualPath).FullName;
return objectName;
}
/// <summary>
/// Create an object definition name for the given page path
/// </summary>
protected virtual string CreatePageDefinitionName(string url)
{
string objectName;
objectName = WebUtils.CombineVirtualPaths(VirtualEnvironment.CurrentExecutionFilePath, url);
string appPath = VirtualEnvironment.ApplicationVirtualPath;
if (objectName.ToLower().StartsWith(appPath.ToLower()))
{
objectName = objectName.Substring(appPath.Length-1);
}
// System.Web.UI.Page page = (System.Web.UI.Page)WebObjectUtils.CreatePageInstance(url);
//#if NET_2_0
// objectName = page.AppRelativeVirtualPath.Substring(1);
//#else
// string appPath = HttpContext.Current.Request.ApplicationPath.TrimEnd('\\', '/');
// objectName = page.TemplateSourceDirectory.TrimEnd('\\','/') + "/" + WebUtils.GetPageName(url) + ".aspx";
// if (objectName.ToLower().StartsWith(appPath.ToLower()))
// {
// objectName = objectName.Substring(appPath.Length);
// }
//#endif
return objectName;
}
}
}

View File

@@ -48,7 +48,7 @@ namespace Spring.Objects.Factory.Xml
/// <see cref="ObjectsNamespaceParser"/>
public class WebObjectsNamespaceParser : ObjectsNamespaceParser
{
private IObjectDefinitionFactory objectDefinitionFactory;
// private IObjectDefinitionFactory objectDefinitionFactory;
#region Constructor (s) / Destructor
@@ -58,148 +58,148 @@ namespace Spring.Objects.Factory.Xml
/// </summary>
public WebObjectsNamespaceParser()
{
objectDefinitionFactory = new WebObjectDefinitionFactory();
// objectDefinitionFactory = new WebObjectDefinitionFactory();
}
#endregion
/// <summary>
/// Parses an object definition and set various web related properties
/// if the definition is an <see cref="RootWebObjectDefinition"/>.
/// </summary>
/// <param name="element">The object definition element.</param>
/// <param name="id">The id / name of the object definition.</param>
/// <param name="parserContext">the parser helper</param>
/// <returns>The object (definition).</returns>
/// <remarks>
/// <p>
/// The <i>'various web related properties'</i> currently includes the
/// intended scope of the object.
/// </p>
/// </remarks>
/// <see cref="Spring.Objects.Factory.Support.ObjectScope"/>
/// <see cref="Spring.Objects.Factory.Support.IWebObjectDefinition"/>
protected override IConfigurableObjectDefinition ParseObjectDefinitionElement(
XmlElement element, string id, ParserContext parserContext)
{
parserContext.ReaderContext.ObjectDefinitionFactory = objectDefinitionFactory;
IConfigurableObjectDefinition definition = base.ParseObjectDefinitionElement(element, id, parserContext);
IWebObjectDefinition webDefinition = definition as IWebObjectDefinition;
if (webDefinition != null)
{
webDefinition.Scope = GetScope(element.GetAttribute(ObjectDefinitionConstants.ScopeAttribute));
// /// <summary>
// /// Parses an object definition and set various web related properties
// /// if the definition is an <see cref="RootWebObjectDefinition"/>.
// /// </summary>
// /// <param name="element">The object definition element.</param>
// /// <param name="id">The id / name of the object definition.</param>
// /// <param name="parserContext">the parser helper</param>
// /// <returns>The object (definition).</returns>
// /// <remarks>
// /// <p>
// /// The <i>'various web related properties'</i> currently includes the
// /// intended scope of the object.
// /// </p>
// /// </remarks>
// /// <see cref="Spring.Objects.Factory.Support.ObjectScope"/>
// /// <see cref="Spring.Objects.Factory.Support.IWebObjectDefinition"/>
// protected override IConfigurableObjectDefinition ParseObjectDefinitionElement(
// XmlElement element, string id, ParserContext parserContext)
// {
// IConfigurableObjectDefinition definition = base.ParseObjectDefinitionElement(element, id, parserContext);
// IWebObjectDefinition webDefinition = definition as IWebObjectDefinition;
//
// if (webDefinition != null)
// {
// webDefinition.Scope = GetScope(element.GetAttribute(ObjectDefinitionConstants.ScopeAttribute));
//
// // force request and session scoped objects to be lazily initialized...
// if (webDefinition.Scope != ObjectScope.Application)
// {
// definition.IsLazyInit = true;
// }
//
// string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
// if (typeName.EndsWith(".ascx") || typeName.EndsWith(".master"))
// {
// definition.IsAbstract = true;
// }
// }
//
// return definition;
// }
// force request and session scoped objects to be lazily initialized...
if (webDefinition.Scope != ObjectScope.Application)
{
definition.IsLazyInit = true;
}
string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
if (typeName.EndsWith(".ascx") || typeName.EndsWith(".master"))
{
definition.IsAbstract = true;
}
}
return definition;
}
// /// <summary>
// /// Calculates an id for an object definition.
// /// </summary>
// /// <param name="element">
// /// The element containing the object definition.
// /// </param>
// /// <param name="aliases">
// /// The list of names defined for the object; may be <see lang="null"/>
// /// or even empty.
// /// </param>
// /// <returns>
// /// A calculated object definition id.
// /// </returns>
// /// <seealso cref="ObjectsNamespaceParser.CalculateId"/>.
// protected override string CalculateId(XmlElement element, ArrayList aliases)
// {
// return null;
// string id = null;
// string strTypeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute).ToLower();
// if (strTypeName.EndsWith(".aspx"))
// {
// string url = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
// //id = WebUtils.GetPageName(url);
// //Type pageType = WebUtils.GetPageType(url);
// System.Web.UI.Page page = (System.Web.UI.Page)WebObjectUtils.CreatePageInstance(url);
//#if NET_2_0
// id = page.AppRelativeVirtualPath.Substring(1);
//#else
// string appPath = HttpContext.Current.Request.ApplicationPath.TrimEnd('\\', '/');
// id = page.TemplateSourceDirectory.TrimEnd('\\','/') + "/" + WebUtils.GetPageName(url) + ".aspx";
// if (id.ToLower().StartsWith(appPath.ToLower()))
// {
// id = id.Substring(appPath.Length);
// }
//#endif
// for(int ai=0;ai<aliases.Count;ai++)
// {
// string alias = (string)aliases[ai];
// if (alias != null && alias.Length>0 && alias[0]=='~')
// {
// aliases[ai] = "/"+alias.Substring(1).TrimStart('/','\\');
// }
// }
// }
// else if (strTypeName.EndsWith(".ascx") || strTypeName.EndsWith(".master"))
// {
// id = WebObjectUtils.GetControlType(strTypeName).FullName;
// }
// else
// {
// id = base.CalculateId(element, aliases);
// }
// return id;
// }
/// <summary>
/// Calculates an id for an object definition.
/// </summary>
/// <param name="element">
/// The element containing the object definition.
/// </param>
/// <param name="aliases">
/// The list of names defined for the object; may be <see lang="null"/>
/// or even empty.
/// </param>
/// <returns>
/// A calculated object definition id.
/// </returns>
/// <seealso cref="ObjectsNamespaceParser.CalculateId"/>.
protected override string CalculateId(XmlElement element, ArrayList aliases)
{
string id = null;
string strTypeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute).ToLower();
if (strTypeName.EndsWith(".aspx"))
{
string url = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
//id = WebUtils.GetPageName(url);
//Type pageType = WebUtils.GetPageType(url);
System.Web.UI.Page page = (System.Web.UI.Page)WebObjectUtils.CreatePageInstance(url);
#if NET_2_0
id = page.AppRelativeVirtualPath.Substring(1);
#else
string appPath = HttpContext.Current.Request.ApplicationPath.TrimEnd('\\', '/');
id = page.TemplateSourceDirectory.TrimEnd('\\','/') + "/" + WebUtils.GetPageName(url) + ".aspx";
if (id.ToLower().StartsWith(appPath.ToLower()))
{
id = id.Substring(appPath.Length);
}
#endif
for(int ai=0;ai<aliases.Count;ai++)
{
string alias = (string)aliases[ai];
if (StringUtils.HasText(alias) && alias[0]=='~')
{
aliases[ai] = "/"+alias.Substring(1).TrimStart('/','\\');
}
}
}
else if (strTypeName.EndsWith(".ascx") || strTypeName.EndsWith(".master"))
{
id = WebObjectUtils.GetControlType(strTypeName).FullName;
}
else
{
id = base.CalculateId(element, aliases);
}
return id;
}
/// <summary>
/// Gets the scope out of the supplied <paramref name="value"/>.
/// </summary>
/// <remarks>
/// <p>
/// If the supplied <paramref name="value"/> is invalid
/// (i.e. it does not resolve to one of the
/// <see cref="Spring.Objects.Factory.Support.ObjectScope"/> values),
/// then the return value of this method call will be
/// <see cref="Spring.Objects.Factory.Support.ObjectScope.Default"/>;
/// no exception will be raised (although the value of the invalid
/// scope <paramref name="value"/> will be logged).
/// </p>
/// </remarks>
/// <param name="value">The string containing the scope name.</param>
/// <returns>The scope.</returns>
/// <seealso cref="Spring.Objects.Factory.Support.ObjectScope"/>
private ObjectScope GetScope(string value)
{
ObjectScope scope = ObjectScope.Default;
if (StringUtils.HasText(value))
{
try
{
scope = (ObjectScope) Enum.Parse(typeof(ObjectScope), value, true);
}
catch (ArgumentException ex)
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Error while parsing object scope : '{0}' is an invalid value.",
value), ex);
}
#endregion
}
}
return scope;
}
// /// <summary>
// /// Gets the scope out of the supplied <paramref name="value"/>.
// /// </summary>
// /// <remarks>
// /// <p>
// /// If the supplied <paramref name="value"/> is invalid
// /// (i.e. it does not resolve to one of the
// /// <see cref="Spring.Objects.Factory.Support.ObjectScope"/> values),
// /// then the return value of this method call will be
// /// <see cref="Spring.Objects.Factory.Support.ObjectScope.Default"/>;
// /// no exception will be raised (although the value of the invalid
// /// scope <paramref name="value"/> will be logged).
// /// </p>
// /// </remarks>
// /// <param name="value">The string containing the scope name.</param>
// /// <returns>The scope.</returns>
// /// <seealso cref="Spring.Objects.Factory.Support.ObjectScope"/>
// private ObjectScope GetScope(string value)
// {
// ObjectScope scope = ObjectScope.Default;
// if (StringUtils.HasText(value))
// {
// try
// {
// scope = (ObjectScope) Enum.Parse(typeof(ObjectScope), value, true);
// }
// catch (ArgumentException ex)
// {
// #region Instrumentation
//
// if (log.IsDebugEnabled)
// {
// log.Debug(string.Format("Error while parsing object scope : '{0}' is an invalid value.",
// value), ex);
// }
//
// #endregion
// }
// }
// return scope;
// }
}
}

View File

@@ -125,6 +125,10 @@
<Compile Include="Globalization\AspNetResourceCache.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Factory\Support\IWebObjectNameGenerator.cs" />
<Compile Include="Objects\Factory\Xml\WebObjectDefinitionDocumentReader.cs" />
<Compile Include="Objects\Factory\Xml\WebObjectDefinitionParserHelper.cs" />
<Compile Include="Objects\Factory\Xml\WebObjectDefinitionReader.cs" />
<Compile Include="Util\ISessionState.cs" />
<Compile Include="Util\SecurityCritical.cs" />
<Compile Include="Web\Support\DefaultHandlerFactory.cs" />

View File

@@ -49,34 +49,60 @@ namespace Spring.Util
/// <author>Erich Eichinger</author>
public class HttpContextSwitch : IDisposable
{
private HttpContext savedContext;
private string originalUrl;
private readonly IDisposable rewriteContext;
private static readonly ILog log = LogManager.GetLogger(typeof(HttpContextSwitch));
// /// <summary>
// /// Performs an immediate call to <see cref="HttpContext.RewritePath(string)"/>
// /// </summary>
// /// <param name="virtualDirectory">a directory path (without trailing filename!)</param>
// public HttpContextSwitch( string virtualDirectory )
// {
// HttpContext currentContext = HttpContext.Current;
// if (currentContext == null) return; // no webrequest
//
// virtualDirectory = WebUtils.GetVirtualDirectory(virtualDirectory);
// string currentFileDirectory = WebUtils.GetVirtualDirectory(currentContext.Request.FilePath);
// // only switch path if necessary
// if (string.Compare( virtualDirectory, currentFileDirectory, true ) != 0)
// {
// savedContext = currentContext;
// originalUrl = savedContext.Request.Url.PathAndQuery;
// string newPath = virtualDirectory + "currentcontext.dummy";
//#if NET_2_0
// savedContext.RewritePath( newPath, false );
//#else
// savedContext.RewritePath( newPath );
//#endif
// if (log.IsDebugEnabled) log.Debug("rewriting path from " + originalUrl + " to " + newPath + " results in " + savedContext.Request.FilePath);
// }
// }
/// <summary>
/// Performs an immediate call to <see cref="HttpContext.RewritePath(string)"/>
/// </summary>
/// <param name="virtualDirectory">a directory path (without trailing filename!)</param>
public HttpContextSwitch( string virtualDirectory )
public HttpContextSwitch(string virtualDirectory)
{
HttpContext currentContext = HttpContext.Current;
if (currentContext == null) return; // no webrequest
rewriteContext = VirtualEnvironment.RewritePath(virtualDirectory, false);
virtualDirectory = WebUtils.GetVirtualDirectory(virtualDirectory);
string currentFileDirectory = WebUtils.GetVirtualDirectory(currentContext.Request.FilePath);
// only switch path if necessary
if (string.Compare( virtualDirectory, currentFileDirectory, true ) != 0)
{
savedContext = currentContext;
originalUrl = savedContext.Request.Url.PathAndQuery;
string newPath = virtualDirectory + "currentcontext.dummy";
#if NET_2_0
savedContext.RewritePath( newPath, false );
#else
savedContext.RewritePath( newPath );
#endif
if (log.IsDebugEnabled) log.Debug("rewriting path from " + originalUrl + " to " + newPath + " results in " + savedContext.Request.FilePath);
}
// string currentFileDirectory = WebUtils.GetVirtualDirectory(VirtualEnvironment.CurrentVirtualFilePath);
// // only switch path if necessary
// if (string.Compare(virtualDirectory, currentFileDirectory, true) != 0)
// {
// originalUrl = VirtualEnvironment.CurrentVirtualPathAndQuery;
// string newPath = virtualDirectory + "currentcontext.dummy";
// VirtualEnvironment.RewritePath(newPath, false);
//
// #region Instrumentation
//
// if (log.IsDebugEnabled)
// {
// log.Debug("rewriting path from " + originalUrl + " to " + newPath + " results in " + VirtualEnvironment.CurrentVirtualFilePath);
// }
//
// #endregion
// }
}
/// <summary>
@@ -84,17 +110,45 @@ namespace Spring.Util
/// </summary>
public void Dispose()
{
if (savedContext != null)
{
if (log.IsDebugEnabled) log.Debug("restoring original path from " + savedContext.Request.FilePath + " back to " + originalUrl);
HttpContext context = savedContext;
savedContext = null;
#if NET_2_0
context.RewritePath( originalUrl, false );
#else
context.RewritePath( originalUrl );
#endif
}
rewriteContext.Dispose();
// if (rewriteContext != null)
// {
// VirtualEnvironment.RewritePath(originalUrl, false);
//
// #region Instrumentation
//
// if (log.IsDebugEnabled)
// {
// log.Debug("restoring original path from " + VirtualEnvironment.CurrentVirtualFilePath + " back to " + originalUrl);
// }
//
// #endregion
// }
}
// /// <summary>
// /// Restores original path if necessary
// /// </summary>
// public void Dispose()
// {
// if (originalUrl != null)
// {
// HttpContext context = HttpContext.Current;
//#if NET_2_0
// context.RewritePath( originalUrl, false );
//#else
// context.RewritePath( originalUrl );
//#endif
//
// #region Instrumentation
//
// if (log.IsDebugEnabled)
// {
// log.Debug("restoring original path from " + context.Request.FilePath + " back to " + originalUrl);
// }
//
// #endregion
// }
// }
}
}

View File

@@ -22,6 +22,7 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Reflection;
using System.Web;
@@ -64,17 +65,40 @@ namespace Spring.Util
/// </remarks>
string CurrentExecutionFilePath { get; }
/// <summary>
/// The query parameters
/// </summary>
NameValueCollection QueryString { get; }
/// <summary>
/// Maps a virtual path to it's physical location
/// </summary>
string MapPath( string virtualPath );
/// <summary>
/// Rewrites the <see cref="CurrentVirtualPath"/>, thus also affecting <see cref="MapPath"/>
/// </summary>
IDisposable RewritePath(string newVirtualPath, bool rebaseClientPath);
/// <summary>
/// Returns the current Session's variable dictionary
/// </summary>
ISessionState Session { get; }
/// <summary>
/// Returns the current Request's variable dictionary
/// Returns the current Request's variable dictionary <see cref="HttpContext.Items"/>
/// </summary>
IDictionary RequestVariables { get; }
/// <summary>
/// Returns the current Request's parameter dictionary <see cref="HttpRequest.Params"/>
/// </summary>
NameValueCollection RequestParams { get; }
/// <summary>
/// Get the compiled type for the given virtual path
/// </summary>
/// <param name="absoluteVirtualPath">the absolute (=rooted) virtual path</param>
/// <returns></returns>
Type GetCompiledType(string absoluteVirtualPath);
/// <summary>
/// Creates an instance from the given virtual path
/// </summary>
/// <param name="absoluteVirtualPath">the absolute (=rooted) virtual path</param>
/// <param name="requiredBaseType">the required base type </param>
object CreateInstanceFromVirtualPath(string absoluteVirtualPath, Type requiredBaseType);
}
}

View File

@@ -22,10 +22,15 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.Caching;
using System.Web.Compilation;
using System.Web.SessionState;
using System.Web.UI;
using Common.Logging;
#endregion
@@ -229,6 +234,75 @@ namespace Spring.Util
#endregion //HttpSessionState Adapter
private static readonly ILog log = LogManager.GetLogger(typeof (HttpRuntimeEnvironment));
#if NET_1_1
// Required method for resolving control types
private static MethodInfo miGetCompiledUserControlType = null;
static HttpRuntimeEnvironment()
{
Type tUserControlParser = typeof(System.Web.UI.UserControl).Assembly.GetType("System.Web.UI.UserControlParser");
miGetCompiledUserControlType = tUserControlParser.GetMethod("GetCompiledUserControlType", BindingFlags.Static | BindingFlags.NonPublic);
}
#endif
private class RewriteContext : IDisposable
{
private string originalPath;
private bool rebaseClientPath;
private HttpContext ctx;
public RewriteContext(string virtualDirectory, bool rebaseClientPath)
{
ctx = HttpContext.Current;
if (ctx == null)
{
return;
}
this.rebaseClientPath = rebaseClientPath;
string newVirtualPath = WebUtils.GetVirtualDirectory(virtualDirectory);
string currentFileDirectory = WebUtils.GetVirtualDirectory(ctx.Request.FilePath);
// only switch path if necessary
if (string.Compare(newVirtualPath, currentFileDirectory, true) != 0)
{
originalPath = ctx.Request.Url.PathAndQuery;
string newPath = newVirtualPath + "currentcontext.dummy";
#if NET_1_1
ctx.RewritePath(newPath);
#else
ctx.RewritePath(newPath, rebaseClientPath);
#endif
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("rewriting path from " + currentFileDirectory + " to " + newPath + " results in " + ctx.Request.FilePath);
}
#endregion
}
}
public void Dispose()
{
if (originalPath != null)
{
if (log.IsDebugEnabled)
{
log.Debug("restoring path from " + ctx.Request.FilePath + " back to " + originalPath);
}
#if NET_1_1
ctx.RewritePath(originalPath);
#else
ctx.RewritePath(originalPath, rebaseClientPath);
#endif
}
}
}
public string ApplicationVirtualPath
{
get
@@ -254,6 +328,11 @@ namespace Spring.Util
get { return HttpContext.Current.Request.CurrentExecutionFilePath; }
}
public NameValueCollection QueryString
{
get { return HttpContext.Current.Request.QueryString; }
}
public string MapPath(string virtualPath)
{
HttpContext ctx = HttpContext.Current;
@@ -261,8 +340,9 @@ namespace Spring.Util
{
return ctx.Request.MapPath(virtualPath);
}
#if NET_2_0
#if NET_1_1
throw new ArgumentException("can't map context relative path outside a context");
#else
if (VirtualPathUtility.IsAbsolute(virtualPath) && virtualPath.StartsWith(HttpRuntime.AppDomainAppVirtualPath))
{
virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
@@ -273,8 +353,13 @@ namespace Spring.Util
string physicalPath = Path.Combine(HttpRuntime.AppDomainAppPath, virtualPath);
return physicalPath;
}
return virtualPath;
#endif
throw new ArgumentException("can't map context relative path outside a context");
}
public IDisposable RewritePath(string virtualDirectory, bool rebaseClientPath)
{
return new RewriteContext(virtualDirectory, rebaseClientPath);
}
public ISessionState Session
@@ -286,6 +371,49 @@ namespace Spring.Util
{
get { return HttpContext.Current.Items; }
}
public NameValueCollection RequestParams
{
get { return HttpContext.Current.Request.Params; }
}
public Type GetCompiledType(string virtualPath)
{
string rootedVPath = WebUtils.CombineVirtualPaths(CurrentExecutionFilePath, virtualPath);
Type type = null;
#if NET_1_1
if (virtualPath.EndsWith(".aspx"))
{
type = CreateInstanceFromVirtualPath(virtualPath, typeof(Page)).GetType();
}
else if (virtualPath.EndsWith(".ascx"))
{
type = (Type)miGetCompiledUserControlType.Invoke(null, new object[] { rootedVPath, null, HttpContext.Current });
}
#else
type = BuildManager.GetCompiledType(rootedVPath); // requires rooted virtual path!
#endif
return type;
}
public object CreateInstanceFromVirtualPath(string virtualPath, Type requiredBaseType)
{
string rootedVPath = WebUtils.CombineVirtualPaths(CurrentExecutionFilePath, virtualPath);
object result;
#if NET_1_1
HttpContext ctx = HttpContext.Current;
string physicalPath = ctx.Server.MapPath(rootedVPath);
result = PageParser.GetCompiledPageInstance(virtualPath, physicalPath, ctx);
#else
result = BuildManager.CreateInstanceFromVirtualPath(rootedVPath, requiredBaseType);
#endif
if (!requiredBaseType.IsAssignableFrom(result.GetType()))
{
throw new HttpException(string.Format("Type '{0}' from virtual path '{1}' does not inherit from '{2}'", result.GetType(), rootedVPath, requiredBaseType));
}
return result;
}
}
#endregion
@@ -306,6 +434,22 @@ namespace Spring.Util
get { return instance.CurrentVirtualPath; }
}
/// <summary>
/// The virtual (rooted) path of the current Request including <see cref="HttpRequest.PathInfo"/>
/// </summary>
public static string CurrentVirtualPathAndQuery
{
get
{
string result = CurrentVirtualPath;
if (QueryString.Count > 0)
{
result = result + "?" + QueryString.ToString();
}
return result;
}
}
/// <summary>
/// The virtual (rooted) path of the current Request without trailing <see cref="HttpRequest.PathInfo"/>
/// </summary>
@@ -322,6 +466,30 @@ namespace Spring.Util
get { return instance.CurrentExecutionFilePath; }
}
/// <summary>
/// The query parameters
/// </summary>
public static NameValueCollection QueryString
{
get { return instance.QueryString; }
}
/// <summary>
/// Returns the current Request's variable dictionary (<see cref="HttpContext.Items"/>)
/// </summary>
public static IDictionary RequestVariables
{
get { return instance.RequestVariables; }
}
/// <summary>
/// Returns the current Request's parameter dictionary (<see cref="HttpRequest.Params"/>)
/// </summary>
public static NameValueCollection RequestParams
{
get { return instance.RequestParams; }
}
/// <summary>
/// Maps a virtual path to it's physical location
/// </summary>
@@ -330,6 +498,32 @@ namespace Spring.Util
return instance.MapPath(virtualPath);
}
/// <summary>
/// Rewrites the <see cref="CurrentVirtualPath"/>, thus also affecting <see cref="MapPath"/>
/// </summary>
public static IDisposable RewritePath(string newVirtualPath, bool rebaseClientPath)
{
return instance.RewritePath(newVirtualPath, rebaseClientPath);
}
/// <summary>
/// Returns an instance of the specified file.
/// </summary>
public static object CreateInstanceFromVirtualPath(string virtualPath, Type requiredBaseType)
{
string rootedVPath = WebUtils.CombineVirtualPaths(instance.CurrentExecutionFilePath, virtualPath);
return instance.CreateInstanceFromVirtualPath(rootedVPath, requiredBaseType);
}
/// <summary>
/// Returns an the compiled type of the specified file.
/// </summary>
public static Type GetCompiledType(string virtualPath)
{
string rootedVPath = WebUtils.CombineVirtualPaths(instance.CurrentExecutionFilePath, virtualPath);
return instance.GetCompiledType(rootedVPath);
}
/// <summary>
/// Receives EndRequest-event from an <see cref="HttpApplication"/> instance
/// and dispatches it to all handlers registered with this module.

View File

@@ -318,7 +318,7 @@ namespace Spring.Web.Support
return handler;
}
#else
private static readonly IDynamicField fControls = SafeField.CreateFrom(GetField("_controls"));
private static readonly IDynamicField fControls = new SafeField(GetField("_controls"));
private ControlCollection GetChildControlCollection()
{

View File

@@ -111,7 +111,7 @@ namespace Spring.Web.Support
}
else
{
handler = WebObjectUtils.CreateHandler(context, rawUrl);
handler = WebObjectUtils.CreateHandler(rawUrl);
// let WebSupportModule handle configuration
handler = WebSupportModule.ConfigureHandler(context, handler, appContext, rawUrl, false);
}

View File

@@ -1784,7 +1784,8 @@ namespace Spring.Objects.Factory.Xml
</objects>";
stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
IObjectFactory factory = new XmlObjectFactory(new InputStreamResource(stream, string.Empty));
factory.GetObject("foo");
ITestObject to = (ITestObject) factory.GetObject("foo");
Assert.IsNotNull( to.Spouse );
}
[Test(Description="SPR-1313")]

View File

@@ -803,6 +803,7 @@
<Content Include="Data\Spring\Objects\Factory\Xml\collections.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\constructor-arg.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\array-autowire.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\objectNameGeneration.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\simple-constructor-arg.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\expressions.xml" />
<Content Include="Data\Spring\Objects\Factory\Xml\default-autowire.xml" />

View File

@@ -404,5 +404,23 @@ namespace Spring.Util
return ((int)dex.Key).CompareTo(dey.Key);
}
[Test]
public void FindFirstMatchReturnsNullIfAnyInputIsEmpty()
{
Assert.IsNull( CollectionUtils.FindFirstMatch(null, null) );
Assert.IsNull( CollectionUtils.FindFirstMatch(new string[0], new string[0]));
Assert.IsNull( CollectionUtils.FindFirstMatch(null, new string[] { "x" }));
Assert.IsNull( CollectionUtils.FindFirstMatch(new string[] { "x" }, null));
}
[Test]
public void FindFirstMatchReturnsFirstMatch()
{
ArrayList source = new ArrayList();
string[] candidates = new string[] { "G", "B", "H" };
source.AddRange( new string[] { "A", "B", "C" } );
Assert.AreEqual( "B" , CollectionUtils.FindFirstMatch(source, candidates));
}
}
}

View File

@@ -126,6 +126,11 @@ namespace Spring.Validation
{
throw new NotImplementedException();
}
public bool IsObjectNameInUse(string objectName)
{
return this.objects[objectName] != null;
}
}
}

View File

@@ -39,7 +39,7 @@ namespace Spring.Core.IO
[TestFixtureSetUp]
public void SetUpFixture()
{
testVirtualEnvironment = new VirtualEnvironmentMock("/some.request", "somepathinfo", "/", true);
testVirtualEnvironment = new VirtualEnvironmentMock("/some.request", "somepathinfo", null, "/", true);
}
[TestFixtureTearDown]

View File

@@ -44,7 +44,7 @@ namespace Spring.Objects.Factory.Support
// we need to create WOF within a valid HttpContext environment 'cause we will
// make use of 'request' and 'session' scope.
using (new VirtualEnvironmentMock("/somedir/some.file", null, "/", true))
using (new VirtualEnvironmentMock("/somedir/some.file", null, null, "/", true))
{
wof = new WebObjectFactory("/somedir/", false);
}

View File

@@ -0,0 +1,60 @@
#region License
/*
* Copyright 2002-2009 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
using System;
using NUnit.Framework;
namespace Spring.Objects.Factory.Support
{
/// <summary>
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class WebObjectUtilsTests
{
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void GetPageTypeWithNullPageName()
{
WebObjectUtils.GetPageType(null);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void GetPageTypeWithEmptyStringPageName()
{
WebObjectUtils.GetPageType(string.Empty);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void GetPageTypeWithWhitespacedPageName()
{
WebObjectUtils.GetPageType(" ");
}
[Test]
[ExpectedException(typeof(ObjectCreationException))]
public void CreatePageInstanceWhenNotRunningInServerContext()
{
WebObjectUtils.CreatePageInstance("foo.aspx");
}
}
}

View File

@@ -0,0 +1,181 @@
#region License
/*
* Copyright 2002-2009 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
using System;
using System.Collections;
using System.Xml;
using NUnit.Framework;
using Spring.Collections;
using Spring.Core.IO;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.TestSupport;
using Spring.Util;
namespace Spring.Objects.Factory
{
/// <summary>
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class WebObjectDefinitionReaderTests
{
public class TestWebObjectDefinitionReader : WebObjectDefinitionReader
{
public TestWebObjectDefinitionReader(string contextVirtualPath, IObjectDefinitionRegistry registry, XmlResolver resolver)
: base(contextVirtualPath, registry, resolver)
{}
}
[Test]
public void ControlDefinitionsGetMarkedAbstract()
{
const string CONTEXTPATH = "/ContextPath/";
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object type='MyControl.ascx' />
</objects>";
WebObjectFactory objectFactory = new WebObjectFactory(CONTEXTPATH, false);
TestWebObjectDefinitionReader reader = new TestWebObjectDefinitionReader(objectFactory.ContextPath, objectFactory, new XmlUrlResolver());
using (VirtualEnvironmentMock env = new VirtualEnvironmentMock(CONTEXTPATH + "test.aspx", null, null, CONTEXTPATH, true))
{
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyControl.ascx"] = typeof(Spring.Web.UI.UserControl);
reader.LoadObjectDefinitions(new StringResource(xml));
}
Assert.IsTrue(objectFactory.ContainsObjectDefinition("Spring.Web.UI.UserControl"));
Assert.IsTrue(objectFactory.GetObjectDefinition("Spring.Web.UI.UserControl").IsAbstract);
}
[Test]
public void ParsesPagePathIntoObjectNameIfNeitherIdNorNameAttributeSpecified()
{
const string CONTEXTPATH = "/ContextPath/";
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object type='MyPage.aspx' />
<object type='~/MyControl.ascx' />
</objects>";
WebObjectFactory objectFactory = new WebObjectFactory(CONTEXTPATH, false);
TestWebObjectDefinitionReader reader = new TestWebObjectDefinitionReader(objectFactory.ContextPath, objectFactory, new XmlUrlResolver());
using (VirtualEnvironmentMock env = new VirtualEnvironmentMock(CONTEXTPATH + "test.aspx", null, null, CONTEXTPATH, true))
{
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyPage.aspx"] = typeof (Spring.Web.UI.Page);
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyControl.ascx"] = typeof (Spring.Web.UI.UserControl);
reader.LoadObjectDefinitions(new StringResource(xml));
}
Assert.IsTrue(objectFactory.ContainsObjectDefinition("/MyPage.aspx"));
Assert.AreEqual(typeof(Spring.Web.UI.Page), objectFactory.GetType("/MyPage.aspx"));
Assert.IsTrue(objectFactory.ContainsObjectDefinition("Spring.Web.UI.UserControl"));
}
[Test]
public void DoesNotGenerateObjectNameIfIdAttributeSpecified()
{
const string CONTEXTPATH = "/ContextPath/";
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object id='mypage' type='MyPage.aspx' />
<object id='mycontrol' type='MyControl.ascx' />
</objects>";
WebObjectFactory objectFactory = new WebObjectFactory(CONTEXTPATH, false);
TestWebObjectDefinitionReader reader = new TestWebObjectDefinitionReader(objectFactory.ContextPath, objectFactory, new XmlUrlResolver());
using (VirtualEnvironmentMock env = new VirtualEnvironmentMock(CONTEXTPATH + "test.aspx", null, null, CONTEXTPATH, true))
{
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyPage.aspx"] = typeof (Spring.Web.UI.Page);
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyControl.ascx"] = typeof (Spring.Web.UI.UserControl);
reader.LoadObjectDefinitions(new StringResource(xml));
}
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mypage"));
Assert.AreEqual(typeof(Spring.Web.UI.Page), objectFactory.GetType("mypage"));
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mycontrol"));
}
[Test]
public void DoesNotGenerateObjectNameIfNameAttributeSpecified()
{
const string CONTEXTPATH = "/ContextPath/";
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object name='mypage' type='MyPage.aspx' />
<object name='mycontrol' type='MyControl.ascx' />
</objects>";
WebObjectFactory objectFactory = new WebObjectFactory(CONTEXTPATH, false);
TestWebObjectDefinitionReader reader = new TestWebObjectDefinitionReader(objectFactory.ContextPath, objectFactory, new XmlUrlResolver());
using (VirtualEnvironmentMock env = new VirtualEnvironmentMock(CONTEXTPATH + "test.aspx", null, null, CONTEXTPATH, true))
{
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyPage.aspx"] = typeof(Spring.Web.UI.Page);
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyControl.ascx"] = typeof(Spring.Web.UI.UserControl);
reader.LoadObjectDefinitions(new StringResource(xml));
}
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mypage"));
Assert.AreEqual(typeof(Spring.Web.UI.Page), objectFactory.GetType("mypage"));
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mycontrol"));
}
[Test]
public void DoesNotGenerateObjectNameIfIdAndNameAttributeSpecified()
{
const string CONTEXTPATH = "/";
const string xml =
@"<?xml version='1.0' encoding='UTF-8' ?>
<objects xmlns='http://www.springframework.net'>
<object id='mypage' name='mypageAlias' type='~/MyPage.aspx' />
<object id='mycontrol' name='mycontrolAlias' type='~/MyControl.ascx' />
</objects>";
WebObjectFactory objectFactory = new WebObjectFactory(CONTEXTPATH, false);
TestWebObjectDefinitionReader reader = new TestWebObjectDefinitionReader(objectFactory.ContextPath, objectFactory, new XmlUrlResolver());
using (VirtualEnvironmentMock env = new VirtualEnvironmentMock(CONTEXTPATH + "test.aspx", null, null, CONTEXTPATH, true))
{
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyPage.aspx"] = typeof(Spring.Web.UI.Page);
env.VirtualPath2ArtifactsTable[CONTEXTPATH + "MyControl.ascx"] = typeof(Spring.Web.UI.UserControl);
reader.LoadObjectDefinitions(new StringResource(xml));
}
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mypage"));
Assert.IsTrue(objectFactory.ContainsObject("mypageAlias"));
Assert.IsTrue(objectFactory.ContainsObjectDefinition("mycontrol"));
Assert.IsTrue(objectFactory.ContainsObject("mycontrolAlias"));
}
}
}

View File

@@ -104,6 +104,8 @@
<Compile Include="Objects\Factory\Support\WebObjectFactoryTests.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Factory\Support\WebObjectUtilsTests.cs" />
<Compile Include="Objects\Factory\Xml\WebObjectDefinitionReaderTests.cs" />
<Compile Include="TestSupport\NUnitAdapter.cs" />
<Compile Include="TestSupport\SessionMock.cs" />
<Compile Include="TestSupport\TestPage.cs">

View File

@@ -2,6 +2,9 @@ using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;
using Spring.Collections;
using Spring.Util;
@@ -15,20 +18,30 @@ namespace Spring.TestSupport
{
private readonly IVirtualEnvironment _prevEnvironment;
private readonly string _currentVirtualFilePath;
private readonly string _pathInfo;
private string _currentVirtualFilePath;
private string _pathInfo;
private HttpValueCollection _query;
private string _currentExecutionFilePath;
private readonly string _applicationVirtualPath;
private ISessionState _session = new SessionMock();
private IDictionary _requestVariables = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
private NameValueCollection requestParams = new NameValueCollection();
private IDictionary virtualPath2ArtifactsTable = new CaseInsensitiveHashtable();
public VirtualEnvironmentMock(string currentVirtualFilePath, string pathInfo, string applicationVirtualPath, bool autoInitialize)
public VirtualEnvironmentMock(string currentVirtualFilePath, string pathInfo, string queryText, string applicationVirtualPath, bool autoInitialize)
{
_currentVirtualFilePath = currentVirtualFilePath;
_currentExecutionFilePath = currentVirtualFilePath;
_pathInfo = (pathInfo == null || pathInfo.Length == 0) ? "" : "/" + pathInfo.TrimStart('/'); // prevent null string and ensure '/' prefixed
_query = new HttpValueCollection(queryText);
_applicationVirtualPath = "/" + ("" + applicationVirtualPath).Trim('/');
if (!_applicationVirtualPath.EndsWith("/")) _applicationVirtualPath = _applicationVirtualPath + "/";
// if (!_currentVirtualFilePath.StartsWith(_applicationVirtualPath))
// {
// throw new ArgumentException("currentVirtualFilePath must begin with applicationVirtualPath");
// }
_prevEnvironment = VirtualEnvironment.SetInstance(this);
if (autoInitialize)
{
@@ -36,6 +49,11 @@ namespace Spring.TestSupport
}
}
public IDictionary VirtualPath2ArtifactsTable
{
get { return virtualPath2ArtifactsTable; }
}
public string ApplicationVirtualPath
{
get { return _applicationVirtualPath; }
@@ -43,9 +61,19 @@ namespace Spring.TestSupport
public string CurrentVirtualPath
{
get
{
return _currentVirtualFilePath + _pathInfo;
get { return _currentVirtualFilePath + _pathInfo; }
}
public string CurrentVirtualPathAndQuery
{
get
{
string result = _currentVirtualFilePath + _pathInfo;
if (_query.Count > 0)
{
result = result + "?" + _query.ToString();
}
return result;
}
}
@@ -60,14 +88,58 @@ namespace Spring.TestSupport
set { this._currentExecutionFilePath = value; }
}
public NameValueCollection QueryString
{
get { return _query; }
}
public string MapPath(string virtualPath)
{
string basePath = Path.GetDirectoryName(new Uri(GetType().Assembly.CodeBase).LocalPath);
string resultPath = WebUtils.CreateAbsolutePath(this.ApplicationVirtualPath, virtualPath);
string resultPath = WebUtils.CreateAbsolutePath(this.CurrentVirtualFilePath, virtualPath);
resultPath = basePath.TrimEnd('\\') + "\\" + resultPath.Replace('/', '\\').TrimStart('\\');
return resultPath;
}
public IDisposable RewritePath(string newVirtualPath, bool rebaseClientPath)
{
IDisposable ctx = new RewriteContext(CurrentVirtualPathAndQuery, false, this);
int index = newVirtualPath.IndexOf('?');
if (index >= 0)
{
string newQueryString = (index < (newVirtualPath.Length - 1)) ? newVirtualPath.Substring(index + 1) : string.Empty;
_query = new HttpValueCollection(newQueryString);
newVirtualPath = newVirtualPath.Substring(0, index);
}
_currentVirtualFilePath = newVirtualPath;
return ctx;
}
public Type GetCompiledType(string virtualPath)
{
object o = virtualPath2ArtifactsTable[virtualPath];
if (o == null)
throw new FileNotFoundException(virtualPath);
else if (o is Type)
return (Type) o;
else
return o.GetType();
}
public object CreateInstanceFromVirtualPath(string virtualPath, Type requiredBaseType)
{
object o = virtualPath2ArtifactsTable[virtualPath];
if (o == null)
throw new FileNotFoundException(virtualPath);
else if (o is Type)
return Activator.CreateInstance((Type)o);
else
return o;
}
public ISessionState Session
{
get { return _session; }
@@ -80,9 +152,152 @@ namespace Spring.TestSupport
set { _requestVariables = value; }
}
public NameValueCollection RequestParams
{
get { return requestParams; }
}
public void Dispose()
{
VirtualEnvironment.SetInstance(_prevEnvironment);
}
private class RewriteContext : IDisposable
{
private string originalPath;
private bool rebaseClientPath;
private VirtualEnvironmentMock runtime;
public RewriteContext(string originalPath, bool rebaseClientPath, VirtualEnvironmentMock runtime)
{
this.originalPath = originalPath;
this.rebaseClientPath = rebaseClientPath;
this.runtime = runtime;
}
public void Dispose()
{
if (originalPath != null)
{
this.runtime.RewritePath(originalPath, rebaseClientPath);
}
}
}
private class HttpValueCollection : NameValueCollection
{
public HttpValueCollection(string queryText)
{
FillFromString(queryText, false, Encoding.UTF8);
}
public override string ToString()
{
return ToString(true);
}
private void FillFromString(string s, bool urlencoded, Encoding encoding)
{
int num = (s != null) ? s.Length : 0;
for (int i = 0; i < num; i++)
{
int startIndex = i;
int num4 = -1;
while (i < num)
{
char ch = s[i];
if (ch == '=')
{
if (num4 < 0)
{
num4 = i;
}
}
else if (ch == '&')
{
break;
}
i++;
}
string str = null;
string str2 = null;
if (num4 >= 0)
{
str = s.Substring(startIndex, num4 - startIndex);
str2 = s.Substring(num4 + 1, (i - num4) - 1);
}
else
{
str2 = s.Substring(startIndex, i - startIndex);
}
if (urlencoded)
{
base.Add(HttpUtility.UrlDecode(str, encoding), HttpUtility.UrlDecode(str2, encoding));
}
else
{
base.Add(str, str2);
}
if ((i == (num - 1)) && (s[i] == '&'))
{
base.Add(null, string.Empty);
}
}
}
internal virtual string ToString(bool urlencoded)
{
StringBuilder builder = new StringBuilder();
int count = this.Count;
for (int i = 0; i < count; i++)
{
string str3;
string key = this.GetKey(i);
if (urlencoded)
{
key = HttpUtility.UrlEncodeUnicode(key);
}
string str2 = ((key != null) && (key.Length > 0)) ? (key + "=") : "";
ArrayList list = (ArrayList)base.BaseGet(i);
int num3 = (list != null) ? list.Count : 0;
if (i > 0)
{
builder.Append('&');
}
if (num3 == 1)
{
builder.Append(str2);
str3 = (string)list[0];
if (urlencoded)
{
str3 = HttpUtility.UrlEncodeUnicode(str3);
}
builder.Append(str3);
}
else if (num3 == 0)
{
builder.Append(str2);
}
else
{
for (int j = 0; j < num3; j++)
{
if (j > 0)
{
builder.Append('&');
}
builder.Append(str2);
str3 = (string)list[j];
if (urlencoded)
{
str3 = HttpUtility.UrlEncodeUnicode(str3);
}
builder.Append(str3);
}
}
}
return builder.ToString();
}
}
}
}

View File

@@ -39,34 +39,6 @@ namespace Spring.Util
{
private const string ExpectedPageName = "foo";
[Test]
[ExpectedException(typeof (ArgumentNullException))]
public void GetPageTypeWithNullPageName()
{
WebObjectUtils.GetPageType(null);
}
[Test]
[ExpectedException(typeof (ArgumentNullException))]
public void GetPageTypeWithEmptyStringPageName()
{
WebObjectUtils.GetPageType(string.Empty);
}
[Test]
[ExpectedException(typeof (ArgumentNullException))]
public void GetPageTypeWithWhitespacedPageName()
{
WebObjectUtils.GetPageType(" ");
}
[Test]
[ExpectedException(typeof (ObjectCreationException))]
public void CreatePageInstanceWhenNotRunningInServerContext()
{
WebObjectUtils.CreatePageInstance("foo.aspx");
}
[Test]
[ExpectedException(typeof (ArgumentNullException))]
public void GetPageNameWithNullUrl()
@@ -180,7 +152,7 @@ namespace Spring.Util
public void CombineVirtualPathsInRootWeb()
{
// emulate root website context
using( new VirtualEnvironmentMock("/somedir/some.file", null, "/", true) )
using( new VirtualEnvironmentMock("/somedir/some.file", null, null, "/", true) )
{
CombineVirtualPathsSuite( "/" );
}
@@ -190,7 +162,7 @@ namespace Spring.Util
public void CombineVirtualPathsInChildWeb()
{
// emulate child website context
using( new VirtualEnvironmentMock("/somedir/some.file", null, "/myapp", true) )
using( new VirtualEnvironmentMock("/somedir/some.file", null, null, "/myapp", true) )
{
CombineVirtualPathsSuite( "/myapp/" );
}