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