1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.Components
.Common
.TemplateEngine
.NVelocityTemplateEngine
18 using System
.Collections
;
19 using System
.ComponentModel
;
23 using Castle
.Components
.Common
.TemplateEngine
;
24 using Castle
.Core
.Logging
;
26 using Commons
.Collections
;
30 using NVelocity
.Context
;
31 using NVelocity
.Runtime
;
34 /// Implementation of <see cref="ITemplateEngine"/>
35 /// that uses NVelocity
37 public class NVelocityTemplateEngine
: ITemplateEngine
, ISupportInitialize
39 private VelocityEngine vengine
;
40 private ILogger log
= NullLogger
.Instance
;
42 private ArrayList assemblies
= new ArrayList();
43 private String templateDir
= ".";
44 private bool enableCache
= true;
47 /// Constructs a NVelocityTemplateEngine instance
48 /// assuming the default values
50 public NVelocityTemplateEngine()
55 /// Constructs a NVelocityTemplateEngine instance
56 /// specifing the template directory
58 /// <param name="templateDir"></param>
59 public NVelocityTemplateEngine(String templateDir
)
61 this.TemplateDir
= templateDir
;
65 /// Gets or sets the assembly name. This
66 /// forces NVelocityTemplateEngine to use an assembly resource loader
67 /// instead of File resource loader (which is the default)
70 /// The property is obsolete, please use the AddResourceAssembly function.
72 [Obsolete("Please use the AddResourceAssembly function")]
73 public string AssemblyName
;
76 /// Add an assembly to the resource collection.
78 /// <param name="assembly"></param>
79 public void AddResourceAssembly(string assembly
)
81 if (assembly
== null || assembly
== string.Empty
)
82 throw new ArgumentException("assembly name can not be null or empty");
84 if (assemblies
.Contains(assembly
))
88 assemblies
.Add(assembly
);
92 /// Gets or sets the template directory
94 public string TemplateDir
96 get { return templateDir; }
100 throw new InvalidOperationException("Could not change the TemplateDir after Template Engine initialization.");
107 /// Enable/Disable caching. Default is <c>true</c>
109 public bool EnableCache
111 get { return enableCache; }
112 set { enableCache = value; }
122 /// Starts/configure NVelocity based on the properties.
124 public void BeginInit()
126 vengine
= new VelocityEngine();
128 ExtendedProperties props
= new ExtendedProperties();
130 if (assemblies
.Count
!= 0)
132 log
.Info("Initializing NVelocityTemplateEngine component using Assemblies:");
133 foreach(string s
in assemblies
)
135 log
.Info(" - {0}", s
);
138 props
.SetProperty(RuntimeConstants
.RESOURCE_LOADER
, "assembly");
139 props
.SetProperty("assembly.resource.loader.class", "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader;NVelocity");
140 props
.SetProperty("assembly.resource.loader.cache", EnableCache
.ToString().ToLower() );
141 props
.SetProperty("assembly.resource.loader.assembly", assemblies
);
145 String expandedTemplateDir
= ExpandTemplateDir(templateDir
);
146 log
.InfoFormat("Initializing NVelocityTemplateEngine component using template directory: {0}", expandedTemplateDir
);
148 FileInfo propertiesFile
= new FileInfo(Path
.Combine(expandedTemplateDir
, "nvelocity.properties"));
149 if (propertiesFile
.Exists
)
151 log
.Info("Found 'nvelocity.properties' on template dir, loading as base configuration");
152 using(Stream stream
= propertiesFile
.OpenRead())
158 props
.SetProperty(RuntimeConstants
.RESOURCE_LOADER
, "file");
159 props
.SetProperty(RuntimeConstants
.FILE_RESOURCE_LOADER_PATH
, expandedTemplateDir
);
160 props
.SetProperty(RuntimeConstants
.FILE_RESOURCE_LOADER_CACHE
, EnableCache
.ToString().ToLower() );
166 public void EndInit()
171 /// Returns <c>true</c> only if the
172 /// specified template exists and can be used
174 /// <param name="templateName"></param>
175 /// <returns></returns>
176 public bool HasTemplate(String templateName
)
179 throw new InvalidOperationException("Template Engine not yet initialized.");
183 vengine
.GetTemplate(templateName
);
194 /// Process the template with data from the context.
196 public bool Process(IDictionary context
, String templateName
, TextWriter output
)
199 throw new InvalidOperationException("Template Engine not yet initialized.");
201 Template template
= vengine
.GetTemplate(templateName
);
203 template
.Merge(CreateContext(context
), output
);
209 /// Process the input template with data from the context.
211 /// <param name="context">The context.</param>
212 /// <param name="templateName">Name of the template. Used only for information during logging</param>
213 /// <param name="output">The output.</param>
214 /// <param name="inputTemplate">The input template.</param>
215 /// <returns></returns>
216 public bool Process(IDictionary context
, string templateName
, TextWriter output
, string inputTemplate
)
218 return Process(context
, templateName
, output
, new StringReader(inputTemplate
));
222 /// Process the input template with data from the context.
224 /// <param name="context">The context.</param>
225 /// <param name="templateName">Name of the template. Used only for information during logging</param>
226 /// <param name="output">The output.</param>
227 /// <param name="inputTemplate">The input template.</param>
228 /// <returns></returns>
229 public bool Process(IDictionary context
, string templateName
, TextWriter output
, TextReader inputTemplate
)
232 throw new InvalidOperationException("Template Engine not yet initialized.");
234 return vengine
.Evaluate(CreateContext(context
), output
, templateName
, inputTemplate
);
237 private IContext
CreateContext(IDictionary context
)
239 return new VelocityContext( new Hashtable(context
) );
242 private String
ExpandTemplateDir(String templateDir
)
244 log
.DebugFormat("Template directory before expansion: {0}", templateDir
);
246 // if nothing to expand, then exit
247 if (templateDir
== null)
248 templateDir
= String
.Empty
;
250 // expand web application root
251 if (templateDir
.StartsWith("~/"))
253 HttpContext webContext
= HttpContext
.Current
;
254 if (webContext
!= null && webContext
.Request
!= null)
255 templateDir
= webContext
.Server
.MapPath(templateDir
);
258 // normalizes the path (including ".." notation, for parent directories)
259 templateDir
= new DirectoryInfo(templateDir
).FullName
;
261 log
.DebugFormat("Template directory after expansion: {0}", templateDir
);