1 package org.apache.velocity.app;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.Reader;
27 import java.io.UnsupportedEncodingException;
28 import java.io.Writer;
29 import java.util.Properties;
30
31 import org.apache.commons.collections.ExtendedProperties;
32 import org.apache.velocity.Template;
33 import org.apache.velocity.context.Context;
34 import org.apache.velocity.exception.MethodInvocationException;
35 import org.apache.velocity.exception.ParseErrorException;
36 import org.apache.velocity.exception.ResourceNotFoundException;
37 import org.apache.velocity.exception.VelocityException;
38 import org.apache.velocity.runtime.RuntimeConstants;
39 import org.apache.velocity.runtime.RuntimeSingleton;
40 import org.apache.velocity.runtime.log.Log;
41
42 /**
43 * This class provides services to the application
44 * developer, such as :
45 * <ul>
46 * <li> Simple Velocity Runtime engine initialization methods.
47 * <li> Functions to apply the template engine to streams and strings
48 * to allow embedding and dynamic template generation.
49 * <li> Methods to access Velocimacros directly.
50 * </ul>
51 *
52 * <br><br>
53 * While the most common way to use Velocity is via templates, as
54 * Velocity is a general-purpose template engine, there are other
55 * uses that Velocity is well suited for, such as processing dynamically
56 * created templates, or processing content streams.
57 *
58 * <br><br>
59 * The methods herein were developed to allow easy access to the Velocity
60 * facilities without direct spelunking of the internals. If there is
61 * something you feel is necessary to add here, please, send a patch.
62 *
63 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
64 * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph Reck</a>
65 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
66 * @version $Id: Velocity.java 687177 2008-08-19 22:00:32Z nbubna $
67 */
68 public class Velocity implements RuntimeConstants
69 {
70 /**
71 * initialize the Velocity runtime engine, using the default
72 * properties of the Velocity distribution
73 *
74 * @throws Exception When an error during initialization occurs.
75 */
76 public static void init()
77 throws Exception
78 {
79 RuntimeSingleton.init();
80 }
81
82 /**
83 * initialize the Velocity runtime engine, using default properties
84 * plus the properties in the properties file passed in as the arg
85 *
86 * @param propsFilename file containing properties to use to initialize
87 * the Velocity runtime
88 * @throws Exception When an error during initialization occurs.
89 */
90 public static void init( String propsFilename )
91 throws Exception
92 {
93 RuntimeSingleton.init(propsFilename);
94 }
95
96 /**
97 * initialize the Velocity runtime engine, using default properties
98 * plus the properties in the passed in java.util.Properties object
99 *
100 * @param p Properties object containing initialization properties
101 * @throws Exception When an error during initialization occurs.
102 *
103 */
104 public static void init( Properties p )
105 throws Exception
106 {
107 RuntimeSingleton.init( p );
108 }
109
110 /**
111 * Set a Velocity Runtime property.
112 *
113 * @param key The property key.
114 * @param value The property value.
115 */
116 public static void setProperty(String key, Object value)
117 {
118 RuntimeSingleton.setProperty(key,value);
119 }
120
121 /**
122 * Add a Velocity Runtime property.
123 *
124 * @param key The property key.
125 * @param value The property value.
126 */
127 public static void addProperty(String key, Object value)
128 {
129 RuntimeSingleton.addProperty(key,value);
130 }
131
132 /**
133 * Clear a Velocity Runtime property.
134 *
135 * @param key of property to clear
136 */
137 public static void clearProperty(String key)
138 {
139 RuntimeSingleton.clearProperty(key);
140 }
141
142 /**
143 * Set an entire configuration at once. This is
144 * useful in cases where the parent application uses
145 * the ExtendedProperties class and the velocity configuration
146 * is a subset of the parent application's configuration.
147 *
148 * @param configuration A configuration object.
149 *
150 */
151 public static void setExtendedProperties( ExtendedProperties configuration)
152 {
153 RuntimeSingleton.setConfiguration( configuration );
154 }
155
156 /**
157 * Get a Velocity Runtime property.
158 *
159 * @param key property to retrieve
160 * @return property value or null if the property
161 * not currently set
162 */
163 public static Object getProperty( String key )
164 {
165 return RuntimeSingleton.getProperty( key );
166 }
167
168 /**
169 * renders the input string using the context into the output writer.
170 * To be used when a template is dynamically constructed, or want to use
171 * Velocity as a token replacer.
172 *
173 * @param context context to use in rendering input string
174 * @param out Writer in which to render the output
175 * @param logTag string to be used as the template name for log
176 * messages in case of error
177 * @param instring input string containing the VTL to be rendered
178 *
179 * @return true if successful, false otherwise. If false, see
180 * Velocity runtime log
181 * @throws ParseErrorException The template could not be parsed.
182 * @throws MethodInvocationException A method on a context object could not be invoked.
183 * @throws ResourceNotFoundException A referenced resource could not be loaded.
184 * @throws IOException While rendering to the writer, an I/O problem occured.
185 */
186 public static boolean evaluate( Context context, Writer out,
187 String logTag, String instring )
188 throws ParseErrorException, MethodInvocationException,
189 ResourceNotFoundException, IOException
190 {
191 return RuntimeSingleton.getRuntimeServices()
192 .evaluate(context, out, logTag, instring);
193 }
194
195 /**
196 * Renders the input stream using the context into the output writer.
197 * To be used when a template is dynamically constructed, or want to
198 * use Velocity as a token replacer.
199 *
200 * @param context context to use in rendering input string
201 * @param writer Writer in which to render the output
202 * @param logTag string to be used as the template name for log messages
203 * in case of error
204 * @param instream input stream containing the VTL to be rendered
205 *
206 * @return true if successful, false otherwise. If false, see
207 * Velocity runtime log
208 * @deprecated Use
209 * {@link #evaluate( Context context, Writer writer,
210 * String logTag, Reader reader ) }
211 * @throws ParseErrorException The template could not be parsed.
212 * @throws MethodInvocationException A method on a context object could not be invoked.
213 * @throws ResourceNotFoundException A referenced resource could not be loaded.
214 * @throws IOException While loading a reference, an I/O problem occured.
215 */
216 public static boolean evaluate( Context context, Writer writer,
217 String logTag, InputStream instream )
218 throws ParseErrorException, MethodInvocationException,
219 ResourceNotFoundException, IOException
220 {
221 /*
222 * first, parse - convert ParseException if thrown
223 */
224 BufferedReader br = null;
225 String encoding = null;
226
227 try
228 {
229 encoding = RuntimeSingleton.getString(INPUT_ENCODING,ENCODING_DEFAULT);
230 br = new BufferedReader( new InputStreamReader( instream, encoding));
231 }
232 catch( UnsupportedEncodingException uce )
233 {
234 String msg = "Unsupported input encoding : " + encoding
235 + " for template " + logTag;
236 throw new ParseErrorException( msg );
237 }
238
239 return evaluate( context, writer, logTag, br );
240 }
241
242 /**
243 * Renders the input reader using the context into the output writer.
244 * To be used when a template is dynamically constructed, or want to
245 * use Velocity as a token replacer.
246 *
247 * @param context context to use in rendering input string
248 * @param writer Writer in which to render the output
249 * @param logTag string to be used as the template name for log messages
250 * in case of error
251 * @param reader Reader containing the VTL to be rendered
252 *
253 * @return true if successful, false otherwise. If false, see
254 * Velocity runtime log
255 * @throws ParseErrorException The template could not be parsed.
256 * @throws MethodInvocationException A method on a context object could not be invoked.
257 * @throws ResourceNotFoundException A referenced resource could not be loaded.
258 * @throws IOException While reading from the reader or rendering to the writer,
259 * an I/O problem occured.
260 * @since Velocity v1.1
261 */
262 public static boolean evaluate( Context context, Writer writer,
263 String logTag, Reader reader )
264 throws ParseErrorException, MethodInvocationException,
265 ResourceNotFoundException,IOException
266 {
267 return RuntimeSingleton.getRuntimeServices().evaluate(context, writer,
268 logTag, reader);
269 }
270
271 /**
272 * Invokes a currently registered Velocimacro with the params provided
273 * and places the rendered stream into the writer.
274 * <br>
275 * Note : currently only accepts args to the VM if they are in the context.
276 *
277 * @param vmName name of Velocimacro to call
278 * @param logTag string to be used for template name in case of error. if null,
279 * the vmName will be used
280 * @param params keys for args used to invoke Velocimacro, in java format
281 * rather than VTL (eg "foo" or "bar" rather than "$foo" or "$bar")
282 * @param context Context object containing data/objects used for rendering.
283 * @param writer Writer for output stream
284 * @return true if Velocimacro exists and successfully invoked, false otherwise.
285 */
286 public static boolean invokeVelocimacro( String vmName, String logTag,
287 String params[], Context context,
288 Writer writer )
289 {
290 try
291 {
292 return RuntimeSingleton.getRuntimeServices()
293 .invokeVelocimacro(vmName, logTag, params, context, writer);
294 }
295 catch (IOException ioe)
296 {
297 String msg = "Velocity.invokeVelocimacro("+vmName+") failed";
298 getLog().error(msg, ioe);
299 throw new VelocityException(msg, ioe);
300 }
301 }
302
303 /**
304 * Merges a template and puts the rendered stream into the writer.
305 * The default encoding that Velocity uses to read template files is defined in
306 * the property input.encoding and defaults to ISO-8859-1.
307 *
308 * @param templateName name of template to be used in merge
309 * @param context filled context to be used in merge
310 * @param writer writer to write template into
311 *
312 * @return true if successful, false otherwise. Errors
313 * logged to velocity log.
314 * @deprecated Use
315 * {@link #mergeTemplate( String templateName, String encoding,
316 * Context context, Writer writer )}
317 * @throws ParseErrorException The template could not be parsed.
318 * @throws MethodInvocationException A method on a context object could not be invoked.
319 * @throws ResourceNotFoundException A referenced resource could not be loaded.
320 * @throws Exception Any other exception.
321 */
322 public static boolean mergeTemplate( String templateName,
323 Context context, Writer writer )
324 throws ResourceNotFoundException, ParseErrorException, MethodInvocationException, Exception
325 {
326 return mergeTemplate( templateName, RuntimeSingleton.getString(INPUT_ENCODING,ENCODING_DEFAULT),
327 context, writer );
328 }
329
330 /**
331 * merges a template and puts the rendered stream into the writer
332 *
333 * @param templateName name of template to be used in merge
334 * @param encoding encoding used in template
335 * @param context filled context to be used in merge
336 * @param writer writer to write template into
337 *
338 * @return true if successful, false otherwise. Errors
339 * logged to velocity log
340 *
341 * @throws ParseErrorException The template could not be parsed.
342 * @throws MethodInvocationException A method on a context object could not be invoked.
343 * @throws ResourceNotFoundException A referenced resource could not be loaded.
344 * @throws Exception Any other exception.
345 *
346 * @since Velocity v1.1
347 */
348 public static boolean mergeTemplate( String templateName, String encoding,
349 Context context, Writer writer )
350 throws ResourceNotFoundException, ParseErrorException, MethodInvocationException, Exception
351 {
352 Template template = RuntimeSingleton.getTemplate(templateName, encoding);
353
354 if ( template == null )
355 {
356 String msg = "Velocity.mergeTemplate() was unable to load template '"
357 + templateName + "'";
358 getLog().error(msg);
359 throw new ResourceNotFoundException(msg);
360 }
361 else
362 {
363 template.merge(context, writer);
364 return true;
365 }
366 }
367
368 /**
369 * Returns a <code>Template</code> from the Velocity
370 * resource management system.
371 *
372 * @param name The file name of the desired template.
373 * @return The template.
374 * @throws ResourceNotFoundException if template not found
375 * from any available source.
376 * @throws ParseErrorException if template cannot be parsed due
377 * to syntax (or other) error.
378 * @throws Exception if an error occurs in template initialization
379 */
380 public static Template getTemplate(String name)
381 throws ResourceNotFoundException, ParseErrorException, Exception
382 {
383 return RuntimeSingleton.getTemplate( name );
384 }
385
386 /**
387 * Returns a <code>Template</code> from the Velocity
388 * resource management system.
389 *
390 * @param name The file name of the desired template.
391 * @param encoding The character encoding to use for the template.
392 * @return The template.
393 * @throws ResourceNotFoundException if template not found
394 * from any available source.
395 * @throws ParseErrorException if template cannot be parsed due
396 * to syntax (or other) error.
397 * @throws Exception if an error occurs in template initialization
398 *
399 * @since Velocity v1.1
400 */
401 public static Template getTemplate(String name, String encoding)
402 throws ResourceNotFoundException, ParseErrorException, Exception
403 {
404 return RuntimeSingleton.getTemplate( name, encoding );
405 }
406
407 /**
408 * <p>Determines whether a resource is accessable via the
409 * currently configured resource loaders. {@link
410 * org.apache.velocity.runtime.resource.Resource} is the generic
411 * description of templates, static content, etc.</p>
412 *
413 * <p>Note that the current implementation will <b>not</b> change
414 * the state of the system in any real way - so this cannot be
415 * used to pre-load the resource cache, as the previous
416 * implementation did as a side-effect.</p>
417 *
418 * @param resourceName The name of the resource to search for.
419 * @return Whether the resource was located.
420 */
421 public static boolean resourceExists(String resourceName)
422 {
423 return (RuntimeSingleton.getLoaderNameForResource(resourceName) != null);
424 }
425
426 /**
427 * Returns a convenient Log instance that wraps the current LogChute.
428 * Use this to log error messages. It has the usual methods.
429 *
430 * @return A convenience Log instance that wraps the current LogChute.
431 * @since 1.5
432 */
433 public static Log getLog()
434 {
435 return RuntimeSingleton.getLog();
436 }
437
438 /**
439 * @deprecated Use getLog() and call warn() on it.
440 * @see Log#warn(Object)
441 * @param message The message to log.
442 */
443 public static void warn(Object message)
444 {
445 getLog().warn( message );
446 }
447
448 /**
449 * @deprecated Use getLog() and call info() on it.
450 * @see Log#info(Object)
451 * @param message The message to log.
452 */
453 public static void info(Object message)
454 {
455 getLog().info( message );
456 }
457
458 /**
459 * @deprecated Use getLog() and call error() on it.
460 * @see Log#error(Object)
461 * @param message The message to log.
462 */
463 public static void error(Object message)
464 {
465 getLog().error( message );
466 }
467
468 /**
469 * @deprecated Use getLog() and call debug() on it.
470 * @see Log#debug(Object)
471 * @param message The message to log.
472 */
473 public static void debug(Object message)
474 {
475 getLog().debug( message );
476 }
477
478 /**
479 * <p>
480 * Set the an ApplicationAttribue, which is an Object
481 * set by the application which is accessable from
482 * any component of the system that gets a RuntimeServices.
483 * This allows communication between the application
484 * environment and custom pluggable components of the
485 * Velocity engine, such as loaders and loggers.
486 * </p>
487 *
488 * <p>
489 * Note that there is no enfocement or rules for the key
490 * used - it is up to the application developer. However, to
491 * help make the intermixing of components possible, using
492 * the target Class name (e.g. com.foo.bar ) as the key
493 * might help avoid collision.
494 * </p>
495 *
496 * @param key object 'name' under which the object is stored
497 * @param value object to store under this key
498 */
499 public static void setApplicationAttribute( Object key, Object value )
500 {
501 RuntimeSingleton.getRuntimeInstance().setApplicationAttribute( key, value);
502 }
503
504 /**
505 * @param resourceName Name of the Template to check.
506 * @return True if the template exists.
507 * @see #resourceExists(String)
508 * @deprecated Use resourceExists(String) instead.
509 */
510 public static boolean templateExists(String resourceName)
511 {
512 return resourceExists(resourceName);
513 }
514 }