View Javadoc

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 }