diff --git a/doc/reference/src/templating.xml b/doc/reference/src/templating.xml index e426eaa5..b2ab0d8a 100644 --- a/doc/reference/src/templating.xml +++ b/doc/reference/src/templating.xml @@ -51,7 +51,7 @@ linkend="objects-factory-lifecycle-factoryobject" />. A custom namespace parser is provided to simplify the configuration of a NVelocity template engine. For more information on custom namespace parser see . + linkend="context-custom-parsers" />.
Simple file based template engine definition @@ -67,7 +67,8 @@ </objects> The velocity engine could then be used to load and merge a local - template using a simple relative path: + template using a simple relative path (the default resource loader path + is the current execution directory): StringWriter stringWriter = new StringWriter(); Hashtable modelTable = new Hashtable(); @@ -81,6 +82,86 @@ string mergedContent = stringWriter.ToString(); <engine/> to false.
+
+ Configuration Options + + You can define several attributes on the <engine> element to + control how the factory is configured: + + + Engine Factory Configuration Options + + + + + + + + + + + + + Attribute + + Description + + Required + + Default Value + + + + + + config-file + + + A uri of a properties file defining the NVelocity + configuration. This value accepts all spring resource loader + uri (e.g., file://, http://). See + + + no + + N/A + + + + prefer-file-system-access + + + Instructs the NVelocity engine factory to attempt use + NVelocity's file loader. When set to false the provided + SpringResourceLoader will be used (and the ResourceLoaderPath + property must be set) + + + no + + true + + + + override-logging + + + Instructs the NVelocity engine factory to use the + provided spring commons logging based logging system. See See + + + + no + + true + + + +
+
+
Assembly based template loading @@ -99,7 +180,7 @@ string mergedContent = stringWriter.ToString(); velocityEngine.MergeTemplate("MyAssembly.MyNamespace.MyTemplate.vm", Encoding.UTF8.WebName, velocityContext, stringWriter);
-
+
Using Spring's <literal>IResourceLoader</literal> to load templates @@ -110,9 +191,9 @@ string mergedContent = stringWriter.ToString(); object definition loads the NVelocity templates from a single path - <nv:engine id="velocityEngine"> + <nv:engine id="velocityEngine"> <nv:resource-loader> - <nv:file path="MyTemplateFolder/AnotherFolder/" /> + <nv:spring uri="file://Template/Velocity/"/> </nv:resource-loader> </nv:engine> @@ -120,24 +201,127 @@ string mergedContent = stringWriter.ToString(); <nv:engine id="velocityEngine"> <nv:resource-loader> - <nv:file path="MyTemplateFolder/AnotherFolder/" /> - <nv:file path="MyOtherTemplateFolder/" /> + <nv:spring uri="file://Template/Velocity/"/> + <nv:spring uri="assembly://MyAssembly/MyNameSpace"/> </nv:resource-loader> </nv:engine> - By default spring will attempt to load resources using file - based template loading (useful for detection of template changes at - runtime). If this is not desirable you set the - prefer-file-system-access element of the - </engine> element to false. + By default spring will attempt to load resources using NVelocity's + file based template loading (useful for detection of template changes at + runtime). If this is not desirable you set the + prefer-file-system-access property of the factory object + to false which will cause the factory to utilize the supplied + spring resource loader. Using the example above when resource loader paths are defined templates can be loaded using their name: - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntostring(velocityEngine, "MyTemplate.vm", Encoding.UTF8.WebName, model); + string mergedTemplate = VelocityEngineUtils.MergeTemplateIntostring(velocityEngine, "MyFileTemplate.vm", Encoding.UTF8.WebName, model); // template loaded from file://Template/Velocity/ +string mergedTemplate = VelocityEngineUtils.MergeTemplateIntostring(velocityEngine, "MyAseemblyTemplate.vm", Encoding.UTF8.WebName, model); // template loaded from assembly://MyAssembly/MyNameSpace +
+ +
+ Defining a custom resource loader + + The following defines a custom resource loader (the type is an + extension of NVelocity's ResourceLoader + class): + + <nv:engine id="velocityEngine"> + <nv:resource-loader> + <nv:custom name="myResourceLoader" + description="A custom resource loader" + type="MyNamespace.MyResourceLoader, MyAssembly" + path="Template/Velocity/"/> + </nv:resource-loader> +</nv:engine> + +
+ +
+ Resource Loader configuration options + + The <nv:resource-loader> element has additional attributes + which define how NVelocity's resource manager and resource loader + behave. + + + Resource Loader Configuration Options + + + + + + + + + + + + + Attribute + + Description + + Required + + Default Value + + + + + + default-cache-size + + + defines resource manager global cache size, applies when + caching is turned on. This maps to NVelocity's resource + manager resource.manager.defaultcache.size + property + + + no + + 89 + + + + template-caching + + + Enables template caching for the defined resource + loader. This maps to NVelocity's resource loader + <name>.resource.loader.cache + property + + + no + + false + + + + modification-check-interval + + + The modification check interval value (seconds) of the + resource loader, applies only to resource loader with change + detection capabilities (file or custom). This maps to + NVelocity's resource loader + <name>.resource.loader.modificationCheckInterval + property + + + no + + 2 + + + +
@@ -152,7 +336,7 @@ string mergedContent = stringWriter.ToString(); VelocityProperties property to the NVelocity factory object (shown above) - <nv:engine id="customNamespaceVelocityTemplate" config-file="foo.prop"> + <nv:engine id="velocityTemplate" > <nv:nvelocity-properties> <entry key="input.encoding" value="ISO-8859-1"/> <entry key="output.encoding" value="ISO-8859-1"/> @@ -161,12 +345,8 @@ string mergedContent = stringWriter.ToString();
- - Logging - - By default Spring will override NVelocity's default ILogSystem implementation with its own CommonsLoggingLogSystem implementation so that the @@ -174,12 +354,8 @@ string mergedContent = stringWriter.ToString(); Spring uses. If this is not desirable, you can specify the following property of the NVelocity factory object: - - <template:nvelocity id="velocityEngine" override-logging="false" /> - -
@@ -202,7 +378,7 @@ string mergedContent = stringWriter.ToString(); To create a VelocityEngine using the default file resource loader use the definition: - <!-- Simple no arg file based configuration use's NVeclocity default file resource loader --> + <!-- Simple no arg file based configuration use's NVelocity default file resource loader --> <object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" /> For convenience in defining NVelocity engine instances a custom @@ -210,13 +386,13 @@ string mergedContent = stringWriter.ToString(); done this way: -<objects xmlns="http://www.springframework.net" xmlns:template="http://www.springframework.net/template"> +<objects xmlns="http://www.springframework.net" xmlns:nv="http://www.springframework.net/nvelocity"> -<template:nvelocity id="customNamespaceVelocityTemplate" > - <template:resource-loader> - <template:file path="Template/Velocity/" /> - </template:resource-loader> -</template:nvelocity> +<nv:nvelocity id="velocityEngine" > + <nv:resource-loader> + <nv:file path="Template/Velocity/" /> + </nv:resource-loader> +</nv:nvelocity> </objects @@ -224,7 +400,7 @@ string mergedContent = stringWriter.ToString(); resource loader can be used to define where templates reside: <!-- Assembly based template loading with NVelocity assembly resource loader --> -<object id="assemblyBasedVelocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity"> +<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity"> <property name="VelocityProperties"> <dictionary key-type="string" value-type="object"> <entry key="resource.loader" value="assembly"/> @@ -255,11 +431,12 @@ string mergedContent = stringWriter.ToString(); </object> - By default spring will attempt to load resources using file based - template loading (useful for detection of template changes at runtime). - If this is not desirable you set the + By default spring will attempt to load resources using NVelocity's + file based template loading (useful for detection of template changes at + runtime). If this is not desirable you set the preferFileSystemAccess property of the factory object - to false. + to false which will cause the factory to utilize the supplied + spring resource loader. To refer to a property file based configuration of the @@ -275,7 +452,7 @@ string mergedContent = stringWriter.ToString(); To not integrate with the Common.Logging subsystem, set the - OverrideLogging property to false: + OverrideLogging property to false: <object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" > <property name="OverrideLogging" value="false" /> diff --git a/src/Spring/Spring.Template.Velocity/Spring.Template.Velocity.2008.csproj b/src/Spring/Spring.Template.Velocity/Spring.Template.Velocity.2008.csproj index c5554d35..ffebfb63 100644 --- a/src/Spring/Spring.Template.Velocity/Spring.Template.Velocity.2008.csproj +++ b/src/Spring/Spring.Template.Velocity/Spring.Template.Velocity.2008.csproj @@ -69,7 +69,8 @@ - + + diff --git a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs index c42523af..c2003389 100644 --- a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs +++ b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs @@ -21,9 +21,11 @@ #region Imports using System; +using System.Collections; using System.Collections.Generic; using System.Xml; using NVelocity.Runtime; +using NVelocity.Runtime.Resource.Loader; using Spring.Core.TypeResolution; using Spring.Objects.Factory; using Spring.Objects.Factory.Support; @@ -46,6 +48,7 @@ namespace Spring.Template.Velocity.Config { ] public sealed class TemplateNamespaceParser : AbstractSingleObjectDefinitionParser { private const string TemplateTypePrefix = "template: "; + private static readonly ObjectNamespaceParserHelper objectNamespaceParserHelper = new ObjectNamespaceParserHelper(); static TemplateNamespaceParser() { TypeRegistry.RegisterType(TemplateTypePrefix + TemplateDefinitionConstants.NVelocityElement, typeof(VelocityEngineFactoryObject)); @@ -58,134 +61,369 @@ namespace Spring.Template.Velocity.Config { } /// - /// + /// Parses single object definition for the templating namespace /// - /// - /// - /// + /// the current XmlElement to parse + /// the parser context + /// the ObjectDefinitionBuilder used to configure this object + /// protected override void DoParse(XmlElement element, ParserContext parserContext, ObjectDefinitionBuilder builder) { switch (element.LocalName) { case TemplateDefinitionConstants.NVelocityElement: - ParseNVelocityTemplate(element, parserContext, builder); + ParseNVelocityEngine(element, parserContext, builder); return; default: throw new ArgumentException(string.Format("undefined element for templating namespace: {0}", element.LocalName)); } } - private void ParseNVelocityTemplate(XmlElement element, ParserContext parseContext, ObjectDefinitionBuilder builder) { + /// + /// 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 + /// the ObjectDefinitionBuilder used to configure this object + private void ParseNVelocityEngine(XmlElement element, ParserContext parserContext, ObjectDefinitionBuilder builder) { string preferFileSystemAccess = GetAttributeValue(element, TemplateDefinitionConstants.AttributePreferFileSystemAccess); string overrideLogging = GetAttributeValue(element, TemplateDefinitionConstants.AttributeOverrideLogging); string configFile = GetAttributeValue(element, TemplateDefinitionConstants.AttributeConfigFile); if (StringUtils.HasText(preferFileSystemAccess)) { - builder.AddPropertyValue(NVelocityEngineFactoryProperties.PropertyPreferFileSystemAccess, preferFileSystemAccess); + builder.AddPropertyValue(TemplateDefinitionConstants.PropertyPreferFileSystemAccess, preferFileSystemAccess); } if (StringUtils.HasText(overrideLogging)) { - builder.AddPropertyValue(NVelocityEngineFactoryProperties.PropertyOverrideLogging, overrideLogging); + builder.AddPropertyValue(TemplateDefinitionConstants.PropertyOverrideLogging, overrideLogging); } if (StringUtils.HasText(configFile)) { - builder.AddPropertyValue(NVelocityEngineFactoryProperties.PropertyConfigFile, configFile); + builder.AddPropertyValue(TemplateDefinitionConstants.PropertyConfigFile, configFile); } XmlNodeList childElements = element.ChildNodes; if (childElements.Count > 0) { - ParseChildDefinitions(childElements, parseContext, builder); + ParseChildDefinitions(childElements, parserContext, builder); } } - private void ParseChildDefinitions(XmlNodeList childElements, ParserContext context, ObjectDefinitionBuilder builder) { + /// + /// 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 ObjectDefinitionBuilder used to configure this object + private void ParseChildDefinitions(XmlNodeList childElements, ParserContext parserContext, ObjectDefinitionBuilder builder) { IDictionary properties = new Dictionary(); foreach (XmlElement element in childElements) { switch (element.LocalName) { case TemplateDefinitionConstants.ElementResourceLoader: - ParseResourceLoader(element, context, builder, properties); + ParseResourceLoader(element, builder, properties); break; case TemplateDefinitionConstants.ElementNVelocityProperties: - ParseNVelocityProperties(element, properties); + ParseNVelocityProperties(element, parserContext, properties); break; } } if (properties.Count > 0) { - builder.AddPropertyValue(NVelocityEngineFactoryProperties.PropertyVelocityProperties, properties); + builder.AddPropertyValue(TemplateDefinitionConstants.PropertyVelocityProperties, properties); } } - private void ParseResourceLoader(XmlElement element, ParserContext context, ObjectDefinitionBuilder builder, IDictionary properties) { - string loaderTypeDefinition = GetAttributeValue(element, TemplateDefinitionConstants.AttributeLoaderType); + /// + /// Configures the NVelocity resource loader definitions from the xml definition + /// + /// the root resource loader element + /// the ObjectDefinitionBuilder used to configure this object + /// the properties used to initialize the velocity engine + private void ParseResourceLoader(XmlElement element, ObjectDefinitionBuilder builder, 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; - foreach (XmlElement loaderElement in loaderElements) { - switch (loaderElement.LocalName) { - case TemplateDefinitionConstants.ElementResourceLoaderFile: - AppendResourceLoaderPaths(loaderElements, builder); - break; - case TemplateDefinitionConstants.ElementResourceLoaderAssembly: - AppendAssemblyLoaderProperties((XmlElement)loaderElements.Item(0), properties, loaderTypeDefinition); - break; - } + 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, builder); + 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)); } - } - private void AppendAssemblyLoaderProperties(XmlElement element, IDictionary properties, string loaderTypeDefinition) { - string assemblyName = GetAttributeValue(element, TemplateDefinitionConstants.AttributeName); - string loaderType = (StringUtils.HasText(loaderTypeDefinition)) - ? loaderTypeDefinition - : "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader"; - properties.Add(RuntimeConstants.RESOURCE_LOADER, element.LocalName); - properties.Add(element.LocalName + "." + RuntimeConstants.RESOURCE_LOADER + ".class", loaderType); - properties.Add(element.LocalName + "." + RuntimeConstants.RESOURCE_LOADER + ".assembly", assemblyName); + + /// + /// 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 object definiton builder to set the property for the engine factory private void AppendResourceLoaderPaths(XmlNodeList elements, ObjectDefinitionBuilder builder) { IList paths = new List(); foreach (XmlElement element in elements) { - string path = GetAttributeValue(element, TemplateDefinitionConstants.AttributePath); + string path = GetAttributeValue(element, TemplateDefinitionConstants.AttributeUri); paths.Add(path); } - builder.AddPropertyValue(NVelocityEngineFactoryProperties.PropertyResourceLoaderPaths, paths); + builder.AddPropertyValue(TemplateDefinitionConstants.PropertyResourceLoaderPaths, paths); } - - private void ParseNVelocityProperties(XmlElement element, IDictionary dictionary) { - // todo add impl + /// + /// 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); } - - protected override string GetObjectTypeName(XmlElement element) { - string typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); - if (StringUtils.IsNullOrEmpty(typeName)) { - return TemplateTypePrefix + element.LocalName; + /// + /// 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 = objectNamespaceParserHelper.ParseDictionaryElementInternal(element, "NVelocityProperties", parserContext); + foreach (DictionaryEntry entry in parsedProperties) { + properties.Add(Convert.ToString(entry.Key), entry.Value); } - return typeName; } + /// + /// construct the element type name (e.g, nv:engine, nv:resource-loader) + /// + /// the current xml element + protected override string GetObjectTypeName(XmlElement element) { + return TemplateTypePrefix + element.LocalName; + } + + + /// + /// Helper class to access the ParseDictionaryElement of the ObjectsNamespaceParser + /// todo: remove this and externalize the logic in ObjectsNamespaceParser.ParseDictionaryElement + /// + internal sealed class ObjectNamespaceParserHelper : ObjectsNamespaceParser { + public IDictionary ParseDictionaryElementInternal(XmlElement element, string name, ParserContext parserContext) { + return ParseDictionaryElement(element, name, parserContext); + } + } + + /// + /// 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; + } #region Element & Attribute Name Constants - private class TemplateDefinitionConstants { + /// + /// Template definition constants + /// + public class TemplateDefinitionConstants { + /// + /// Engine element definition + /// public const string NVelocityElement = "engine"; - public const string AttributePreferFileSystemAccess = "prefer-file-system-access"; - public const string AttributeConfigFile = "config-file"; - public const string AttributeOverrideLogging = "override-logging"; - public const string AttributeLoaderType = "loader-type"; - public const string ElementResourceLoader = "resource-loader"; - public const string ElementResourceLoaderFile = "file"; - public const string ElementResourceLoaderAssembly = "assembly"; - public const string ElementNVelocityProperties = "nvelocity-properties"; - public const string AttributeName = "name"; - public const string AttributePath = "path"; - } - private class NVelocityEngineFactoryProperties { + /// + /// 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"; } #endregion } diff --git a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/spring-nvelocity-1.3.xsd b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/spring-nvelocity-1.3.xsd index e1d8060f..951d33cb 100644 --- a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/spring-nvelocity-1.3.xsd +++ b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/spring-nvelocity-1.3.xsd @@ -50,7 +50,8 @@ - + @@ -58,7 +59,8 @@ - + @@ -66,7 +68,8 @@ - + @@ -79,9 +82,10 @@ - + - + @@ -94,7 +98,8 @@ - + @@ -104,14 +109,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + .loader.description property) of the resource loader]]> + + + + + .resource.loader.class property) of the resource loader]]> + + + + + .resource.loader.path property) of the resource loader]]> + + + + - + - + + + + + + + + + .resource.loader.cache property) of the resource loader).]]> + + + + + + .resource.loader.modificationCheckInterval property) of the resource loader, + applies only to resource loader with change detection capabilities (file or custom)]]> - - diff --git a/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityConstants.cs b/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityConstants.cs new file mode 100644 index 00000000..09e64d37 --- /dev/null +++ b/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityConstants.cs @@ -0,0 +1,12 @@ +namespace Spring.Template.Velocity{ + public class VelocityConstants{ + public const string File = "file"; + public const string Type = "type"; + public const string Assembly = "assembly"; + public const string Class = "class"; + public const string Name = "name"; + public const string Description = "description"; + public const string Path = "path"; + public const string Separator = "."; + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityEngineFactory.cs b/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityEngineFactory.cs index 6fbe5f91..34dc126b 100644 --- a/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityEngineFactory.cs +++ b/src/Spring/Spring.Template.Velocity/Template/Velocity/VelocityEngineFactory.cs @@ -31,6 +31,7 @@ using NVelocity.Runtime; using NVelocity.Runtime.Resource.Loader; using Spring.Context.Support; using Spring.Core.IO; +using Spring.Util; namespace Spring.Template.Velocity { /// @@ -195,18 +196,17 @@ namespace Spring.Template.Velocity { /// /// public VelocityEngine CreateVelocityEngine() { - VelocityEngine velocityEngine = NewVelocityEngine(); ExtendedProperties extendedProperties = new ExtendedProperties(); + VelocityEngine velocityEngine = NewVelocityEngine(); - // load defaults - see documentation why this is needed - LoadDefaultProperties(velocityEngine); + LoadDefaultProperties(extendedProperties); // Load config file if set. if (configLocation != null) { if (log.IsInfoEnabled) { log.Info(string.Format("Loading Velocity config from [{0}]", configLocation)); } - FillProperties(extendedProperties, configLocation); + FillProperties(extendedProperties, configLocation, false); } // merge local properties if set. @@ -217,12 +217,12 @@ namespace Spring.Template.Velocity { } // Set a resource loader path, if required. - if( !preferFileSystemAccess && resourceLoaderPaths.Count == 0){ + if (!preferFileSystemAccess && resourceLoaderPaths.Count == 0) { throw new ArgumentException("When using SpringResourceLoader you must provide a path using the ResourceLoaderPath property"); } if (resourceLoaderPaths.Count > 0) { - InitVelocityResourceLoader(velocityEngine, resourceLoaderPaths); + InitVelocityResourceLoader(velocityEngine, extendedProperties, resourceLoaderPaths); } // Log via Commons Logging? @@ -233,13 +233,7 @@ namespace Spring.Template.Velocity { PostProcessVelocityEngine(velocityEngine); try { - // do not init with extended properties rather set one by one - foreach (DictionaryEntry property in extendedProperties) { - velocityEngine.SetProperty(Convert.ToString(property.Key), property.Value); - } - - // velocity engine initialization - required - velocityEngine.Init(); + velocityEngine.Init(extendedProperties); } catch (Exception ex) { throw new VelocityException(ex.ToString(), ex); } @@ -261,16 +255,11 @@ namespace Spring.Template.Velocity { /// directive.manager=NVelocity.Runtime.Directive.DirectiveManager
/// runtime.introspector.uberspect=NVelocity.Util.Introspection.UberspectImpl
///
- /// the instance of the velocity engine unto which we load the default properties - private static void LoadDefaultProperties(VelocityEngine velocityEngine) { - ExtendedProperties extendedProperties = new ExtendedProperties(); + private static void LoadDefaultProperties(ExtendedProperties extendedProperties) { IResource defaultRuntimeProperties = new AssemblyResource("assembly://NVelocity/NVelocity.Runtime.Defaults/nvelocity.properties"); IResource defaultRuntimeDirectives = new AssemblyResource("assembly://NVelocity/NVelocity.Runtime.Defaults/directive.properties"); - FillProperties(extendedProperties, defaultRuntimeProperties); - FillProperties(extendedProperties, defaultRuntimeDirectives); - foreach (DictionaryEntry property in extendedProperties) { - velocityEngine.SetProperty(Convert.ToString(property.Key), property.Value); - } + FillProperties(extendedProperties, defaultRuntimeProperties, true); + FillProperties(extendedProperties, defaultRuntimeDirectives, true); } /// @@ -295,51 +284,37 @@ namespace Spring.Template.Velocity { /// /// /// - protected void InitVelocityResourceLoader(VelocityEngine velocityEngine, IList paths) { - + protected void InitVelocityResourceLoader(VelocityEngine velocityEngine, ExtendedProperties extendedProperties, IList paths) { + if (PreferFileSystemAccess) { // Try to load via the file system, fall back to SpringResourceLoader // (for hot detection of template changes, if possible). IList resolvedPaths = new ArrayList(); - foreach (string path in paths){ + foreach (string path in paths) { IResource resource = ResourceLoader.GetResource(path); resolvedPaths.Add(resource.File.FullName); } try { - - velocityEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, "file"); - velocityEngine.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); - velocityEngine.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, joinList(resolvedPaths)); + extendedProperties.SetProperty(RuntimeConstants.RESOURCE_LOADER, VelocityConstants.File); + extendedProperties.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, + StringUtils.CollectionToCommaDelimitedString(resolvedPaths)); } catch (IOException ex) { if (log.IsDebugEnabled) { - log.Error(string.Format("Cannot resolve resource loader path [{0}] to [File]: using SpringResourceLoader", joinList(resolvedPaths)), ex); + log.Error(string.Format("Cannot resolve resource loader path [{0}] to [File]: using SpringResourceLoader", + StringUtils.CollectionToCommaDelimitedString(resolvedPaths)), ex); } - InitSpringResourceLoader(velocityEngine, joinList(paths)); + InitSpringResourceLoader(velocityEngine, extendedProperties, StringUtils.CollectionToCommaDelimitedString(paths)); } } else { // Always load via SpringResourceLoader (without hot detection of template changes). if (log.IsDebugEnabled) { log.Debug("File system access not preferred: using SpringResourceLoader"); } - InitSpringResourceLoader(velocityEngine, joinList(paths)); + InitSpringResourceLoader(velocityEngine, extendedProperties, StringUtils.CollectionToCommaDelimitedString(paths)); } } - /// - /// Join the list of strings to a comma delimited string - /// - /// values list of strings to join - /// comma delimited string representation of the list - private static string joinList(IList values) { - StringBuilder result = new StringBuilder(); - foreach (string value in values) { - result.Append(value); - result.Append(DELIMITER); - } - return result.ToString(0, result.Length < 1 ? 0 : result.Length - 1); - } - /// /// Initialize a SpringResourceLoader for the given VelocityEngine. ///
Called by InitVelocityResourceLoader. @@ -354,12 +329,11 @@ namespace Spring.Template.Velocity { /// resourceLoaderPath the path to load Velocity resources from /// /// - protected void InitSpringResourceLoader(VelocityEngine velocityEngine, string resourceLoaderPathString) { - velocityEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, SpringResourceLoader.NAME); + protected void InitSpringResourceLoader(VelocityEngine velocityEngine, ExtendedProperties extendedProperties, string resourceLoaderPathString) { + extendedProperties.SetProperty(RuntimeConstants.RESOURCE_LOADER, SpringResourceLoader.NAME); Type springResourceLoaderType = typeof(SpringResourceLoader); string springResourceLoaderTypeName = springResourceLoaderType.FullName + "; " + springResourceLoaderType.Assembly.GetName().Name; - velocityEngine.SetProperty(SpringResourceLoader.SPRING_RESOURCE_LOADER_CLASS, springResourceLoaderTypeName); - velocityEngine.SetProperty(SpringResourceLoader.SPRING_RESOURCE_LOADER_CACHE, "true"); + extendedProperties.SetProperty(SpringResourceLoader.SPRING_RESOURCE_LOADER_CLASS, springResourceLoaderTypeName); velocityEngine.SetApplicationAttribute(SpringResourceLoader.SPRING_RESOURCE_LOADER, ResourceLoader); velocityEngine.SetApplicationAttribute(SpringResourceLoader.SPRING_RESOURCE_LOADER_PATH, resourceLoaderPathString); } @@ -375,7 +349,7 @@ namespace Spring.Template.Velocity { /// /// /// - protected static void PostProcessVelocityEngine(VelocityEngine velocityEngine) { + protected void PostProcessVelocityEngine(VelocityEngine velocityEngine) { } /// @@ -383,9 +357,18 @@ namespace Spring.Template.Velocity { /// /// ExtendedProperties instance to populate /// The resource from which to load the properties - private static void FillProperties(ExtendedProperties extendedProperties, IInputStreamSource resource) { + /// A flag indicated weather the properties loaded from the resource should be appended or replaced in the extendedProperties + private static void FillProperties(ExtendedProperties extendedProperties, IInputStreamSource resource, bool append) { try { - extendedProperties.Load(resource.InputStream); + if (append) { + extendedProperties.Load(resource.InputStream); + } else { + ExtendedProperties overrides = new ExtendedProperties(); + overrides.Load(resource.InputStream); + foreach (DictionaryEntry entry in overrides) { + extendedProperties.SetProperty(Convert.ToString(entry.Key), entry.Value); + } + } } finally { resource.InputStream.Close(); } diff --git a/test/Spring/Spring.Template.Velocity.Tests/Spring.Template.Velocity.Tests.csproj b/test/Spring/Spring.Template.Velocity.Tests/Spring.Template.Velocity.Tests.csproj index 9a8023e8..776b9e23 100644 --- a/test/Spring/Spring.Template.Velocity.Tests/Spring.Template.Velocity.Tests.csproj +++ b/test/Spring/Spring.Template.Velocity.Tests/Spring.Template.Velocity.Tests.csproj @@ -47,7 +47,9 @@ + + @@ -75,6 +77,8 @@ Always + + 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 new file mode 100644 index 00000000..99f142a1 --- /dev/null +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/Config/TemplateNamespaceParserTests.cs @@ -0,0 +1,192 @@ +#region License + +/* + * Copyright 2002-2004 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.Collections; +using System.IO; +using Commons.Collections; +using NUnit.Framework; +using NVelocity.App; +using NVelocity.Runtime; +using NVelocity.Runtime.Resource; +using NVelocity.Runtime.Resource.Loader; +using Spring.Core.IO; +using Spring.Template.Velocity.Config; + +#endregion + +namespace Spring.Template.Velocity.Tests.Template.Velocity.Config { + /// + /// This class contains tests for the template namespace configuration parser + /// + /// Erez Mazor + [TestFixture] + public class TemplateNamespaceParserTests : VelocityEngineTestBase { + #region convinience properties aliases + private const string PropertyModificationCheck = + TemplateNamespaceParser.TemplateDefinitionConstants.PropertyResourceLoaderModificationCheckInterval; + private const string PropertyResourceLoaderCachce = + TemplateNamespaceParser.TemplateDefinitionConstants.PropertyResourceLoaderCaching; + #endregion + + #region test constants + private const int DEFAULT_CACHE_SIZE = 200; + private const int DEFAULT_MOD_CHECK = 30; + private const bool DEFAULT_CACHE_FLAG = true; + #endregion + + /// + /// Test a full file-base configuration + /// + [Test] + public void TestFileBasedConfig() { + VelocityEngine velocityEngine = appContext.GetObject("cnFileVelocityEngine") as VelocityEngine; + Assert.IsNotNull(velocityEngine, "velocity engine is null"); + Assert.AreEqual(VelocityConstants.File, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader"); + Assert.AreEqual(TemplateNamespaceParser.TemplateDefinitionConstants.FileResourceLoaderClass, getSingleProperty(velocityEngine, + TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.File, VelocityConstants.Class)), "incorrect resource loader type"); + Assert.AreEqual(new string[]{"Template/Velocity/", "Template/"}, velocityEngine.GetProperty( + TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.File, VelocityConstants.Path)), "incorrect resource loader path"); + Assert.AreEqual(DEFAULT_CACHE_SIZE, velocityEngine.GetProperty(RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE), "incorrect default cache size"); + Assert.AreEqual(DEFAULT_MOD_CHECK, velocityEngine.GetProperty( + VelocityConstants.File + VelocityConstants.Separator + PropertyModificationCheck), "incorrect mod check interval"); + Assert.AreEqual(DEFAULT_CACHE_FLAG, velocityEngine.GetProperty(VelocityConstants.File + VelocityConstants.Separator + PropertyResourceLoaderCachce), + "incorrect caching flag"); + + AssertMergedValue(velocityEngine, "SimpleTemplate.vm"); + } + + /// + /// Test a full aaembly-based configuration + /// + [Test] + public void TestAssemblyBasedConfig() { + VelocityEngine velocityEngine = appContext.GetObject("cnAssemblyVelocityEngine") as VelocityEngine; + Assert.IsNotNull(velocityEngine, "velocity engine is null"); + Assert.AreEqual(VelocityConstants.Assembly, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader"); + Assert.AreEqual(TemplateNamespaceParser.TemplateDefinitionConstants.AssemblyResourceLoaderClass, getSingleProperty(velocityEngine, + TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Class)), "incorrect resource loader type"); + Assert.AreEqual("Spring.Template.Velocity.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), + "incorrect caching flag"); + AssertMergedValue(velocityEngine, "Spring.Template.Velocity.Tests.Template.Velocity.SimpleTemplate.vm"); + } + + /// + /// Test a full aaembly-based configuration + /// + [Test] + public void TestSpringBasedConfig() { + VelocityEngine velocityEngine = appContext.GetObject("cnSpringVelocityEngine") as VelocityEngine; + Assert.IsNotNull(velocityEngine, "velocity engine is null"); + const string PropertySpring = TemplateNamespaceParser.TemplateDefinitionConstants.Spring; + Assert.AreEqual(PropertySpring, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader"); + Assert.AreEqual(TemplateNamespaceParser.TemplateDefinitionConstants.SpringResourceLoaderClass, getSingleProperty(velocityEngine, + TemplateNamespaceParser.getResourceLoaderProperty(PropertySpring, VelocityConstants.Class)), "incorrect resource loader type"); + // no way to test the path property other than trying to actually perform a merge (it is set in velocity engine as an application attribute which is not exposed) + Assert.AreEqual(DEFAULT_CACHE_SIZE, velocityEngine.GetProperty(RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE), "incorrect default cache size"); + Assert.AreEqual(DEFAULT_CACHE_FLAG, velocityEngine.GetProperty(PropertySpring + VelocityConstants.Separator + PropertyResourceLoaderCachce), + "incorrect caching flag"); + + AssertMergedValue(velocityEngine, "SimpleTemplate.vm"); + AssertMergedValue(velocityEngine, "EmbeddedTemplate.vm"); + } + + /// + /// Test using an external configuration properties definition + /// + [Test] + public void TestGlobalConfig() { + VelocityEngine velocityEngine = appContext.GetObject("cnVelocityEngineConfig") as VelocityEngine; + Assert.IsNotNull(velocityEngine, "velocity engine is null"); + + string classProp = TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Class); + string descProp = TemplateNamespaceParser.getResourceLoaderProperty(VelocityConstants.Assembly, VelocityConstants.Description); + + Assert.AreEqual(VelocityConstants.Assembly, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader"); + Assert.AreEqual("NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader", + getSingleProperty(velocityEngine,classProp), "incorrect resource loader type"); + Assert.AreEqual("TestDescription", getSingleProperty(velocityEngine, descProp), "incorrect description"); + } + + /// + /// Test a custom resource loader definition + /// + [Test] + public void TestCustomResourceLoader() { + VelocityEngine velocityEngine = appContext.GetObject("cnVelocityEngingCustomResourceLoader") as VelocityEngine; + Assert.IsNotNull(velocityEngine, "velocity engine is null"); + const string PropertyMyResourceLoader = "myResourceLoader"; + string classProp = TemplateNamespaceParser.getResourceLoaderProperty(PropertyMyResourceLoader, VelocityConstants.Class); + string descProp = TemplateNamespaceParser.getResourceLoaderProperty(PropertyMyResourceLoader, VelocityConstants.Description); + + Assert.AreEqual(PropertyMyResourceLoader, getSingleProperty(velocityEngine, RuntimeConstants.RESOURCE_LOADER), "incorrect resource loader"); + + Assert.AreEqual("Spring.Template.Velocity.Tests.Template.Velocity.Config.TestCustomResourceLoader; Spring.Template.Velocity.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", + getSingleProperty(velocityEngine, descProp), "incorrect resource loader description"); + Assert.AreEqual("Template/Velocity/", getSingleProperty(velocityEngine, + TemplateNamespaceParser.getResourceLoaderProperty(PropertyMyResourceLoader, VelocityConstants.Path)), "incorrect resource loader path"); + + AssertMergedValue(velocityEngine, "Template/Velocity/SimpleTemplate.vm"); + } + + #region internal test methods + /// + /// Grab a single property from (if it's an array return the first value) from the velocityEngine + /// + private string getSingleProperty(VelocityEngine velocityEngine, string prop) { + object property = velocityEngine.GetProperty(prop); + if (property is ArrayList) { + ArrayList list = (ArrayList)property; + return (string)list[0]; + } + return (string)property; + } + #endregion + } + + #region test classes + /// + /// Test class for a custom resource loader class + /// + internal sealed class TestCustomResourceLoader : ResourceLoader { + public override void Init(ExtendedProperties configuration) { + } + + public override Stream GetResourceStream(string source) { + return new ConfigurableResourceLoader().GetResource(source).InputStream; + } + + public override bool IsSourceModified(Resource resource) { + return false; + } + + public override long GetLastModified(Resource resource) { + return resource.LastModified; + } + } + #endregion +} \ No newline at end of file diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/EmbeddedTemplate.vm b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/EmbeddedTemplate.vm new file mode 100644 index 00000000..07da26e3 --- /dev/null +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/EmbeddedTemplate.vm @@ -0,0 +1 @@ +value=${var1} \ No newline at end of file diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.cs b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.cs index 2c8113ab..9dc9f54c 100644 --- a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.cs +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.cs @@ -21,42 +21,20 @@ #region Imports using System; -using System.Collections; -using System.Text; using NUnit.Framework; using NVelocity.App; -using Spring.Context.Support; -using Spring.Objects.Factory.Xml; #endregion namespace Spring.Template.Velocity.Tests.Template.Velocity { + /// /// This class contains tests for VelocityEngineFactoryObject /// /// Mark Pollack /// Erez Mazor [TestFixture] - public class VelocityEngineFactoryObjectTests { - private const string TEST_VALUE = "TEST_VALUE"; - private XmlApplicationContext appContext; - private readonly Hashtable model = new Hashtable(); - - [SetUp] - public void Setup() { - appContext = new XmlApplicationContext(false, - ReadOnlyXmlTestResource.GetFilePath( - "VelocityEngineFactoryObjectTests.xml", - typeof(VelocityEngineFactoryObjectTests))); - model.Add("var1", TEST_VALUE); - } - - [TearDown] - public void TearDown() { - appContext.Dispose(); - model.Clear(); - } - + public class VelocityEngineFactoryObjectTests : VelocityEngineTestBase { /// /// Test the assemblyBasedVelocityEngine bean configuration from VelocityEngineFactoryObjectTests.xml /// @@ -64,9 +42,8 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { public void TestMergeUsingAssembly() { VelocityEngine velocityEngine = appContext.GetObject("assemblyBasedVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "Spring.Template.Velocity.Tests.Template.Velocity.SimpleTemplate.vm", Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", TEST_VALUE), mergedTemplate); - } + AssertMergedValue(velocityEngine, "Spring.Template.Velocity.Tests.Template.Velocity.SimpleTemplate.vm"); + } /// /// Test the fileBasedVelocityEngine bean configuration from VelocityEngineFactoryObjectTests.xml @@ -75,9 +52,7 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { public void TestMergeUsingFile() { VelocityEngine velocityEngine = appContext.GetObject("fileBasedVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString( - velocityEngine, "Template/Velocity/SimpleTemplate.vm", Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", TEST_VALUE), mergedTemplate); + AssertMergedValue(velocityEngine, "Template/Velocity/SimpleTemplate.vm"); } /// @@ -86,11 +61,9 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { [Test] public void TestMergeUsingCustomNamespaceDefinition() { VelocityEngine velocityEngine = - appContext.GetObject("customNamespaceVelocityTemplate") as VelocityEngine; + appContext.GetObject("cnFileVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "SimpleTemplate.vm", - Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", "TEST_VALUE"), mergedTemplate); + AssertMergedValue(velocityEngine, "SimpleTemplate.vm"); } /// @@ -101,9 +74,7 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { VelocityEngine velocityEngine = appContext.GetObject("pathBasedVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "SimpleTemplate.vm", - Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", "TEST_VALUE"), mergedTemplate); + AssertMergedValue(velocityEngine, "SimpleTemplate.vm"); } /// @@ -114,10 +85,7 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { VelocityEngine velocityEngine = appContext.GetObject("propertiesFileBasedVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, - "Spring.Template.Velocity.Tests.Template.Velocity.SimpleTemplate.vm", - Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", "TEST_VALUE"), mergedTemplate); + AssertMergedValue(velocityEngine, "Spring.Template.Velocity.Tests.Template.Velocity.SimpleTemplate.vm"); } /// @@ -128,9 +96,7 @@ namespace Spring.Template.Velocity.Tests.Template.Velocity { VelocityEngine velocityEngine = appContext.GetObject("springResourceLoaderBasedVelocityEngine") as VelocityEngine; Assert.IsNotNull(velocityEngine, "velocityEngine is null"); - string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "SimpleTemplate.vm", - Encoding.UTF8.WebName, model); - Assert.AreEqual(string.Format("value={0}", "TEST_VALUE"), mergedTemplate); + AssertMergedValue(velocityEngine, "SimpleTemplate.vm"); } /// diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.xml b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.xml index 2e17a5fa..567bb04d 100644 --- a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.xml +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineFactoryObjectTests.xml @@ -1,12 +1,37 @@  - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineTestBase.cs b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineTestBase.cs new file mode 100644 index 00000000..70ebc1b8 --- /dev/null +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/VelocityEngineTestBase.cs @@ -0,0 +1,68 @@ +#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 + +#region Imports + +using System.Collections; +using System.Text; +using NUnit.Framework; +using NVelocity.App; +using Spring.Context.Support; +using Spring.Objects.Factory.Xml; + +#endregion + +namespace Spring.Template.Velocity.Tests.Template.Velocity { + public class VelocityEngineTestBase { + protected XmlApplicationContext appContext; + protected readonly Hashtable model = new Hashtable(); + protected const string TEST_VALUE = "TEST_VALUE"; + + #region setup + [SetUp] + public void Setup() { + appContext = new XmlApplicationContext(false, + ReadOnlyXmlTestResource.GetFilePath( + "VelocityEngineFactoryObjectTests.xml", + typeof(VelocityEngineFactoryObjectTests))); + model.Add("var1", TEST_VALUE); + } + #endregion + + #region teardown + [TearDown] + public void TearDown() { + appContext.Dispose(); + model.Clear(); + } + #endregion + + #region base helper methods + /// + /// Basic method for asserting the expected TEST_VALUE in the merged template + /// + protected void AssertMergedValue(VelocityEngine velocityEngine, string template){ + string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, template, Encoding.UTF8.WebName, model); + Assert.AreEqual(string.Format("value={0}", TEST_VALUE), mergedTemplate); + } + #endregion + } + +} diff --git a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/config.properties b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/config.properties index 61944bd9..0da852c0 100644 --- a/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/config.properties +++ b/test/Spring/Spring.Template.Velocity.Tests/Template/Velocity/config.properties @@ -1,3 +1,4 @@ resource.loader=assembly assembly.resource.loader.class=NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader -assembly.resource.loader.assembly=Spring.Template.Velocity.Tests \ No newline at end of file +assembly.resource.loader.assembly=Spring.Template.Velocity.Tests +assembly.resource.loader.description=TestDescription \ No newline at end of file