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 }