1 package org.apache.velocity.runtime; 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.Reader; 23 import java.util.Properties; 24 25 import org.apache.commons.collections.ExtendedProperties; 26 import org.apache.velocity.Template; 27 import org.apache.velocity.app.event.EventCartridge; 28 import org.apache.velocity.exception.ParseErrorException; 29 import org.apache.velocity.exception.ResourceNotFoundException; 30 import org.apache.velocity.runtime.directive.Directive; 31 import org.apache.velocity.runtime.log.Log; 32 import org.apache.velocity.runtime.parser.ParseException; 33 import org.apache.velocity.runtime.parser.node.Node; 34 import org.apache.velocity.runtime.parser.node.SimpleNode; 35 import org.apache.velocity.runtime.resource.ContentResource; 36 import org.apache.velocity.util.introspection.Introspector; 37 import org.apache.velocity.util.introspection.Uberspect; 38 39 /** 40 * This is the Runtime system for Velocity. It is the 41 * single access point for all functionality in Velocity. 42 * It adheres to the mediator pattern and is the only 43 * structure that developers need to be familiar with 44 * in order to get Velocity to perform. 45 * 46 * The Runtime will also cooperate with external 47 * systems like Turbine. Runtime properties can 48 * set and then the Runtime is initialized. 49 * 50 * Turbine for example knows where the templates 51 * are to be loaded from, and where the velocity 52 * log file should be placed. 53 * 54 * So in the case of Velocity cooperating with Turbine 55 * the code might look something like the following: 56 * 57 * <pre> 58 * RuntimeSingleton.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templatePath); 59 * RuntimeSingleton.setProperty(RuntimeConstants.RUNTIME_LOG, pathToVelocityLog); 60 * RuntimeSingleton.init(); 61 * </pre> 62 * 63 * <pre> 64 * ----------------------------------------------------------------------- 65 * N O T E S O N R U N T I M E I N I T I A L I Z A T I O N 66 * ----------------------------------------------------------------------- 67 * RuntimeSingleton.init() 68 * 69 * If Runtime.init() is called by itself the Runtime will 70 * initialize with a set of default values. 71 * ----------------------------------------------------------------------- 72 * RuntimeSingleton.init(String/Properties) 73 * 74 * In this case the default velocity properties are layed down 75 * first to provide a solid base, then any properties provided 76 * in the given properties object will override the corresponding 77 * default property. 78 * ----------------------------------------------------------------------- 79 * </pre> 80 * 81 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 82 * @author <a href="mailto:jlb@houseofdistraction.com">Jeff Bowden</a> 83 * @author <a href="mailto:geirm@optonline.net">Geir Magusson Jr.</a> 84 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 85 * 86 * @see org.apache.velocity.runtime.RuntimeInstance 87 * 88 * @version $Id: RuntimeSingleton.java 685724 2008-08-13 23:12:12Z nbubna $ 89 */ 90 public class RuntimeSingleton implements RuntimeConstants 91 { 92 private static RuntimeInstance ri = new RuntimeInstance(); 93 94 /** 95 * This is the primary initialization method in the Velocity 96 * Runtime. The systems that are setup/initialized here are 97 * as follows: 98 * 99 * <ul> 100 * <li>Logging System</li> 101 * <li>ResourceManager</li> 102 * <li>Event Handlers</li> 103 * <li>Parser Pool</li> 104 * <li>Global Cache</li> 105 * <li>Static Content Include System</li> 106 * <li>Velocimacro System</li> 107 * </ul> 108 * @throws Exception When an error occured during initialization. 109 * @see RuntimeInstance#init() 110 */ 111 public synchronized static void init() 112 throws Exception 113 { 114 ri.init(); 115 } 116 117 /** 118 * Returns true if the RuntimeInstance has been successfully initialized. 119 * @return True if the RuntimeInstance has been successfully initialized. 120 * @see RuntimeInstance#isInitialized() 121 * @since 1.5 122 */ 123 public static boolean isInitialized() 124 { 125 return ri.isInitialized(); 126 } 127 128 /** 129 * Returns the RuntimeServices Instance used by this wrapper. 130 * 131 * @return The RuntimeServices Instance used by this wrapper. 132 */ 133 public static RuntimeServices getRuntimeServices() 134 { 135 return ri; 136 } 137 138 139 /** 140 * Allows an external system to set a property in 141 * the Velocity Runtime. 142 * 143 * @param key property key 144 * @param value property value 145 * @see RuntimeInstance#setProperty(String, Object) 146 */ 147 public static void setProperty(String key, Object value) 148 { 149 ri.setProperty( key, value ); 150 } 151 152 /** 153 * Allow an external system to set an ExtendedProperties 154 * object to use. This is useful where the external 155 * system also uses the ExtendedProperties class and 156 * the velocity configuration is a subset of 157 * parent application's configuration. This is 158 * the case with Turbine. 159 * 160 * @param configuration 161 * @see RuntimeInstance#setConfiguration(ExtendedProperties) 162 */ 163 public static void setConfiguration( ExtendedProperties configuration) 164 { 165 ri.setConfiguration( configuration ); 166 } 167 168 /** 169 * Add a property to the configuration. If it already 170 * exists then the value stated here will be added 171 * to the configuration entry. For example, if 172 * 173 * resource.loader = file 174 * 175 * is already present in the configuration and you 176 * 177 * addProperty("resource.loader", "classpath") 178 * 179 * Then you will end up with a Vector like the 180 * following: 181 * 182 * ["file", "classpath"] 183 * 184 * @param key 185 * @param value 186 * @see RuntimeInstance#addProperty(String, Object) 187 */ 188 public static void addProperty(String key, Object value) 189 { 190 ri.addProperty( key, value ); 191 } 192 193 /** 194 * Clear the values pertaining to a particular 195 * property. 196 * 197 * @param key of property to clear 198 * @see RuntimeInstance#clearProperty(String) 199 */ 200 public static void clearProperty(String key) 201 { 202 ri.clearProperty( key ); 203 } 204 205 /** 206 * Allows an external caller to get a property. The calling 207 * routine is required to know the type, as this routine 208 * will return an Object, as that is what properties can be. 209 * 210 * @param key property to return 211 * @return Value of the property or null if it does not exist. 212 * @see RuntimeInstance#getProperty(String) 213 */ 214 public static Object getProperty( String key ) 215 { 216 return ri.getProperty( key ); 217 } 218 219 /** 220 * Initialize the Velocity Runtime with a Properties 221 * object. 222 * 223 * @param p 224 * @throws Exception When an error occurs during initialization. 225 * @see RuntimeInstance#init(Properties) 226 */ 227 public static void init(Properties p) throws Exception 228 { 229 ri.init(p); 230 } 231 232 /** 233 * Initialize the Velocity Runtime with the name of 234 * ExtendedProperties object. 235 * 236 * @param configurationFile 237 * @throws Exception When an error occurs during initialization. 238 * @see RuntimeInstance#init(String) 239 */ 240 public static void init(String configurationFile) 241 throws Exception 242 { 243 ri.init( configurationFile ); 244 } 245 246 /** 247 * Parse the input and return the root of 248 * AST node structure. 249 * <br><br> 250 * In the event that it runs out of parsers in the 251 * pool, it will create and let them be GC'd 252 * dynamically, logging that it has to do that. This 253 * is considered an exceptional condition. It is 254 * expected that the user will set the 255 * PARSER_POOL_SIZE property appropriately for their 256 * application. We will revisit this. 257 * 258 * @param reader Reader retrieved by a resource loader 259 * @param templateName name of the template being parsed 260 * @return A root node representing the template as an AST tree. 261 * @throws ParseException When the template could not be parsed. 262 * @see RuntimeInstance#parse(Reader, String) 263 */ 264 public static SimpleNode parse( Reader reader, String templateName ) 265 throws ParseException 266 { 267 return ri.parse( reader, templateName ); 268 } 269 270 /** 271 * Parse the input and return the root of the AST node structure. 272 * 273 * @param reader Reader retrieved by a resource loader 274 * @param templateName name of the template being parsed 275 * @param dumpNamespace flag to dump the Velocimacro namespace for this template 276 * @return A root node representing the template as an AST tree. 277 * @throws ParseException When the template could not be parsed. 278 * @see RuntimeInstance#parse(Reader, String, boolean) 279 */ 280 public static SimpleNode parse( Reader reader, String templateName, boolean dumpNamespace ) 281 throws ParseException 282 { 283 return ri.parse( reader, templateName, dumpNamespace ); 284 } 285 286 287 /** 288 * Returns a <code>Template</code> from the resource manager. 289 * This method assumes that the character encoding of the 290 * template is set by the <code>input.encoding</code> 291 * property. The default is "ISO-8859-1" 292 * 293 * @param name The file name of the desired template. 294 * @return The template. 295 * @throws ResourceNotFoundException if template not found 296 * from any available source. 297 * @throws ParseErrorException if template cannot be parsed due 298 * to syntax (or other) error. 299 * @throws Exception if an error occurs in template initialization 300 * @see RuntimeInstance#getTemplate(String) 301 */ 302 public static Template getTemplate(String name) 303 throws ResourceNotFoundException, ParseErrorException, Exception 304 { 305 return ri.getTemplate( name ); 306 } 307 308 /** 309 * Returns a <code>Template</code> from the resource manager 310 * 311 * @param name The name of the desired template. 312 * @param encoding Character encoding of the template 313 * @return The template. 314 * @throws ResourceNotFoundException if template not found 315 * from any available source. 316 * @throws ParseErrorException if template cannot be parsed due 317 * to syntax (or other) error. 318 * @throws Exception if an error occurs in template initialization 319 * @throws ParseErrorException When the template could not be parsed. 320 * @throws Exception Any other error. 321 * @see RuntimeInstance#getTemplate(String, String) 322 */ 323 public static Template getTemplate(String name, String encoding) 324 throws ResourceNotFoundException, ParseErrorException, Exception 325 { 326 return ri.getTemplate( name, encoding ); 327 } 328 329 /** 330 * Returns a static content resource from the 331 * resource manager. Uses the current value 332 * if INPUT_ENCODING as the character encoding. 333 * 334 * @param name Name of content resource to get 335 * @return parsed ContentResource object ready for use 336 * @throws ResourceNotFoundException if template not found 337 * from any available source. 338 * @throws ParseErrorException When the template could not be parsed. 339 * @throws Exception Any other error. 340 * @see RuntimeInstance#getContent(String) 341 */ 342 public static ContentResource getContent(String name) 343 throws ResourceNotFoundException, ParseErrorException, Exception 344 { 345 return ri.getContent( name ); 346 } 347 348 /** 349 * Returns a static content resource from the 350 * resource manager. 351 * 352 * @param name Name of content resource to get 353 * @param encoding Character encoding to use 354 * @return parsed ContentResource object ready for use 355 * @throws ResourceNotFoundException if template not found 356 * from any available source. 357 * @throws ParseErrorException When the template could not be parsed. 358 * @throws Exception Any other error. 359 * @see RuntimeInstance#getContent(String, String) 360 */ 361 public static ContentResource getContent( String name, String encoding ) 362 throws ResourceNotFoundException, ParseErrorException, Exception 363 { 364 return ri.getContent( name, encoding ); 365 } 366 367 368 /** 369 * Determines is a template exists, and returns name of the loader that 370 * provides it. This is a slightly less hokey way to support 371 * the Velocity.templateExists() utility method, which was broken 372 * when per-template encoding was introduced. We can revisit this. 373 * 374 * @param resourceName Name of template or content resource 375 * @return class name of loader than can provide it 376 * @see RuntimeInstance#getLoaderNameForResource(String) 377 */ 378 public static String getLoaderNameForResource( String resourceName ) 379 { 380 return ri.getLoaderNameForResource( resourceName ); 381 } 382 383 384 /** 385 * Returns a convenient Log instance that wraps the current LogChute. 386 * 387 * @return A convenience Log instance that wraps the current LogChute. 388 * @see RuntimeInstance#getLog() 389 * @since 1.5 390 */ 391 public static Log getLog() 392 { 393 return ri.getLog(); 394 } 395 396 /** 397 * @deprecated Use getLog() and call warn() on it. 398 * @see Log#warn(Object) 399 * @param message The message to log. 400 */ 401 public static void warn(Object message) 402 { 403 getLog().warn(message); 404 } 405 406 /** 407 * @deprecated Use getLog() and call info() on it. 408 * @see Log#info(Object) 409 * @param message The message to log. 410 */ 411 public static void info(Object message) 412 { 413 getLog().info(message); 414 } 415 416 /** 417 * @deprecated Use getLog() and call error() on it. 418 * @see Log#error(Object) 419 * @param message The message to log. 420 */ 421 public static void error(Object message) 422 { 423 getLog().error(message); 424 } 425 426 /** 427 * @deprecated Use getLog() and call debug() on it. 428 * @see Log#debug(Object) 429 * @param message The message to log. 430 */ 431 public static void debug(Object message) 432 { 433 getLog().debug(message); 434 } 435 436 /** 437 * String property accessor method with default to hide the 438 * configuration implementation. 439 * 440 * @param key property key 441 * @param defaultValue default value to return if key not 442 * found in resource manager. 443 * @return value of key or default 444 * @see RuntimeInstance#getString(String, String) 445 */ 446 public static String getString( String key, String defaultValue) 447 { 448 return ri.getString( key, defaultValue ); 449 } 450 451 /** 452 * Returns the appropriate VelocimacroProxy object if strVMname 453 * is a valid current Velocimacro. 454 * 455 * @param vmName Name of velocimacro requested 456 * @param templateName Name of the template that contains the velocimacro. 457 * @return The requested VelocimacroProxy. 458 * @see RuntimeInstance#getVelocimacro(String, String) 459 */ 460 public static Directive getVelocimacro( String vmName, String templateName ) 461 { 462 return ri.getVelocimacro( vmName, templateName ); 463 } 464 465 /** 466 * Adds a new Velocimacro. Usually called by Macro only while parsing. 467 * 468 * @param name Name of a new velocimacro. 469 * @param macro root AST node of the parsed macro 470 * @param argArray Array of strings, containing the 471 * #macro() arguments. the 0th argument is the name. 472 * @param sourceTemplate The template from which the macro is requested. 473 * @return boolean True if added, false if rejected for some 474 * reason (either parameters or permission settings) 475 * @see RuntimeInstance#addVelocimacro(String, Node, String[], String) 476 * @since 1.6 477 */ 478 public static boolean addVelocimacro(String name, Node macro, 479 String argArray[], String sourceTemplate) 480 { 481 return ri.addVelocimacro(name, macro, argArray, sourceTemplate); 482 } 483 484 /** 485 * Adds a new Velocimacro. Usually called by Macro only while parsing. 486 * 487 * @param name Name of velocimacro 488 * @param macro String form of macro body 489 * @param argArray Array of strings, containing the 490 * #macro() arguments. the 0th is the name. 491 * @param sourceTemplate Name of the template that contains the velocimacro. 492 * @return True if added, false if rejected for some 493 * reason (either parameters or permission settings) 494 * 495 * @deprecated Use addVelocimacro(String, Node, String[], String) instead 496 * 497 * @see RuntimeInstance#addVelocimacro(String, String, String[], String) 498 */ 499 public static boolean addVelocimacro( String name, 500 String macro, 501 String argArray[], 502 String sourceTemplate ) 503 { 504 return ri.addVelocimacro( name, macro, argArray, sourceTemplate ); 505 } 506 507 /** 508 * Checks to see if a VM exists 509 * 510 * @param vmName Name of the Velocimacro. 511 * @param templateName Template on which to look for the Macro. 512 * @return True if VM by that name exists, false if not 513 * @see RuntimeInstance#isVelocimacro(String, String) 514 */ 515 public static boolean isVelocimacro( String vmName, String templateName ) 516 { 517 return ri.isVelocimacro( vmName, templateName ); 518 } 519 520 /** 521 * tells the vmFactory to dump the specified namespace. This is to support 522 * clearing the VM list when in inline-VM-local-scope mode 523 * @param namespace Namespace to dump. 524 * @return True if namespace was dumped successfully. 525 * @see RuntimeInstance#dumpVMNamespace(String) 526 */ 527 public static boolean dumpVMNamespace( String namespace ) 528 { 529 return ri.dumpVMNamespace( namespace ); 530 } 531 532 /* -------------------------------------------------------------------- 533 * R U N T I M E A C C E S S O R M E T H O D S 534 * -------------------------------------------------------------------- 535 * These are the getXXX() methods that are a simple wrapper 536 * around the configuration object. This is an attempt 537 * to make a the Velocity Runtime the single access point 538 * for all things Velocity, and allow the Runtime to 539 * adhere as closely as possible the the Mediator pattern 540 * which is the ultimate goal. 541 * -------------------------------------------------------------------- 542 */ 543 544 /** 545 * String property accessor method to hide the configuration implementation 546 * @param key property key 547 * @return value of key or null 548 * @see RuntimeInstance#getString(String) 549 */ 550 public static String getString(String key) 551 { 552 return ri.getString( key ); 553 } 554 555 /** 556 * Int property accessor method to hide the configuration implementation. 557 * 558 * @param key Property key 559 * @return value 560 * @see RuntimeInstance#getInt(String) 561 */ 562 public static int getInt( String key ) 563 { 564 return ri.getInt( key ); 565 } 566 567 /** 568 * Int property accessor method to hide the configuration implementation. 569 * 570 * @param key property key 571 * @param defaultValue The default value. 572 * @return value 573 * @see RuntimeInstance#getInt(String, int) 574 */ 575 public static int getInt( String key, int defaultValue ) 576 { 577 return ri.getInt( key, defaultValue ); 578 } 579 580 /** 581 * Boolean property accessor method to hide the configuration implementation. 582 * 583 * @param key property key 584 * @param def The default value if property not found. 585 * @return value of key or default value 586 * @see RuntimeInstance#getBoolean(String, boolean) 587 */ 588 public static boolean getBoolean( String key, boolean def ) 589 { 590 return ri.getBoolean( key, def ); 591 } 592 593 /** 594 * Return the velocity runtime configuration object. 595 * 596 * @return ExtendedProperties configuration object which houses 597 * the velocity runtime properties. 598 * @see RuntimeInstance#getConfiguration() 599 */ 600 public static ExtendedProperties getConfiguration() 601 { 602 return ri.getConfiguration(); 603 } 604 605 /** 606 * Return the Introspector for this RuntimeInstance 607 * 608 * @return Introspector object for this runtime instance 609 * @see RuntimeInstance#getIntrospector() 610 */ 611 public static Introspector getIntrospector() 612 { 613 return ri.getIntrospector(); 614 } 615 616 /** 617 * Returns the event handlers for the application. 618 * @return The event handlers for the application. 619 * @see RuntimeInstance#getApplicationEventCartridge() 620 * @since 1.5 621 */ 622 public EventCartridge getEventCartridge() 623 { 624 return ri.getApplicationEventCartridge(); 625 } 626 627 /** 628 * Gets the application attribute for the given key 629 * 630 * @see org.apache.velocity.runtime.RuntimeServices#getApplicationAttribute(Object) 631 * @param key 632 * @return The application attribute for the given key. 633 * @see RuntimeInstance#getApplicationAttribute(Object) 634 */ 635 public static Object getApplicationAttribute(Object key) 636 { 637 return ri.getApplicationAttribute(key); 638 } 639 640 /** 641 * Returns the Uberspect object for this Instance. 642 * 643 * @return The Uberspect object for this Instance. 644 * @see org.apache.velocity.runtime.RuntimeServices#getUberspect() 645 * @see RuntimeInstance#getUberspect() 646 */ 647 public static Uberspect getUberspect() 648 { 649 return ri.getUberspect(); 650 } 651 652 /** 653 * @deprecated Use getRuntimeServices() instead. 654 * @return The RuntimeInstance used by this Singleton. 655 */ 656 public static RuntimeInstance getRuntimeInstance() 657 { 658 return ri; 659 } 660 }