diff --git a/src/Spring/Spring.Template.Velocity.Castle/Spring.Template.Velocity.Castle.2010.csproj b/src/Spring/Spring.Template.Velocity.Castle/Spring.Template.Velocity.Castle.2010.csproj
index 19205663..99cbac0a 100644
--- a/src/Spring/Spring.Template.Velocity.Castle/Spring.Template.Velocity.Castle.2010.csproj
+++ b/src/Spring/Spring.Template.Velocity.Castle/Spring.Template.Velocity.Castle.2010.csproj
@@ -76,9 +76,6 @@
Template\Velocity\CommonsLoggingLogSystem.cs
-
- Template\Velocity\Config\TemplateNamespaceParser.cs
-
Template\Velocity\VelocityConstants.cs
@@ -92,6 +89,7 @@
Template\Velocity\VelocityEngineUtils.cs
+
diff --git a/src/Spring/Spring.Template.Velocity.Castle/Template/Velocity/Config/TemplateNamespaceParser.cs b/src/Spring/Spring.Template.Velocity.Castle/Template/Velocity/Config/TemplateNamespaceParser.cs
new file mode 100644
index 00000000..394ccdfa
--- /dev/null
+++ b/src/Spring/Spring.Template.Velocity.Castle/Template/Velocity/Config/TemplateNamespaceParser.cs
@@ -0,0 +1,473 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+using NVelocity.Runtime;
+
+using Spring.Core.TypeResolution;
+using Spring.Objects;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+using Spring.Objects.Factory.Xml;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Template.Velocity.Config {
+ ///
+ /// Implementation of the custom configuration parser for template configurations
+ /// based on
+ ///
+ ///
+ /// Erez Mazor
+ ///
+ [
+ NamespaceParser(
+ Namespace = "http://www.springframework.net/nvelocity",
+ SchemaLocationAssemblyHint = typeof(TemplateNamespaceParser),
+ SchemaLocation = "/Spring.Template.Velocity.Config/spring-nvelocity-1.3.xsd")
+ ]
+ public class TemplateNamespaceParser : ObjectsNamespaceParser {
+ private const string TemplateTypePrefix = "template: ";
+
+ static TemplateNamespaceParser() {
+ TypeRegistry.RegisterType(TemplateTypePrefix + TemplateDefinitionConstants.NVelocityElement, typeof(VelocityEngineFactoryObject));
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TemplateNamespaceParser() {
+ }
+
+ ///
+ public override IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext) {
+ string name = element.GetAttribute(ObjectDefinitionConstants.IdAttribute);
+ IConfigurableObjectDefinition templateDefinition = ParseTemplateDefinition(element, parserContext);
+ if (!StringUtils.HasText(name)) {
+ name = ObjectDefinitionReaderUtils.GenerateObjectName(templateDefinition, parserContext.Registry);
+ }
+ parserContext.Registry.RegisterObjectDefinition(name, templateDefinition);
+ return null;
+ }
+
+ ///
+ /// Parse a template definition from the templating namespace
+ ///
+ /// the root element defining the templating object
+ /// the parser context
+ ///
+ private IConfigurableObjectDefinition ParseTemplateDefinition(XmlElement element, ParserContext parserContext) {
+ switch (element.LocalName) {
+ case TemplateDefinitionConstants.NVelocityElement:
+ return ParseNVelocityEngine(element, parserContext);
+ default:
+ throw new ArgumentException(string.Format("undefined element for templating namespace: {0}", element.LocalName));
+ }
+ }
+
+ ///
+ /// Parses the object definition for the engine object, configures a single NVelocity template engine based
+ /// on the element definitions.
+ ///
+ /// the root element defining the velocity engine
+ /// the parser context
+ private IConfigurableObjectDefinition ParseNVelocityEngine(XmlElement element, ParserContext parserContext) {
+ string typeName = GetTypeName(element);
+ IConfigurableObjectDefinition configurableObjectDefinition = parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition(
+ typeName, null, parserContext.ReaderContext.Reader.Domain);
+
+ string preferFileSystemAccess = GetAttributeValue(element, TemplateDefinitionConstants.AttributePreferFileSystemAccess);
+ string overrideLogging = GetAttributeValue(element, TemplateDefinitionConstants.AttributeOverrideLogging);
+ string configFile = GetAttributeValue(element, TemplateDefinitionConstants.AttributeConfigFile);
+
+ MutablePropertyValues objectDefinitionProperties = new MutablePropertyValues();
+ if (StringUtils.HasText(preferFileSystemAccess)) {
+ objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyPreferFileSystemAccess, preferFileSystemAccess);
+ }
+
+ if (StringUtils.HasText(overrideLogging)) {
+ objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyOverrideLogging, overrideLogging);
+ }
+
+ if (StringUtils.HasText(configFile)) {
+ objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyConfigFile, configFile);
+ }
+
+ XmlNodeList childElements = element.ChildNodes;
+ if (childElements.Count > 0) {
+ ParseChildDefinitions(childElements, parserContext, objectDefinitionProperties);
+ }
+ configurableObjectDefinition.PropertyValues = objectDefinitionProperties;
+ return configurableObjectDefinition;
+ }
+
+ ///
+ /// Parses child element definitions for the NVelocity engine. Typically resource loaders and locally defined properties are parsed here
+ ///
+ /// the XmlNodeList representing the child configuration of the root NVelocity engine element
+ /// the parser context
+ /// the MutablePropertyValues used to configure this object
+ private void ParseChildDefinitions(XmlNodeList childElements, ParserContext parserContext, MutablePropertyValues objectDefinitionProperties) {
+ IDictionary properties = new Dictionary();
+
+ foreach (XmlElement element in childElements) {
+ switch (element.LocalName) {
+ case TemplateDefinitionConstants.ElementResourceLoader:
+ ParseResourceLoader(element, objectDefinitionProperties, properties);
+ break;
+ case TemplateDefinitionConstants.ElementNVelocityProperties:
+ ParseNVelocityProperties(element, parserContext, properties);
+ break;
+ }
+ }
+
+ if (properties.Count > 0) {
+ objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyVelocityProperties, properties);
+ }
+ }
+
+ ///
+ /// Configures the NVelocity resource loader definitions from the xml definition
+ ///
+ /// the root resource loader element
+ /// the MutablePropertyValues used to configure this object
+ /// the properties used to initialize the velocity engine
+ private void ParseResourceLoader(XmlElement element, MutablePropertyValues objectDefinitionProperties, IDictionary properties) {
+ string caching = GetAttributeValue(element, TemplateDefinitionConstants.AttributeTemplateCaching);
+ string defaultCacheSize = GetAttributeValue(element, TemplateDefinitionConstants.AttributeDefaultCacheSize);
+ string modificationCheckInterval = GetAttributeValue(element, TemplateDefinitionConstants.AttributeModificationCheckInterval);
+
+ if (!string.IsNullOrEmpty(defaultCacheSize)) {
+ properties.Add(RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE, defaultCacheSize);
+ }
+
+ XmlNodeList loaderElements = element.ChildNodes;
+ switch (loaderElements[0].LocalName) {
+ case VelocityConstants.File:
+ AppendFileLoaderProperties(loaderElements, properties);
+ AppendResourceLoaderGlobalProperties(properties, VelocityConstants.File, caching,
+ modificationCheckInterval);
+ break;
+ case VelocityConstants.Assembly:
+ AppendAssemblyLoaderProperties(loaderElements, properties);
+ AppendResourceLoaderGlobalProperties(properties, VelocityConstants.Assembly, caching, null);
+ break;
+ case TemplateDefinitionConstants.Spring:
+ AppendResourceLoaderPaths(loaderElements, objectDefinitionProperties);
+ AppendResourceLoaderGlobalProperties(properties, TemplateDefinitionConstants.Spring, caching, null);
+ break;
+ case TemplateDefinitionConstants.Custom:
+ XmlElement firstElement = (XmlElement)loaderElements.Item(0);
+ AppendCustomLoaderProperties(firstElement, properties);
+ AppendResourceLoaderGlobalProperties(properties, firstElement.LocalName, caching, modificationCheckInterval);
+ break;
+ default:
+ throw new ArgumentException(string.Format("undefined element for resource loadre type: {0}", element.LocalName));
+ }
+ }
+
+
+ ///
+ /// Set the caching and modification interval checking properties of a resource loader of a given type
+ ///
+ /// the properties used to initialize the velocity engine
+ /// type of the resource loader
+ /// caching flag
+ /// modification interval value
+ private void AppendResourceLoaderGlobalProperties(IDictionary properties, string type, string caching, string modificationInterval) {
+ AppendResourceLoaderGlobalProperty(properties, type,
+ TemplateDefinitionConstants.PropertyResourceLoaderCaching,
+ Convert.ToBoolean(caching));
+ AppendResourceLoaderGlobalProperty
+ (properties, type, TemplateDefinitionConstants.PropertyResourceLoaderModificationCheckInterval, Convert.ToInt64(modificationInterval));
+ }
+
+ ///
+ /// Set global velocity resource loader properties (caching, modification interval etc.)
+ ///
+ /// the properties used to initialize the velocity engine
+ /// the type of resource loader
+ /// the suffix property
+ /// the value of the property
+ private void AppendResourceLoaderGlobalProperty(IDictionary properties, string type, string property, object value) {
+ if (null != value) {
+ properties.Add(type + VelocityConstants.Separator + property, value);
+ }
+ }
+
+ ///
+ /// Creates a nvelocity file based resource loader by setting the required properties
+ ///
+ /// a list of nv:file elements defining the paths to template files
+ /// the properties used to initialize the velocity engine
+ private void AppendFileLoaderProperties(XmlNodeList elements, IDictionary properties) {
+ IList paths = new List(elements.Count);
+ foreach (XmlElement element in elements)
+ {
+ paths.Add(GetAttributeValue(element, VelocityConstants.Path));
+ }
+ properties.Add(RuntimeConstants.RESOURCE_LOADER, VelocityConstants.File);
+ properties.Add(getResourceLoaderProperty(VelocityConstants.File, VelocityConstants.Class), TemplateDefinitionConstants.FileResourceLoaderClass);
+ properties.Add(getResourceLoaderProperty(VelocityConstants.File, VelocityConstants.Path), StringUtils.CollectionToCommaDelimitedString(paths));
+ }
+
+ ///
+ /// Creates a nvelocity assembly based resource loader by setting the required properties
+ ///
+ /// a list of nv:assembly elements defining the assemblies
+ /// the properties used to initialize the velocity engine
+ private void AppendAssemblyLoaderProperties(XmlNodeList elements, IDictionary properties) {
+ IList assemblies = new List(elements.Count);
+ foreach (XmlElement element in elements) {
+ assemblies.Add(GetAttributeValue(element, VelocityConstants.Name));
+ }
+ properties.Add(RuntimeConstants.RESOURCE_LOADER, VelocityConstants.Assembly);
+ properties.Add(getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Class), TemplateDefinitionConstants.AssemblyResourceLoaderClass);
+ properties.Add(getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Assembly), StringUtils.CollectionToCommaDelimitedString(assemblies));
+ }
+
+ ///
+ /// Creates a spring resource loader by setting the ResourceLoaderPaths of the
+ /// engine factory (the resource loader itself will be created internally either as
+ /// spring or as file resource loader based on the value of prefer-file-system-access
+ /// attribute).
+ ///
+ /// list of resource loader path elements
+ /// the MutablePropertyValues to set the property for the engine factory
+ private void AppendResourceLoaderPaths(XmlNodeList elements, MutablePropertyValues objectDefinitionProperties) {
+ IList paths = new List();
+ foreach (XmlElement element in elements) {
+ string path = GetAttributeValue(element, TemplateDefinitionConstants.AttributeUri);
+ paths.Add(path);
+ }
+ objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyResourceLoaderPaths, paths);
+ }
+
+ ///
+ /// Create a custom resource loader from an nv:custom element
+ /// generates the 4 required nvelocity props for a resource loader (name, description, class and path).
+ ///
+ /// the nv:custom xml definition element
+ /// the properties used to initialize the velocity engine
+ private void AppendCustomLoaderProperties(XmlElement element, IDictionary properties) {
+ string name = GetAttributeValue(element, VelocityConstants.Name);
+ string description = GetAttributeValue(element, VelocityConstants.Description);
+ string type = GetAttributeValue(element, VelocityConstants.Type);
+ string path = GetAttributeValue(element, VelocityConstants.Path);
+ properties.Add(RuntimeConstants.RESOURCE_LOADER, name);
+ properties.Add(getResourceLoaderProperty(name, VelocityConstants.Description), description);
+ properties.Add(getResourceLoaderProperty(name, VelocityConstants.Class), type.Replace(',', ';'));
+ properties.Add(getResourceLoaderProperty(name, VelocityConstants.Path), path);
+ }
+
+ ///
+ /// Parses the nvelocity properties map using ObjectNamespaceParserHelper
+ /// and appends it to the properties dictionary
+ ///
+ /// root element of the map element
+ /// the parser context
+ /// the properties used to initialize the velocity engine
+ private void ParseNVelocityProperties(XmlElement element, ParserContext parserContext, IDictionary properties) {
+ IDictionary parsedProperties = ParseDictionaryElement(element,
+ TemplateDefinitionConstants.ElementNVelocityProperties, parserContext);
+ foreach (DictionaryEntry entry in parsedProperties) {
+ properties.Add(Convert.ToString(entry.Key), entry.Value);
+ }
+ }
+
+ ///
+ /// Gets the name of the object type for the specified element.
+ ///
+ /// The element.
+ /// The name of the object type.
+ private string GetTypeName(XmlElement element) {
+ string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute);
+ if (StringUtils.IsNullOrEmpty(typeName)) {
+ return TemplateTypePrefix + element.LocalName;
+ }
+ return typeName;
+ }
+
+ ///
+ /// constructs an nvelocity style resource loader property in the format:
+ /// prefix.resource.loader.suffix
+ ///
+ /// the prefix
+ /// the suffix
+ /// a concatenated string like: prefix.resource.loader.suffix
+ public static string getResourceLoaderProperty(string type, string suffix) {
+ return type + VelocityConstants.Separator + RuntimeConstants.RESOURCE_LOADER + VelocityConstants.Separator +
+ suffix;
+ }
+
+ ///
+ /// This method is overriden from ObjectsNamespaceParser since when invoked on
+ /// sub-elements from the objets namespace (e.g., objects:objectMap for nvelocity
+ /// property map) the element.SelectNodes fails because it is in
+ /// the nvelocity custom namespace and not the object's namespace (http://www.springframwork.net)
+ /// to amend this the object's namespace is added to the provided XmlNamespaceManager
+ ///
+ /// The element to be searched in.
+ /// The name of the child nodes to look for.
+ ///
+ /// The child s of the supplied
+ /// with the supplied .
+ ///
+ ///
+ [Obsolete("not used anymore - ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead")]
+ protected override XmlNodeList SelectNodes(XmlElement element, string childElementName) {
+ XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable());
+ nsManager.AddNamespace(GetNamespacePrefix(element), element.NamespaceURI);
+ nsManager.AddNamespace(GetNamespacePrefix(element), Namespace);
+ return element.SelectNodes(GetNamespacePrefix(element) + ":" + childElementName, nsManager);
+ }
+
+ private string GetNamespacePrefix(XmlElement element) {
+ return StringUtils.HasText(element.Prefix) ? element.Prefix : "spring";
+ }
+ }
+
+
+
+ #region Element & Attribute Name Constants
+
+ ///
+ /// Template definition constants
+ ///
+ public class TemplateDefinitionConstants {
+ ///
+ /// Engine element definition
+ ///
+ public const string NVelocityElement = "engine";
+
+ ///
+ /// Spring resource loader element definition
+ ///
+ public const string Spring = "spring";
+
+ ///
+ /// Custom resource loader element definition
+ ///
+ public const string Custom = "custom";
+
+ ///
+ /// uri attribute of the spring element
+ ///
+ public const string AttributeUri = "uri";
+
+ ///
+ /// prefer-file-system-access attribute of the engine factory
+ ///
+ public const string AttributePreferFileSystemAccess = "prefer-file-system-access";
+
+ ///
+ /// config-file attribute of the engine factory
+ ///
+ public const string AttributeConfigFile = "config-file";
+
+ ///
+ /// override-logging attribute of the engine factory
+ ///
+ public const string AttributeOverrideLogging = "override-logging";
+
+ ///
+ /// template-caching attribute of the nvelocity engine
+ ///
+ public const string AttributeTemplateCaching = "template-caching";
+
+ ///
+ /// default-cache-size attribute of the nvelocity engine resource manager
+ ///
+ public const string AttributeDefaultCacheSize = "default-cache-size";
+
+ ///
+ /// modification-check-interval attribute of the nvelocity engine resource loader
+ ///
+ public const string AttributeModificationCheckInterval = "modification-check-interval";
+
+ ///
+ /// resource loader element
+ ///
+ public const string ElementResourceLoader = "resource-loader";
+
+ ///
+ /// nvelocity propeties element (map)
+ ///
+ public const string ElementNVelocityProperties = "nvelocity-properties";
+
+ ///
+ /// PreferFileSystemAccess property of the engine factory
+ ///
+ public const string PropertyPreferFileSystemAccess = "PreferFileSystemAccess";
+
+ ///
+ /// OverrideLogging property of the engine factory
+ ///
+ public const string PropertyOverrideLogging = "OverrideLogging";
+
+ ///
+ /// ConfigLocation property of the engine factory
+ ///
+ public const string PropertyConfigFile = "ConfigLocation";
+
+ ///
+ /// ResourceLoaderPaths property of the engine factory
+ ///
+ public const string PropertyResourceLoaderPaths = "ResourceLoaderPaths";
+
+ ///
+ /// VelocityProperties property of the engine factory
+ ///
+ public const string PropertyVelocityProperties = "VelocityProperties";
+
+ ///
+ /// resource.loader.cache property of the resource loader configuration
+ ///
+ public const string PropertyResourceLoaderCaching = "resource.loader.cache";
+
+ ///
+ /// resource.loader.modificationCheckInterval property of the resource loader configuration
+ ///
+ public const string PropertyResourceLoaderModificationCheckInterval = "resource.loader.modificationCheckInterval";
+
+ ///
+ /// the type used for file resource loader
+ ///
+ public const string FileResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.FileResourceLoader; NVelocity";
+
+ ///
+ /// the type used for assembly resource loader
+ ///
+ public const string AssemblyResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader; NVelocity";
+
+ ///
+ /// the type used for spring resource loader
+ ///
+ public const string SpringResourceLoaderClass = "Spring.Template.Velocity.SpringResourceLoader; Spring.Template.Velocity.Castle";
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/Config/TemplateNamespaceParserTests.cs b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/Config/TemplateNamespaceParserTests.cs
index 91172f8e..6a00cffd 100644
--- a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/Config/TemplateNamespaceParserTests.cs
+++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/Config/TemplateNamespaceParserTests.cs
@@ -85,7 +85,7 @@ namespace Spring.Template.Velocity.Config {
Assert.AreEqual(VelocityConstants.Assembly, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader");
Assert.AreEqual(TemplateDefinitionConstants.AssemblyResourceLoaderClass, getSingleProperty(velocityEngine,
TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Class)), "incorrect resource loader type");
- Assert.AreEqual("Spring.Template.Velocity.Tests", getSingleProperty(velocityEngine,
+ Assert.AreEqual("Spring.Template.Velocity.Castle.Tests", getSingleProperty(velocityEngine,
TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.Assembly,VelocityConstants.Assembly)), "incorrect resource loader path");
Assert.AreEqual(DEFAULT_CACHE_SIZE, velocityEngine.GetProperty(RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE), "incorrect default cache size");
Assert.AreEqual(DEFAULT_CACHE_FLAG, velocityEngine.GetProperty(VelocityConstants.Assembly + VelocityConstants.Separator + PropertyResourceLoaderCachce),
@@ -155,7 +155,7 @@ namespace Spring.Template.Velocity.Config {
Assert.AreEqual(PropertyMyResourceLoader, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader");
- Assert.AreEqual("Spring.Template.Velocity.Config.TestCustomResourceLoader; Spring.Template.Velocity.Tests",
+ Assert.AreEqual("Spring.Template.Velocity.Config.TestCustomResourceLoader; Spring.Template.Velocity.Castle.Tests",
getSingleProperty(velocityEngine, classProp), "incorrect resource loader type");
Assert.AreEqual(PropertyMyResourceLoader, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader");
Assert.AreEqual("A custom resource loader",