[prev in list] [next in list] [prev in thread] [next in thread]
List: velocity-dev
Subject: Re: Expanding enviornmental variables in properties files
From: csanders <csanders () hoovers ! com>
Date: 2008-05-06 14:39:28
Message-ID: 48206DA0.5070009 () hoovers ! com
[Download RAW message or body]
Argh, sorry to spam, ignore this patch please - there is something else
that needs updating.
Thanks,
Charlie
csanders wrote:
> And here is the patch :) .
>
> csanders wrote:
> > Attached is a patch for RuntimeInstance.java that adds two methods,
> > private String replaceEnviornmentalVariable(String string) , private
> > void replaceEnviormentalVariables(ExtendedProperties properties) ...
> > and changes initializeProperties and setProperty() to replace them as
> > they come in.
> >
> > Can someone review it and let me know what it needs to be included in
> > Velocity ?
> >
> > Thanks!
> > Charles
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
> > For additional commands, e-mail: dev-help@velocity.apache.org
> >
>
> ------------------------------------------------------------------------
>
> Index: /home/csanders/workspace/Velocity/src/java/org/apache/velocity/runtime/RuntimeInstance.java
> ===================================================================
> --- /home/csanders/workspace/Velocity/src/java/org/apache/velocity/runtime/RuntimeInstance.java (revision \
> 653607)
> +++ /home/csanders/workspace/Velocity/src/java/org/apache/velocity/runtime/RuntimeInstance.java (working \
> copy) @@ -29,6 +29,7 @@
> import java.util.Enumeration;
> import java.util.HashMap;
> import java.util.Hashtable;
> +import java.util.Iterator;
> import java.util.Map;
> import java.util.Properties;
>
> @@ -64,23 +65,15 @@
> import org.apache.velocity.util.introspection.UberspectLoggable;
>
> /**
> - * This is the Runtime system for Velocity. It is the
> - * single access point for all functionality in Velocity.
> - * It adheres to the mediator pattern and is the only
> - * structure that developers need to be familiar with
> - * in order to get Velocity to perform.
> - *
> - * The Runtime will also cooperate with external
> - * systems like Turbine. Runtime properties can
> - * set and then the Runtime is initialized.
> - *
> - * Turbine, for example, knows where the templates
> - * are to be loaded from, and where the Velocity
> - * log file should be placed.
> - *
> - * So in the case of Velocity cooperating with Turbine
> - * the code might look something like the following:
> - *
> + * This is the Runtime system for Velocity. It is the single access point for all \
> functionality in Velocity. It adheres to the mediator pattern and is the only + * \
> structure that developers need to be familiar with in order to get Velocity to \
> perform. + *
> + * The Runtime will also cooperate with external systems like Turbine. Runtime \
> properties can set and then the Runtime is initialized. + *
> + * Turbine, for example, knows where the templates are to be loaded from, and \
> where the Velocity log file should be placed. + *
> + * So in the case of Velocity cooperating with Turbine the code might look \
> something like the following: + *
> * <blockquote><code><pre>
> * ri.setProperty(Runtime.FILE_RESOURCE_LOADER_PATH, templatePath);
> * ri.setProperty(Runtime.RUNTIME_LOG, pathToVelocityLog);
> @@ -86,7 +79,7 @@
> * ri.setProperty(Runtime.RUNTIME_LOG, pathToVelocityLog);
> * ri.init();
> * </pre></code></blockquote>
> - *
> + *
> * <pre>
> * -----------------------------------------------------------------------
> * 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
> @@ -92,7 +85,6 @@
> * 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
> * -----------------------------------------------------------------------
> * init()
> - *
> * If init() is called by itself the RuntimeInstance will initialize
> * with a set of default values.
> * -----------------------------------------------------------------------
> @@ -97,7 +89,6 @@
> * with a set of default values.
> * -----------------------------------------------------------------------
> * init(String/Properties)
> - *
> * In this case the default velocity properties are layed down
> * first to provide a solid base, then any properties provided
> * in the given properties object will override the corresponding
> @@ -104,7 +95,7 @@
> * default property.
> * -----------------------------------------------------------------------
> * </pre>
> - *
> + *
> * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
> * @author <a href="mailto:jlb@houseofdistraction.com">Jeff Bowden</a>
> * @author <a href="mailto:geirm@optonline.net">Geir Magusson Jr.</a>
> @@ -110,1585 +101,1446 @@
> * @author <a href="mailto:geirm@optonline.net">Geir Magusson Jr.</a>
> * @version $Id$
> */
> -public class RuntimeInstance implements RuntimeConstants, RuntimeServices
> -{
> - /**
> - * VelocimacroFactory object to manage VMs
> - */
> - private VelocimacroFactory vmFactory = null;
> +public class RuntimeInstance implements RuntimeConstants, RuntimeServices {
> + /**
> + * VelocimacroFactory object to manage VMs
> + */
> + private VelocimacroFactory vmFactory = null;
>
> - /**
> - * The Runtime logger. We start with an instance of
> - * a 'primordial logger', which just collects log messages
> - * then, when the log system is initialized, all the
> - * messages get dumpted out of the primordial one into the real one.
> - */
> - private Log log = new Log();
> + /**
> + * The Runtime logger. We start with an instance of a 'primordial logger', which \
> just collects log messages then, when the log system is initialized, all + * the \
> messages get dumpted out of the primordial one into the real one. + */
> + private Log log = new Log();
>
> - /**
> - * The Runtime parser pool
> - */
> - private ParserPool parserPool;
> + /**
> + * The Runtime parser pool
> + */
> + private ParserPool parserPool;
>
> - /**
> - * Indicate whether the Runtime is in the midst of initialization.
> - */
> - private boolean initializing = false;
> + /**
> + * Indicate whether the Runtime is in the midst of initialization.
> + */
> + private boolean initializing = false;
>
> - /**
> - * Indicate whether the Runtime has been fully initialized.
> - */
> - private boolean initialized = false;
> + /**
> + * Indicate whether the Runtime has been fully initialized.
> + */
> + private boolean initialized = false;
>
> - /**
> - * These are the properties that are laid down over top
> - * of the default properties when requested.
> - */
> - private ExtendedProperties overridingProperties = null;
> + /**
> + * These are the properties that are laid down over top of the default properties \
> when requested. + */
> + private ExtendedProperties overridingProperties = null;
>
> - /**
> - * This is a hashtable of initialized directives.
> - * The directives that populate this hashtable are
> - * taken from the RUNTIME_DEFAULT_DIRECTIVES
> - * property file. This hashtable is passed
> - * to each parser that is created.
> - */
> - private Hashtable runtimeDirectives;
> + /**
> + * This is a hashtable of initialized directives. The directives that populate \
> this hashtable are taken from the RUNTIME_DEFAULT_DIRECTIVES property file. + * \
> This hashtable is passed to each parser that is created. + */
> + private Hashtable runtimeDirectives;
>
> - /**
> - * Object that houses the configuration options for
> - * the velocity runtime. The ExtendedProperties object allows
> - * the convenient retrieval of a subset of properties.
> - * For example all the properties for a resource loader
> - * can be retrieved from the main ExtendedProperties object
> - * using something like the following:
> - *
> - * ExtendedProperties loaderConfiguration =
> - * configuration.subset(loaderID);
> - *
> - * And a configuration is a lot more convenient to deal
> - * with then conventional properties objects, or Maps.
> - */
> - private ExtendedProperties configuration = new ExtendedProperties();
> + /**
> + * Object that houses the configuration options for the velocity runtime. The \
> ExtendedProperties object allows the convenient retrieval of a subset of + * \
> properties. For example all the properties for a resource loader can be retrieved \
> from the main ExtendedProperties object using something like the + * following:
> + *
> + * ExtendedProperties loaderConfiguration = configuration.subset(loaderID);
> + *
> + * And a configuration is a lot more convenient to deal with then conventional \
> properties objects, or Maps. + */
> + private ExtendedProperties configuration = new ExtendedProperties();
>
> - private ResourceManager resourceManager = null;
> + private ResourceManager resourceManager = null;
>
> - /**
> - * This stores the engine-wide set of event handlers. Event handlers for
> - * each specific merge are stored in the context.
> - */
> - private EventCartridge eventCartridge = null;
> + /**
> + * This stores the engine-wide set of event handlers. Event handlers for each \
> specific merge are stored in the context. + */
> + private EventCartridge eventCartridge = null;
>
> - /*
> - * Each runtime instance has it's own introspector
> - * to ensure that each instance is completely separate.
> - */
> - private Introspector introspector = null;
> + /*
> + * Each runtime instance has it's own introspector to ensure that each instance \
> is completely separate. + */
> + private Introspector introspector = null;
>
> + /*
> + * Opaque reference to something specificed by the application for use in \
> application supplied/specified pluggable components + */
> + private Map applicationAttributes = null;
>
> - /*
> - * Opaque reference to something specificed by the
> - * application for use in application supplied/specified
> - * pluggable components
> - */
> - private Map applicationAttributes = null;
> + private Uberspect uberSpect;
>
> + /**
> + * Creates a new RuntimeInstance object.
> + */
> + public RuntimeInstance() {
> + /*
> + * create a VM factory, introspector, and application attributes
> + */
> + vmFactory = new VelocimacroFactory(this);
>
> - private Uberspect uberSpect;
> + /*
> + * make a new introspector and initialize it
> + */
> + introspector = new Introspector(getLog());
>
> - /**
> - * Creates a new RuntimeInstance object.
> - */
> - public RuntimeInstance()
> - {
> - /*
> - * create a VM factory, introspector, and application attributes
> - */
> - vmFactory = new VelocimacroFactory( this );
> + /*
> + * and a store for the application attributes
> + */
> + applicationAttributes = new HashMap();
> + }
>
> - /*
> - * make a new introspector and initialize it
> - */
> - introspector = new Introspector(getLog());
> + /**
> + * This is the primary initialization method in the Velocity Runtime. The systems \
> that are setup/initialized here are as follows: + *
> + * <ul>
> + * <li>Logging System</li>
> + * <li>ResourceManager</li>
> + * <li>EventHandler</li>
> + * <li>Parser Pool</li>
> + * <li>Global Cache</li>
> + * <li>Static Content Include System</li>
> + * <li>Velocimacro System</li>
> + * </ul>
> + *
> + * @throws Exception
> + * When an error occured during initialization.
> + */
> + public synchronized void init() throws Exception {
> + if (!initialized && !initializing) {
> + initializing = true;
>
> - /*
> - * and a store for the application attributes
> - */
> - applicationAttributes = new HashMap();
> - }
> + log.trace("*******************************************************************");
> + log.debug("Starting Apache Velocity v@build.version@ (compiled: \
> @build.time@)"); + log.trace("RuntimeInstance initializing.");
>
> - /**
> - * This is the primary initialization method in the Velocity
> - * Runtime. The systems that are setup/initialized here are
> - * as follows:
> - *
> - * <ul>
> - * <li>Logging System</li>
> - * <li>ResourceManager</li>
> - * <li>EventHandler</li>
> - * <li>Parser Pool</li>
> - * <li>Global Cache</li>
> - * <li>Static Content Include System</li>
> - * <li>Velocimacro System</li>
> - * </ul>
> - * @throws Exception When an error occured during initialization.
> - */
> - public synchronized void init()
> - throws Exception
> - {
> - if (!initialized && !initializing)
> - {
> - initializing = true;
> + initializeProperties();
> + initializeLog();
> + initializeResourceManager();
> + initializeDirectives();
> + initializeEventHandlers();
> + initializeParserPool();
>
> - log.trace("*******************************************************************");
>
> - log.debug("Starting Apache Velocity v@build.version@ (compiled: \
> @build.time@)");
> - log.trace("RuntimeInstance initializing.");
> + initializeIntrospection();
> + /*
> + * initialize the VM Factory. It will use the properties accessable from \
> Runtime, so keep this here at the end. + */
> + vmFactory.initVelocimacro();
>
> - initializeProperties();
> - initializeLog();
> - initializeResourceManager();
> - initializeDirectives();
> - initializeEventHandlers();
> - initializeParserPool();
> + log.trace("RuntimeInstance successfully initialized.");
>
> - initializeIntrospection();
> - /*
> - * initialize the VM Factory. It will use the properties
> - * accessable from Runtime, so keep this here at the end.
> - */
> - vmFactory.initVelocimacro();
> + initialized = true;
> + initializing = false;
> + }
> + }
>
> - log.trace("RuntimeInstance successfully initialized.");
> + /**
> + * Returns true if the RuntimeInstance has been successfully initialized.
> + *
> + * @return True if the RuntimeInstance has been successfully initialized.
> + */
> + public boolean isInitialized() {
> + return initialized;
> + }
>
> - initialized = true;
> - initializing = false;
> - }
> - }
> + /**
> + * Gets the classname for the Uberspect introspection package and instantiates an \
> instance. + */
> + private void initializeIntrospection() throws Exception {
> + String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);
>
> - /**
> - * Returns true if the RuntimeInstance has been successfully initialized.
> - * @return True if the RuntimeInstance has been successfully initialized.
> - */
> - public boolean isInitialized()
> - {
> - return initialized;
> - }
> + if (rm != null && rm.length() > 0) {
> + Object o = null;
>
> - /**
> - * Gets the classname for the Uberspect introspection package and
> - * instantiates an instance.
> - */
> - private void initializeIntrospection()
> - throws Exception
> - {
> - String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);
> + try {
> + o = ClassUtils.getNewInstance(rm);
> + }
> + catch (ClassNotFoundException cnfe) {
> + String err = "The specified class for Uberspect (" + rm + ") does not exist or \
> is not accessible to the current classloader."; + log.error(err);
> + throw new Exception(err);
> + }
>
> - if (rm != null && rm.length() > 0)
> - {
> - Object o = null;
> + if (!(o instanceof Uberspect)) {
> + String err = "The specified class for Uberspect (" + rm + ") does not \
> implement " + Uberspect.class.getName() + + "; Velocity is not initialized \
> correctly.";
> - try
> - {
> - o = ClassUtils.getNewInstance( rm );
> - }
> - catch (ClassNotFoundException cnfe)
> - {
> - String err = "The specified class for Uberspect (" + rm
> - + ") does not exist or is not accessible to the current \
> classloader.";
> - log.error(err);
> - throw new Exception(err);
> - }
> + log.error(err);
> + throw new Exception(err);
> + }
>
> - if (!(o instanceof Uberspect))
> - {
> - String err = "The specified class for Uberspect ("
> - + rm + ") does not implement " + Uberspect.class.getName()
> - + "; Velocity is not initialized correctly.";
> + uberSpect = (Uberspect) o;
>
> - log.error(err);
> - throw new Exception(err);
> - }
> + if (uberSpect instanceof UberspectLoggable) {
> + ((UberspectLoggable) uberSpect).setLog(getLog());
> + }
>
> - uberSpect = (Uberspect) o;
> + if (uberSpect instanceof RuntimeServicesAware) {
> + ((RuntimeServicesAware) uberSpect).setRuntimeServices(this);
> + }
>
> - if (uberSpect instanceof UberspectLoggable)
> - {
> - ((UberspectLoggable) uberSpect).setLog(getLog());
> - }
> + uberSpect.init();
> + }
> + else {
> + /*
> + * someone screwed up. Lets not fool around...
> + */
>
> - if (uberSpect instanceof RuntimeServicesAware)
> - {
> - ((RuntimeServicesAware) uberSpect).setRuntimeServices(this);
> - }
> -
> - uberSpect.init();
> - }
> - else
> - {
> - /*
> - * someone screwed up. Lets not fool around...
> - */
> + String err = "It appears that no class was specified as the" + " Uberspect. \
> Please ensure that all configuration" + " information is correct.";
> - String err = "It appears that no class was specified as the"
> - + " Uberspect. Please ensure that all configuration"
> - + " information is correct.";
> + log.error(err);
> + throw new Exception(err);
> + }
> + }
>
> - log.error(err);
> - throw new Exception(err);
> - }
> - }
> + /**
> + * Initializes the Velocity Runtime with properties file. The properties file may \
> be in the file system proper, or the properties file may be in the + * classpath.
> + */
> + private void setDefaultProperties() {
> + InputStream inputStream = null;
> + try {
> + inputStream = getClass().getResourceAsStream('/' + DEFAULT_RUNTIME_PROPERTIES);
>
> - /**
> - * Initializes the Velocity Runtime with properties file.
> - * The properties file may be in the file system proper,
> - * or the properties file may be in the classpath.
> - */
> - private void setDefaultProperties()
> - {
> - InputStream inputStream = null;
> - try
> - {
> - inputStream = getClass()
> - .getResourceAsStream('/' + DEFAULT_RUNTIME_PROPERTIES);
> + configuration.load(inputStream);
>
> - configuration.load( inputStream );
> + if (log.isDebugEnabled()) {
> + log.debug("Default Properties File: " + new \
> File(DEFAULT_RUNTIME_PROPERTIES).getPath()); + }
>
> - if (log.isDebugEnabled())
> - {
> - log.debug("Default Properties File: " +
> - new File(DEFAULT_RUNTIME_PROPERTIES).getPath());
> - }
> + }
> + catch (IOException ioe) {
> + log.error("Cannot get Velocity Runtime default properties!", ioe);
> + }
> + finally {
> + try {
> + if (inputStream != null) {
> + inputStream.close();
> + }
> + }
> + catch (IOException ioe) {
> + log.error("Cannot close Velocity Runtime default properties!", ioe);
> + }
> + }
> + }
>
> + /**
> + * Allows an external system to set a property in the Velocity Runtime.
> + *
> + * @param key
> + * property key
> + * @param value
> + * property value
> + */
> + public void setProperty(String key, Object value) {
>
> - }
> - catch (IOException ioe)
> - {
> - log.error("Cannot get Velocity Runtime default properties!", ioe);
> - }
> - finally
> - {
> - try
> - {
> - if (inputStream != null)
> - {
> - inputStream.close();
> - }
> - }
> - catch (IOException ioe)
> - {
> - log.error("Cannot close Velocity Runtime default properties!", \
> ioe);
> - }
> - }
> - }
> + if (overridingProperties == null) {
> + overridingProperties = new ExtendedProperties();
> + }
>
> - /**
> - * Allows an external system to set a property in
> - * the Velocity Runtime.
> - *
> - * @param key property key
> - * @param value property value
> - */
> - public void setProperty(String key, Object value)
> - {
> - if (overridingProperties == null)
> - {
> - overridingProperties = new ExtendedProperties();
> - }
> + if (value instanceof String)
> + {
> + String newValue = replaceEnviornmentalVariable((String) value);
> + overridingProperties.setProperty(key, newValue);
> + }
> + else if ( value instanceof String[] )
> + {
> + String[] stringArray = (String[])value;
> + String[] newStringArray = new String [ stringArray.length] ;
> + for ( int i = 0 ; i < stringArray.length;i ++ )
> + {
> + newStringArray[i] = replaceEnviornmentalVariable(stringArray[i]);
> + }
> +
> + overridingProperties.setProperty(key, newStringArray);
> + }
> +
> + }
>
> - overridingProperties.setProperty(key, value);
> - }
> + /**
> + * Allow an external system to set an ExtendedProperties object to use. This is \
> useful where the external system also uses the ExtendedProperties class and + * \
> the velocity configuration is a subset of parent application's configuration. This \
> is the case with Turbine. + *
> + * @param configuration
> + */
> + public void setConfiguration(ExtendedProperties configuration) {
> + if (overridingProperties == null) {
> + overridingProperties = configuration;
> + }
> + else {
> + // Avoid possible ConcurrentModificationException
> + if (overridingProperties != configuration) {
> + overridingProperties.combine(configuration);
> + }
> + }
> + }
>
> - /**
> - * Allow an external system to set an ExtendedProperties
> - * object to use. This is useful where the external
> - * system also uses the ExtendedProperties class and
> - * the velocity configuration is a subset of
> - * parent application's configuration. This is
> - * the case with Turbine.
> - *
> - * @param configuration
> - */
> - public void setConfiguration( ExtendedProperties configuration)
> - {
> - if (overridingProperties == null)
> - {
> - overridingProperties = configuration;
> - }
> - else
> - {
> - // Avoid possible ConcurrentModificationException
> - if (overridingProperties != configuration)
> - {
> - overridingProperties.combine(configuration);
> - }
> - }
> - }
> + /**
> + * Add a property to the configuration. If it already exists then the value \
> stated here will be added to the configuration entry. For example, if + *
> + * resource.loader = file
> + *
> + * is already present in the configuration and you
> + *
> + * addProperty("resource.loader", "classpath")
> + *
> + * Then you will end up with a Vector like the following:
> + *
> + * ["file", "classpath"]
> + *
> + * @param key
> + * @param value
> + */
> + public void addProperty(String key, Object value) {
> + if (overridingProperties == null) {
> + overridingProperties = new ExtendedProperties();
> + }
>
> - /**
> - * Add a property to the configuration. If it already
> - * exists then the value stated here will be added
> - * to the configuration entry. For example, if
> - *
> - * resource.loader = file
> - *
> - * is already present in the configuration and you
> - *
> - * addProperty("resource.loader", "classpath")
> - *
> - * Then you will end up with a Vector like the
> - * following:
> - *
> - * ["file", "classpath"]
> - *
> - * @param key
> - * @param value
> - */
> - public void addProperty(String key, Object value)
> - {
> - if (overridingProperties == null)
> - {
> - overridingProperties = new ExtendedProperties();
> - }
> + overridingProperties.addProperty(key, value);
> + }
>
> - overridingProperties.addProperty(key, value);
> - }
> + /**
> + * Clear the values pertaining to a particular property.
> + *
> + * @param key
> + * of property to clear
> + */
> + public void clearProperty(String key) {
> + if (overridingProperties != null) {
> + overridingProperties.clearProperty(key);
> + }
> + }
>
> - /**
> - * Clear the values pertaining to a particular
> - * property.
> - *
> - * @param key of property to clear
> - */
> - public void clearProperty(String key)
> - {
> - if (overridingProperties != null)
> - {
> - overridingProperties.clearProperty(key);
> - }
> - }
> + /**
> + * Allows an external caller to get a property. The calling routine is required \
> to know the type, as this routine will return an Object, as that is what + * \
> properties can be. + *
> + * @param key
> + * property to return
> + * @return Value of the property or null if it does not exist.
> + */
> + public Object getProperty(String key) {
> + Object o = null;
>
> - /**
> - * Allows an external caller to get a property. The calling
> - * routine is required to know the type, as this routine
> - * will return an Object, as that is what properties can be.
> - *
> - * @param key property to return
> - * @return Value of the property or null if it does not exist.
> - */
> - public Object getProperty(String key)
> - {
> - Object o = null;
> -
> - /**
> - * Before initialization, check the user-entered properties first.
> - */
> - if (!initialized && !initializing && overridingProperties != null)
> - {
> - o = overridingProperties.get(key);
> - }
> -
> - /**
> - * After initialization, configuration will hold all properties.
> - */
> - if (o == null)
> - {
> - o = configuration.getProperty(key);
> - }
> - if (o instanceof String)
> - {
> - return StringUtils.nullTrim((String) o);
> - }
> - else
> - {
> - return o;
> - }
> - }
> + /**
> + * Before initialization, check the user-entered properties first.
> + */
> + if (!initialized && !initializing && overridingProperties != null) {
> + o = overridingProperties.get(key);
> + }
>
> - /**
> - * Initialize Velocity properties, if the default
> - * properties have not been laid down first then
> - * do so. Then proceed to process any overriding
> - * properties. Laying down the default properties
> - * gives a much greater chance of having a
> - * working system.
> - */
> - private void initializeProperties()
> - {
> - /*
> - * Always lay down the default properties first as
> - * to provide a solid base.
> - */
> - if (configuration.isInitialized() == false)
> - {
> - setDefaultProperties();
> - }
> + /**
> + * After initialization, configuration will hold all properties.
> + */
> + if (o == null) {
> + o = configuration.getProperty(key);
> + }
> + if (o instanceof String) {
> + return StringUtils.nullTrim((String) o);
> + }
> + else {
> + return o;
> + }
> + }
>
> - if( overridingProperties != null)
> - {
> - configuration.combine(overridingProperties);
> - }
> - }
> + /**
> + * Replace all environmental variables in the form of ${VELOCITY_HOME} with their
> + * expansions
> + * @param properties
> + */
> +
> + private void replaceEnviormentalVariables(ExtendedProperties properties) {
>
> - /**
> - * Initialize the Velocity Runtime with a Properties
> - * object.
> - *
> - * @param p
> - * @throws Exception When an error occurs during initialization.
> - */
> - public void init(Properties p) throws Exception
> - {
> - overridingProperties = ExtendedProperties.convertProperties(p);
> - init();
> - }
> + Iterator iterator = properties.getKeys();
> + Map convertedKeys = new HashMap();
>
> - /**
> - * Initialize the Velocity Runtime with the name of
> - * ExtendedProperties object.
> - *
> - * @param configurationFile
> - * @throws Exception When an error occurs during initialization.
> - */
> - public void init(String configurationFile)
> - throws Exception
> - {
> - overridingProperties = new ExtendedProperties(configurationFile);
> - init();
> - }
> + while (iterator.hasNext()) {
> + String key = (String) iterator.next();
> + Object value = properties.get(key);
>
> - private void initializeResourceManager()
> - throws Exception
> - {
> - /*
> - * Which resource manager?
> - */
> + if (value instanceof String) {
>
> - String rm = getString(RuntimeConstants.RESOURCE_MANAGER_CLASS);
> + String v = replaceEnviornmentalVariable((String) value);
> + convertedKeys.put(key, v);
>
> - if (rm != null && rm.length() > 0)
> - {
> - /*
> - * if something was specified, then make one.
> - * if that isn't a ResourceManager, consider
> - * this a huge error and throw
> - */
> + }
> + else if (value instanceof String[]) {
> + String[] stringArray = (String[]) value;
> + for (int i = 0; i < stringArray.length; i++) {
> + String val = stringArray[i];
> + String v = replaceEnviornmentalVariable((String) val);
> + convertedKeys.put(key, v);
>
> - Object o = null;
> + }
> + }
>
> - try
> - {
> - o = ClassUtils.getNewInstance( rm );
> - }
> - catch (ClassNotFoundException cnfe )
> - {
> - String err = "The specified class for ResourceManager (" + rm
> - + ") does not exist or is not accessible to the current \
> classloader.";
> - log.error(err);
> - throw new Exception(err);
> - }
> + }
>
> - if (!(o instanceof ResourceManager))
> - {
> - String err = "The specified class for ResourceManager (" + rm
> - + ") does not implement " + ResourceManager.class.getName()
> - + "; Velocity is not initialized correctly.";
> + properties.putAll(convertedKeys);
>
> - log.error(err);
> - throw new Exception(err);
> - }
> + }
>
> - resourceManager = (ResourceManager) o;
> + /**
> + * Replace all occurrences of ${} in a string with its corresponding expanded \
> environmental var's + * @param string
> + * @return
> + */
> +
> + private String replaceEnviornmentalVariable(String string) {
>
> - resourceManager.initialize(this);
> - }
> - else
> - {
> - /*
> - * someone screwed up. Lets not fool around...
> - */
> + int start = string.indexOf("${");
>
> - String err = "It appears that no class was specified as the"
> - + " ResourceManager. Please ensure that all configuration"
> - + " information is correct.";
> + if (start != -1) {
>
> - log.error(err);
> - throw new Exception( err );
> - }
> - }
> + int end = string.indexOf('}');
>
> - private void initializeEventHandlers()
> - throws Exception
> - {
> + if (end != -1) {
> + String env = string.substring(start + 2, end);
> + String regex = "\\$\\{" + env + "\\}";
> + String replacement = System.getenv(env);
> + if (replacement != null) {
> + return string.replaceAll(regex, replacement);
>
> - eventCartridge = new EventCartridge();
> + }
>
> - /**
> - * For each type of event handler, get the class name, instantiate it, and \
> store it.
> - */
> + }
>
> - String[] referenceinsertion = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION);
>
> - if ( referenceinsertion != null )
> - {
> - for ( int i=0; i < referenceinsertion.length; i++ )
> - {
> - EventHandler ev = \
> initializeSpecificEventHandler(referenceinsertion[i],RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION,ReferenceInsertionEventHandler.class);
>
> - if (ev != null)
> - \
> eventCartridge.addReferenceInsertionEventHandler((ReferenceInsertionEventHandler) \
> ev);
> - }
> - }
> + }
> + return string;
>
> - String[] nullset = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_NULLSET);
>
> - if ( nullset != null )
> - {
> - for ( int i=0; i < nullset.length; i++ )
> - {
> - EventHandler ev = \
> initializeSpecificEventHandler(nullset[i],RuntimeConstants.EVENTHANDLER_NULLSET,NullSetEventHandler.class);
>
> - if (ev != null)
> - eventCartridge.addNullSetEventHandler((NullSetEventHandler) \
> ev);
> - }
> - }
> + }
>
> - String[] methodexception = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION);
>
> - if ( methodexception != null )
> - {
> - for ( int i=0; i < methodexception.length; i++ )
> - {
> - EventHandler ev = \
> initializeSpecificEventHandler(methodexception[i],RuntimeConstants.EVENTHANDLER_METHODEXCEPTION,MethodExceptionEventHandler.class);
>
> - if (ev != null)
> - \
> eventCartridge.addMethodExceptionHandler((MethodExceptionEventHandler) \
> ev);
> - }
> - }
> + /**
> + * Initialize Velocity properties, if the default properties have not been laid \
> down first then do so. Then proceed to process any overriding properties. + * \
> Laying down the default properties gives a much greater chance of having a working \
> system. + */
> + private void initializeProperties() {
> + /*
> + * Always lay down the default properties first as to provide a solid base.
> + */
> + if (configuration.isInitialized() == false) {
> + setDefaultProperties();
> + replaceEnviormentalVariables(configuration);
> + }
>
> - String[] includeHandler = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_INCLUDE);
>
> - if ( includeHandler != null )
> - {
> - for ( int i=0; i < includeHandler.length; i++ )
> - {
> - EventHandler ev = \
> initializeSpecificEventHandler(includeHandler[i],RuntimeConstants.EVENTHANDLER_INCLUDE,IncludeEventHandler.class);
>
> - if (ev != null)
> - eventCartridge.addIncludeEventHandler((IncludeEventHandler) \
> ev);
> - }
> - }
> + if (overridingProperties != null) {
> + replaceEnviormentalVariables(overridingProperties);
> + configuration.combine(overridingProperties);
> + }
> + }
>
> - String[] invalidReferenceSet = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES);
>
> - if ( invalidReferenceSet != null )
> - {
> - for ( int i=0; i < invalidReferenceSet.length; i++ )
> - {
> - EventHandler ev = \
> initializeSpecificEventHandler(invalidReferenceSet[i],RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES,InvalidReferenceEventHandler.class);
>
> - if (ev != null)
> - {
> - \
> eventCartridge.addInvalidReferenceEventHandler((InvalidReferenceEventHandler) \
> ev);
> - }
> - }
> - }
> + /**
> + * Initialize the Velocity Runtime with a Properties object.
> + *
> + * @param p
> + * @throws Exception
> + * When an error occurs during initialization.
> + */
> + public void init(Properties p) throws Exception {
> + overridingProperties = ExtendedProperties.convertProperties(p);
> + init();
> + }
>
> + /**
> + * Initialize the Velocity Runtime with the name of ExtendedProperties object.
> + *
> + * @param configurationFile
> + * @throws Exception
> + * When an error occurs during initialization.
> + */
> + public void init(String configurationFile) throws Exception {
> + overridingProperties = new ExtendedProperties(configurationFile);
> + init();
> + }
>
> - }
> + private void initializeResourceManager() throws Exception {
> + /*
> + * Which resource manager?
> + */
>
> - private EventHandler initializeSpecificEventHandler(String classname, String \
> paramName, Class EventHandlerInterface)
> - throws Exception
> - {
> - if ( classname != null && classname.length() > 0)
> - {
> - Object o = null;
> - try {
> - o = ClassUtils.getNewInstance(classname);
> - }
> - catch (ClassNotFoundException cnfe )
> - {
> - String err = "The specified class for "
> - + paramName + " (" + classname
> - + ") does not exist or is not accessible to the current \
> classloader.";
> - log.error(err);
> - throw new Exception(err);
> - }
> + String rm = getString(RuntimeConstants.RESOURCE_MANAGER_CLASS);
>
> - if (!EventHandlerInterface.isAssignableFrom(EventHandlerInterface))
> - {
> - String err = "The specified class for " + paramName + " ("
> - + classname + ") does not implement "
> - + EventHandlerInterface.getName()
> - + "; Velocity is not initialized correctly.";
> + if (rm != null && rm.length() > 0) {
> + /*
> + * if something was specified, then make one. if that isn't a ResourceManager, \
> consider this a huge error and throw + */
>
> - log.error(err);
> - throw new Exception(err);
> - }
> + Object o = null;
>
> - EventHandler ev = (EventHandler) o;
> - if ( ev instanceof RuntimeServicesAware )
> - ((RuntimeServicesAware) ev).setRuntimeServices(this);
> - return ev;
> + try {
> + o = ClassUtils.getNewInstance(rm);
> + }
> + catch (ClassNotFoundException cnfe) {
> + String err = "The specified class for ResourceManager (" + rm + ") does not \
> exist or is not accessible to the current classloader."; + log.error(err);
> + throw new Exception(err);
> + }
>
> - } else
> - return null;
> - }
> + if (!(o instanceof ResourceManager)) {
> + String err = "The specified class for ResourceManager (" + rm + ") does not \
> implement " + ResourceManager.class.getName() + + "; Velocity is not \
> initialized correctly.";
> - /**
> - * Initialize the Velocity logging system.
> - *
> - * @throws Exception
> - */
> - private void initializeLog() throws Exception
> - {
> - // since the Log we started with was just placeholding,
> - // let's update it with the real LogChute settings.
> - LogManager.updateLog(this.log, this);
> - }
> + log.error(err);
> + throw new Exception(err);
> + }
>
> + resourceManager = (ResourceManager) o;
>
> - /**
> - * This methods initializes all the directives
> - * that are used by the Velocity Runtime. The
> - * directives to be initialized are listed in
> - * the RUNTIME_DEFAULT_DIRECTIVES properties
> - * file.
> - *
> - * @throws Exception
> - */
> - private void initializeDirectives()
> - throws Exception
> - {
> - /*
> - * Initialize the runtime directive table.
> - * This will be used for creating parsers.
> - */
> - runtimeDirectives = new Hashtable();
> + resourceManager.initialize(this);
> + }
> + else {
> + /*
> + * someone screwed up. Lets not fool around...
> + */
>
> - Properties directiveProperties = new Properties();
> + String err = "It appears that no class was specified as the" + " \
> ResourceManager. Please ensure that all configuration" + + " information is \
> correct.";
> - /*
> - * Grab the properties file with the list of directives
> - * that we should initialize.
> - */
> + log.error(err);
> + throw new Exception(err);
> + }
> + }
>
> - InputStream inputStream = null;
> + private void initializeEventHandlers() throws Exception {
>
> - try
> - {
> - inputStream = getClass().getResourceAsStream('/' + \
> DEFAULT_RUNTIME_DIRECTIVES); + eventCartridge = new EventCartridge();
>
> - if (inputStream == null)
> - {
> - throw new Exception("Error loading directive.properties! " +
> - "Something is very wrong if these properties " \
> +
> - "aren't being located. Either your Velocity " \
> +
> - "distribution is incomplete or your Velocity " \
> +
> - "jar file is corrupted!");
> - }
> + /**
> + * For each type of event handler, get the class name, instantiate it, and store \
> it. + */
>
> - directiveProperties.load(inputStream);
> + String[] referenceinsertion = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION); \
> + if (referenceinsertion != null) { + for (int i = 0; i < \
> referenceinsertion.length; i++) { + EventHandler ev = \
> initializeSpecificEventHandler(referenceinsertion[i], \
> RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION, \
> + ReferenceInsertionEventHandler.class); + if (ev != null) \
> eventCartridge.addReferenceInsertionEventHandler((ReferenceInsertionEventHandler) \
> ev); + }
> + }
>
> - }
> - catch (IOException ioe)
> - {
> - log.error("Error while loading directive properties!", ioe);
> - }
> - finally
> - {
> - try
> - {
> - if (inputStream != null)
> - {
> - inputStream.close();
> - }
> - }
> - catch (IOException ioe)
> - {
> - log.error("Cannot close directive properties!", ioe);
> - }
> - }
> + String[] nullset = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_NULLSET); + if (nullset \
> != null) { + for (int i = 0; i < nullset.length; i++) {
> + EventHandler ev = initializeSpecificEventHandler(nullset[i], \
> RuntimeConstants.EVENTHANDLER_NULLSET, NullSetEventHandler.class); + if (ev != \
> null) eventCartridge.addNullSetEventHandler((NullSetEventHandler) ev); + }
> + }
>
> + String[] methodexception = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION); + if \
> (methodexception != null) { + for (int i = 0; i < methodexception.length; i++) {
> + EventHandler ev = initializeSpecificEventHandler(methodexception[i], \
> RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, \
> + MethodExceptionEventHandler.class); + if (ev != null) \
> eventCartridge.addMethodExceptionHandler((MethodExceptionEventHandler) ev); + }
> + }
>
> - /*
> - * Grab all the values of the properties. These
> - * are all class names for example:
> - *
> - * org.apache.velocity.runtime.directive.Foreach
> - */
> - Enumeration directiveClasses = directiveProperties.elements();
> + String[] includeHandler = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_INCLUDE); + if \
> (includeHandler != null) { + for (int i = 0; i < includeHandler.length; i++) {
> + EventHandler ev = initializeSpecificEventHandler(includeHandler[i], \
> RuntimeConstants.EVENTHANDLER_INCLUDE, IncludeEventHandler.class); + if (ev != \
> null) eventCartridge.addIncludeEventHandler((IncludeEventHandler) ev); + }
> + }
>
> - while (directiveClasses.hasMoreElements())
> - {
> - String directiveClass = (String) directiveClasses.nextElement();
> - loadDirective(directiveClass);
> - log.debug("Loaded System Directive: " + directiveClass);
> - }
> + String[] invalidReferenceSet = \
> configuration.getStringArray(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES); \
> + if (invalidReferenceSet != null) { + for (int i = 0; i < \
> invalidReferenceSet.length; i++) { + EventHandler ev = \
> initializeSpecificEventHandler(invalidReferenceSet[i], \
> RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES, \
> + InvalidReferenceEventHandler.class); + if (ev != null) {
> + eventCartridge.addInvalidReferenceEventHandler((InvalidReferenceEventHandler) \
> ev); + }
> + }
> + }
>
> - /*
> - * now the user's directives
> - */
> + }
>
> - String[] userdirective = configuration.getStringArray("userdirective");
> + private EventHandler initializeSpecificEventHandler(String classname, String \
> paramName, Class EventHandlerInterface) throws Exception { + if (classname != null \
> && classname.length() > 0) { + Object o = null;
> + try {
> + o = ClassUtils.getNewInstance(classname);
> + }
> + catch (ClassNotFoundException cnfe) {
> + String err = "The specified class for " + paramName + " (" + classname + ") \
> does not exist or is not accessible to the current classloader."; \
> + log.error(err); + throw new Exception(err);
> + }
>
> - for( int i = 0; i < userdirective.length; i++)
> - {
> - loadDirective(userdirective[i]);
> - if (log.isDebugEnabled())
> - {
> - log.debug("Loaded User Directive: " + userdirective[i]);
> - }
> - }
> + if (!EventHandlerInterface.isAssignableFrom(EventHandlerInterface)) {
> + String err = "The specified class for " + paramName + " (" + classname + ") \
> does not implement " + EventHandlerInterface.getName() + + "; Velocity is not \
> initialized correctly.";
> - }
> + log.error(err);
> + throw new Exception(err);
> + }
>
> - /**
> - * Programatically add a directive.
> - * @param directive
> - */
> - public void addDirective(Directive directive)
> - {
> - runtimeDirectives.put(directive.getName(), directive);
> - }
> + EventHandler ev = (EventHandler) o;
> + if (ev instanceof RuntimeServicesAware) ((RuntimeServicesAware) \
> ev).setRuntimeServices(this); + return ev;
>
> - /**
> - * Retrieve a previously instantiated directive.
> - * @param name name of the directive
> - * @return
> - */
> - public Directive getDirective(String name)
> - {
> - return (Directive) runtimeDirectives.get(name);
> - }
> + }
> + else return null;
> + }
>
> - /**
> - * Remove a directive.
> - * @param name name of the directive.
> - */
> - public void removeDirective(String name)
> - {
> - runtimeDirectives.remove(name);
> - }
> + /**
> + * Initialize the Velocity logging system.
> + *
> + * @throws Exception
> + */
> + private void initializeLog() throws Exception {
> + // since the Log we started with was just placeholding,
> + // let's update it with the real LogChute settings.
> + LogManager.updateLog(this.log, this);
> + }
>
> - /**
> - * instantiates and loads the directive with some basic checks
> - *
> - * @param directiveClass classname of directive to load
> - */
> - private void loadDirective(String directiveClass)
> - {
> - try
> - {
> - Object o = ClassUtils.getNewInstance( directiveClass );
> + /**
> + * This methods initializes all the directives that are used by the Velocity \
> Runtime. The directives to be initialized are listed in the + * \
> RUNTIME_DEFAULT_DIRECTIVES properties file. + *
> + * @throws Exception
> + */
> + private void initializeDirectives() throws Exception {
> + /*
> + * Initialize the runtime directive table. This will be used for creating \
> parsers. + */
> + runtimeDirectives = new Hashtable();
>
> - if (o instanceof Directive)
> - {
> - Directive directive = (Directive) o;
> - addDirective(directive);
> - }
> - else
> - {
> - log.error(directiveClass + " does not implement "
> - + Directive.class.getName() + "; it cannot be loaded.");
> - }
> - }
> - // The ugly threesome: ClassNotFoundException,
> - // IllegalAccessException, InstantiationException.
> - // Ignore Findbugs complaint for now.
> - catch (Exception e)
> - {
> - log.error("Failed to load Directive: " + directiveClass, e);
> - }
> - }
> + Properties directiveProperties = new Properties();
>
> + /*
> + * Grab the properties file with the list of directives that we should \
> initialize. + */
>
> - /**
> - * Initializes the Velocity parser pool.
> - */
> - private void initializeParserPool() throws Exception
> - {
> - /*
> - * Which parser pool?
> - */
> - String pp = getString(RuntimeConstants.PARSER_POOL_CLASS);
> + InputStream inputStream = null;
>
> - if (pp != null && pp.length() > 0)
> - {
> - /*
> - * if something was specified, then make one.
> - * if that isn't a ParserPool, consider
> - * this a huge error and throw
> - */
> + try {
> + inputStream = getClass().getResourceAsStream('/' + DEFAULT_RUNTIME_DIRECTIVES);
>
> - Object o = null;
> + if (inputStream == null) { throw new Exception("Error loading \
> directive.properties! " + "Something is very wrong if these properties " + + \
> "aren't being located. Either your Velocity " + "distribution is incomplete or your \
> Velocity " + "jar file is corrupted!"); }
> - try
> - {
> - o = ClassUtils.getNewInstance( pp );
> - }
> - catch (ClassNotFoundException cnfe )
> - {
> - String err = "The specified class for ParserPool ("
> - + pp
> - + ") does not exist (or is not accessible to the current \
> classloader.";
> - log.error(err);
> - throw new Exception(err);
> - }
> + directiveProperties.load(inputStream);
>
> - if (!(o instanceof ParserPool))
> - {
> - String err = "The specified class for ParserPool ("
> - + pp + ") does not implement " + ParserPool.class
> - + " Velocity not initialized correctly.";
> + }
> + catch (IOException ioe) {
> + log.error("Error while loading directive properties!", ioe);
> + }
> + finally {
> + try {
> + if (inputStream != null) {
> + inputStream.close();
> + }
> + }
> + catch (IOException ioe) {
> + log.error("Cannot close directive properties!", ioe);
> + }
> + }
>
> - log.error(err);
> - throw new Exception(err);
> - }
> + /*
> + * Grab all the values of the properties. These are all class names for example:
> + *
> + * org.apache.velocity.runtime.directive.Foreach
> + */
> + Enumeration directiveClasses = directiveProperties.elements();
>
> - parserPool = (ParserPool) o;
> + while (directiveClasses.hasMoreElements()) {
> + String directiveClass = (String) directiveClasses.nextElement();
> + loadDirective(directiveClass);
> + log.debug("Loaded System Directive: " + directiveClass);
> + }
>
> - parserPool.initialize(this);
> - }
> - else
> - {
> - /*
> - * someone screwed up. Lets not fool around...
> - */
> + /*
> + * now the user's directives
> + */
>
> - String err = "It appears that no class was specified as the"
> - + " ParserPool. Please ensure that all configuration"
> - + " information is correct.";
> + String[] userdirective = configuration.getStringArray("userdirective");
>
> - log.error(err);
> - throw new Exception( err );
> - }
> + for (int i = 0; i < userdirective.length; i++) {
> + loadDirective(userdirective[i]);
> + if (log.isDebugEnabled()) {
> + log.debug("Loaded User Directive: " + userdirective[i]);
> + }
> + }
>
> - }
> + }
>
> - /**
> - * Returns a JavaCC generated Parser.
> - *
> - * @return Parser javacc generated parser
> - */
> - public Parser createNewParser()
> - {
> - /* must be initialized before we use runtimeDirectives */
> - if (!initialized && !initializing)
> - {
> - log.debug("Velocity was not initialized! Calling init()...");
> - try
> - {
> - init();
> - }
> - catch (Exception e)
> - {
> - getLog().error("Could not auto-initialize Velocity", e);
> - throw new IllegalStateException("Velocity could not be \
> initialized!");
> - }
> - }
> + /**
> + * Programatically add a directive.
> + *
> + * @param directive
> + */
> + public void addDirective(Directive directive) {
> + runtimeDirectives.put(directive.getName(), directive);
> + }
>
> - Parser parser = new Parser(this);
> - parser.setDirectives(runtimeDirectives);
> - return parser;
> - }
> + /**
> + * Retrieve a previously instantiated directive.
> + *
> + * @param name
> + * name of the directive
> + * @return
> + */
> + public Directive getDirective(String name) {
> + return (Directive) runtimeDirectives.get(name);
> + }
>
> - /**
> - * Parse the input and return the root of
> - * AST node structure.
> - * <br><br>
> - * In the event that it runs out of parsers in the
> - * pool, it will create and let them be GC'd
> - * dynamically, logging that it has to do that. This
> - * is considered an exceptional condition. It is
> - * expected that the user will set the
> - * PARSER_POOL_SIZE property appropriately for their
> - * application. We will revisit this.
> - *
> - * @param reader Reader retrieved by a resource loader
> - * @param templateName name of the template being parsed
> - * @return A root node representing the template as an AST tree.
> - * @throws ParseException When the template could not be parsed.
> - */
> - public SimpleNode parse(Reader reader, String templateName)
> - throws ParseException
> - {
> - /*
> - * do it and dump the VM namespace for this template
> - */
> - return parse(reader, templateName, true);
> - }
> + /**
> + * Remove a directive.
> + *
> + * @param name
> + * name of the directive.
> + */
> + public void removeDirective(String name) {
> + runtimeDirectives.remove(name);
> + }
>
> - /**
> - * Parse the input and return the root of the AST node structure.
> - *
> - * @param reader Reader retrieved by a resource loader
> - * @param templateName name of the template being parsed
> - * @param dumpNamespace flag to dump the Velocimacro namespace for this \
> template
> - * @return A root node representing the template as an AST tree.
> - * @throws ParseException When the template could not be parsed.
> - */
> - public SimpleNode parse(Reader reader, String templateName, boolean \
> dumpNamespace)
> - throws ParseException
> - {
> - /* must be initialized before using parserPool */
> - if (!initialized && !initializing)
> - {
> - log.debug("Velocity was not initialized! Calling init()...");
> - try
> - {
> - init();
> - }
> - catch (Exception e)
> - {
> - getLog().error("Could not auto-initialize Velocity", e);
> - throw new IllegalStateException("Velocity could not be \
> initialized!");
> - }
> - }
> + /**
> + * instantiates and loads the directive with some basic checks
> + *
> + * @param directiveClass
> + * classname of directive to load
> + */
> + private void loadDirective(String directiveClass) {
> + try {
> + Object o = ClassUtils.getNewInstance(directiveClass);
>
> - SimpleNode ast = null;
> - Parser parser = (Parser) parserPool.get();
> + if (o instanceof Directive) {
> + Directive directive = (Directive) o;
> + addDirective(directive);
> + }
> + else {
> + log.error(directiveClass + " does not implement " + Directive.class.getName() \
> + "; it cannot be loaded."); + }
> + }
> + // The ugly threesome: ClassNotFoundException,
> + // IllegalAccessException, InstantiationException.
> + // Ignore Findbugs complaint for now.
> + catch (Exception e) {
> + log.error("Failed to load Directive: " + directiveClass, e);
> + }
> + }
>
> - if (parser == null)
> - {
> - /*
> - * if we couldn't get a parser from the pool
> - * make one and log it.
> - */
> + /**
> + * Initializes the Velocity parser pool.
> + */
> + private void initializeParserPool() throws Exception {
> + /*
> + * Which parser pool?
> + */
> + String pp = getString(RuntimeConstants.PARSER_POOL_CLASS);
>
> - if (log.isInfoEnabled())
> - {
> - log.info("Runtime : ran out of parsers. Creating a new one. "
> - + " Please increment the parser.pool.size property."
> - + " The current value is too small.");
> - }
> + if (pp != null && pp.length() > 0) {
> + /*
> + * if something was specified, then make one. if that isn't a ParserPool, \
> consider this a huge error and throw + */
>
> - parser = createNewParser();
> + Object o = null;
>
> - }
> + try {
> + o = ClassUtils.getNewInstance(pp);
> + }
> + catch (ClassNotFoundException cnfe) {
> + String err = "The specified class for ParserPool (" + pp + ") does not exist \
> (or is not accessible to the current classloader."; + log.error(err);
> + throw new Exception(err);
> + }
>
> - /*
> - * now, if we have a parser
> - */
> + if (!(o instanceof ParserPool)) {
> + String err = "The specified class for ParserPool (" + pp + ") does not \
> implement " + ParserPool.class + " Velocity not initialized correctly.";
> - if (parser != null)
> - {
> - try
> - {
> - /*
> - * dump namespace if we are told to. Generally, you want to
> - * do this - you don't in special circumstances, such as
> - * when a VM is getting init()-ed & parsed
> - */
> + log.error(err);
> + throw new Exception(err);
> + }
>
> - if (dumpNamespace)
> - {
> - dumpVMNamespace(templateName);
> - }
> + parserPool = (ParserPool) o;
>
> - ast = parser.parse(reader, templateName);
> - }
> - finally
> - {
> - /*
> - * put it back
> - */
> - parserPool.put(parser);
> + parserPool.initialize(this);
> + }
> + else {
> + /*
> + * someone screwed up. Lets not fool around...
> + */
>
> - }
> - }
> - else
> - {
> - log.error("Runtime : ran out of parsers and unable to create more.");
> - }
> - return ast;
> - }
> + String err = "It appears that no class was specified as the" + " ParserPool. \
> Please ensure that all configuration" + " information is correct.";
> - /**
> - * Renders the input string using the context into the output writer.
> - * To be used when a template is dynamically constructed, or want to use
> - * Velocity as a token replacer.
> - *
> - * @param context context to use in rendering input string
> - * @param out Writer in which to render the output
> - * @param logTag string to be used as the template name for log
> - * messages in case of error
> - * @param instring input string containing the VTL to be rendered
> - *
> - * @return true if successful, false otherwise. If false, see
> - * Velocity runtime log
> - * @throws ParseErrorException The template could not be parsed.
> - * @throws MethodInvocationException A method on a context object could not be \
> invoked.
> - * @throws ResourceNotFoundException A referenced resource could not be \
> loaded.
> - * @throws IOException While rendering to the writer, an I/O problem occured.
> - * @since Velocity 1.6
> - */
> - public boolean evaluate(Context context, Writer out,
> - String logTag, String instring) throws IOException
> - {
> - return evaluate(context, out, logTag,
> - new BufferedReader(new StringReader(instring)));
> - }
> + log.error(err);
> + throw new Exception(err);
> + }
>
> - /**
> - * Renders the input reader using the context into the output writer.
> - * To be used when a template is dynamically constructed, or want to
> - * use Velocity as a token replacer.
> - *
> - * @param context context to use in rendering input string
> - * @param writer Writer in which to render the output
> - * @param logTag string to be used as the template name for log messages
> - * in case of error
> - * @param reader Reader containing the VTL to be rendered
> - *
> - * @return true if successful, false otherwise. If false, see
> - * Velocity runtime log
> - * @throws ParseErrorException The template could not be parsed.
> - * @throws MethodInvocationException A method on a context object could not be \
> invoked.
> - * @throws ResourceNotFoundException A referenced resource could not be \
> loaded.
> - * @throws IOException While reading from the reader or rendering to the \
> writer,
> - * an I/O problem occured.
> - * @since Velocity 1.6
> - */
> - public boolean evaluate(Context context, Writer writer,
> - String logTag, Reader reader) throws IOException
> - {
> - if (logTag == null)
> - {
> - throw new NullPointerException("logTag (i.e. template name) cannot be \
> null, you must provide an identifier for the content being \
> evaluated");
> - }
> + }
>
> - SimpleNode nodeTree = null;
> - try
> - {
> - nodeTree = parse(reader, logTag);
> - }
> - catch (ParseException pex)
> - {
> - throw new ParseErrorException(pex);
> - }
> - catch (TemplateInitException pex)
> - {
> - throw new ParseErrorException(pex);
> - }
> + /**
> + * Returns a JavaCC generated Parser.
> + *
> + * @return Parser javacc generated parser
> + */
> + public Parser createNewParser() {
> + /* must be initialized before we use runtimeDirectives */
> + if (!initialized && !initializing) {
> + log.debug("Velocity was not initialized! Calling init()...");
> + try {
> + init();
> + }
> + catch (Exception e) {
> + getLog().error("Could not auto-initialize Velocity", e);
> + throw new IllegalStateException("Velocity could not be initialized!");
> + }
> + }
>
> - if (nodeTree == null)
> - {
> - return false;
> - }
> - else
> - {
> - return render(context, writer, logTag, nodeTree);
> - }
> - }
> + Parser parser = new Parser(this);
> + parser.setDirectives(runtimeDirectives);
> + return parser;
> + }
>
> + /**
> + * Parse the input and return the root of AST node structure. <br>
> + * <br>
> + * In the event that it runs out of parsers in the pool, it will create and let \
> them be GC'd dynamically, logging that it has to do that. This is considered + * \
> an exceptional condition. It is expected that the user will set the \
> PARSER_POOL_SIZE property appropriately for their application. We will revisit \
> this. + *
> + * @param reader
> + * Reader retrieved by a resource loader
> + * @param templateName
> + * name of the template being parsed
> + * @return A root node representing the template as an AST tree.
> + * @throws ParseException
> + * When the template could not be parsed.
> + */
> + public SimpleNode parse(Reader reader, String templateName) throws ParseException \
> { + /*
> + * do it and dump the VM namespace for this template
> + */
> + return parse(reader, templateName, true);
> + }
>
> - /**
> - * Initializes and renders the AST {@link SimpleNode} using the context
> - * into the output writer.
> - *
> - * @param context context to use in rendering input string
> - * @param writer Writer in which to render the output
> - * @param logTag string to be used as the template name for log messages
> - * in case of error
> - * @param nodeTree SimpleNode which is the root of the AST to be rendered
> - *
> - * @return true if successful, false otherwise. If false, see
> - * Velocity runtime log for errors
> - * @throws ParseErrorException The template could not be parsed.
> - * @throws MethodInvocationException A method on a context object could not be \
> invoked.
> - * @throws ResourceNotFoundException A referenced resource could not be \
> loaded.
> - * @throws IOException While rendering to the writer, an I/O problem occured.
> - * @since Velocity 1.6
> - */
> - public boolean render(Context context, Writer writer,
> - String logTag, SimpleNode nodeTree) throws IOException
> - {
> - /*
> - * we want to init then render
> - */
> - InternalContextAdapterImpl ica =
> - new InternalContextAdapterImpl(context);
> + /**
> + * Parse the input and return the root of the AST node structure.
> + *
> + * @param reader
> + * Reader retrieved by a resource loader
> + * @param templateName
> + * name of the template being parsed
> + * @param dumpNamespace
> + * flag to dump the Velocimacro namespace for this template
> + * @return A root node representing the template as an AST tree.
> + * @throws ParseException
> + * When the template could not be parsed.
> + */
> + public SimpleNode parse(Reader reader, String templateName, boolean \
> dumpNamespace) throws ParseException { + /* must be initialized before using \
> parserPool */ + if (!initialized && !initializing) {
> + log.debug("Velocity was not initialized! Calling init()...");
> + try {
> + init();
> + }
> + catch (Exception e) {
> + getLog().error("Could not auto-initialize Velocity", e);
> + throw new IllegalStateException("Velocity could not be initialized!");
> + }
> + }
>
> - ica.pushCurrentTemplateName(logTag);
> + SimpleNode ast = null;
> + Parser parser = (Parser) parserPool.get();
>
> - try
> - {
> - try
> - {
> - nodeTree.init(ica, this);
> - }
> - catch (TemplateInitException pex)
> - {
> - throw new ParseErrorException(pex);
> - }
> - /**
> - * pass through application level runtime exceptions
> - */
> - catch(RuntimeException e)
> - {
> - throw e;
> - }
> - catch(Exception e)
> - {
> - getLog().error("RuntimeInstance.render(): init exception for tag = \
> "
> - + logTag, e);
> - }
> + if (parser == null) {
> + /*
> + * if we couldn't get a parser from the pool make one and log it.
> + */
>
> - /*
> - * now render, and let any exceptions fly
> - */
> - nodeTree.render(ica, writer);
> - }
> - finally
> - {
> - ica.popCurrentTemplateName();
> - }
> + if (log.isInfoEnabled()) {
> + log.info("Runtime : ran out of parsers. Creating a new one. " + " Please \
> increment the parser.pool.size property." + + " The current value is too \
> small."); + }
>
> - return true;
> - }
> + parser = createNewParser();
>
> - /**
> - * Invokes a currently registered Velocimacro with the params provided
> - * and places the rendered stream into the writer.
> - * <br>
> - * Note : currently only accepts args to the VM if they are in the context.
> - *
> - * @param vmName name of Velocimacro to call
> - * @param logTag string to be used for template name in case of error. if \
> null,
> - * the vmName will be used
> - * @param params keys for args used to invoke Velocimacro, in java format
> - * rather than VTL (eg "foo" or "bar" rather than "$foo" or \
> "$bar")
> - * @param context Context object containing data/objects used for rendering.
> - * @param writer Writer for output stream
> - * @return true if Velocimacro exists and successfully invoked, false \
> otherwise.
> - * @throws IOException While rendering to the writer, an I/O problem occured.
> - */
> - public boolean invokeVelocimacro(final String vmName, String logTag,
> - String[] params, final Context context,
> - final Writer writer)
> - throws IOException
> - {
> - /* check necessary parameters */
> - if (vmName == null || context == null || writer == null)
> - {
> - getLog().error("RuntimeInstance.invokeVelocimacro() : invalid call : \
> vmName, context, and writer must not be null");
> - return false;
> - }
> + }
>
> - /* handle easily corrected parameters */
> - if (logTag == null)
> - {
> - logTag = vmName;
> - }
> - if (params == null)
> - {
> - params = new String[0];
> - }
> + /*
> + * now, if we have a parser
> + */
>
> - /* does the VM exist? */
> - if (!isVelocimacro(vmName, logTag))
> - {
> - getLog().error("RuntimeInstance.invokeVelocimacro() : VM '" + vmName
> - + "' is not registered.");
> - return false;
> - }
> + if (parser != null) {
> + try {
> + /*
> + * dump namespace if we are told to. Generally, you want to do this - you \
> don't in special circumstances, such as when a VM is getting init()-ed & + * \
> parsed + */
>
> - /* now just create the VM call, and use evaluate */
> - StringBuffer template = new StringBuffer("#");
> - template.append(vmName);
> - template.append("(");
> - for( int i = 0; i < params.length; i++)
> - {
> - template.append(" $");
> - template.append(params[i]);
> - }
> - template.append(" )");
> + if (dumpNamespace) {
> + dumpVMNamespace(templateName);
> + }
>
> - return evaluate(context, writer, logTag, template.toString());
> - }
> + ast = parser.parse(reader, templateName);
> + }
> + finally {
> + /*
> + * put it back
> + */
> + parserPool.put(parser);
>
> - /**
> - * Returns a <code>Template</code> from the resource manager.
> - * This method assumes that the character encoding of the
> - * template is set by the <code>input.encoding</code>
> - * property. The default is "ISO-8859-1"
> - *
> - * @param name The file name of the desired template.
> - * @return The template.
> - * @throws ResourceNotFoundException if template not found
> - * from any available source.
> - * @throws ParseErrorException if template cannot be parsed due
> - * to syntax (or other) error.
> - * @throws Exception if an error occurs in template initialization
> - */
> - public Template getTemplate(String name)
> - throws ResourceNotFoundException, ParseErrorException, Exception
> - {
> - return getTemplate(name, getString( INPUT_ENCODING, ENCODING_DEFAULT));
> - }
> + }
> + }
> + else {
> + log.error("Runtime : ran out of parsers and unable to create more.");
> + }
> + return ast;
> + }
>
> - /**
> - * Returns a <code>Template</code> from the resource manager
> - *
> - * @param name The name of the desired template.
> - * @param encoding Character encoding of the template
> - * @return The template.
> - * @throws ResourceNotFoundException if template not found
> - * from any available source.
> - * @throws ParseErrorException if template cannot be parsed due
> - * to syntax (or other) error.
> - * @throws Exception if an error occurs in template initialization
> - */
> - public Template getTemplate(String name, String encoding)
> - throws ResourceNotFoundException, ParseErrorException, Exception
> - {
> - /* must be initialized before using resourceManager */
> - if (!initialized && !initializing)
> - {
> - log.debug("Velocity not initialized yet. Calling init()...");
> - init();
> - }
> + /**
> + * Renders the input string using the context into the output writer. To be used \
> when a template is dynamically constructed, or want to use Velocity as a + * token \
> replacer. + *
> + * @param context
> + * context to use in rendering input string
> + * @param out
> + * Writer in which to render the output
> + * @param logTag
> + * string to be used as the template name for log messages in case of \
> error + * @param instring
> + * input string containing the VTL to be rendered
> + *
> + * @return true if successful, false otherwise. If false, see Velocity runtime \
> log + * @throws ParseErrorException
> + * The template could not be parsed.
> + * @throws MethodInvocationException
> + * A method on a context object could not be invoked.
> + * @throws ResourceNotFoundException
> + * A referenced resource could not be loaded.
> + * @throws IOException
> + * While rendering to the writer, an I/O problem occured.
> + * @since Velocity 1.6
> + */
> + public boolean evaluate(Context context, Writer out, String logTag, String \
> instring) throws IOException { + return evaluate(context, out, logTag, new \
> BufferedReader(new StringReader(instring))); + }
>
> - return (Template)
> - resourceManager.getResource(name,
> - ResourceManager.RESOURCE_TEMPLATE, encoding);
> - }
> + /**
> + * Renders the input reader using the context into the output writer. To be used \
> when a template is dynamically constructed, or want to use Velocity as a + * token \
> replacer. + *
> + * @param context
> + * context to use in rendering input string
> + * @param writer
> + * Writer in which to render the output
> + * @param logTag
> + * string to be used as the template name for log messages in case of \
> error + * @param reader
> + * Reader containing the VTL to be rendered
> + *
> + * @return true if successful, false otherwise. If false, see Velocity runtime \
> log + * @throws ParseErrorException
> + * The template could not be parsed.
> + * @throws MethodInvocationException
> + * A method on a context object could not be invoked.
> + * @throws ResourceNotFoundException
> + * A referenced resource could not be loaded.
> + * @throws IOException
> + * While reading from the reader or rendering to the writer, an I/O \
> problem occured. + * @since Velocity 1.6
> + */
> + public boolean evaluate(Context context, Writer writer, String logTag, Reader \
> reader) throws IOException { + if (logTag == null) { throw new \
> NullPointerException( + "logTag (i.e. template name) cannot be null, you must \
> provide an identifier for the content being evaluated"); }
> - /**
> - * Returns a static content resource from the
> - * resource manager. Uses the current value
> - * if INPUT_ENCODING as the character encoding.
> - *
> - * @param name Name of content resource to get
> - * @return parsed ContentResource object ready for use
> - * @throws ResourceNotFoundException if template not found
> - * from any available source.
> - * @throws ParseErrorException When the template could not be parsed.
> - * @throws Exception Any other error.
> - */
> - public ContentResource getContent(String name)
> - throws ResourceNotFoundException, ParseErrorException, Exception
> - {
> - /*
> - * the encoding is irrelvant as we don't do any converstion
> - * the bytestream should be dumped to the output stream
> - */
> + SimpleNode nodeTree = null;
> + try {
> + nodeTree = parse(reader, logTag);
> + }
> + catch (ParseException pex) {
> + throw new ParseErrorException(pex);
> + }
> + catch (TemplateInitException pex) {
> + throw new ParseErrorException(pex);
> + }
>
> - return getContent(name, getString( INPUT_ENCODING, ENCODING_DEFAULT));
> - }
> + if (nodeTree == null) {
> + return false;
> + }
> + else {
> + return render(context, writer, logTag, nodeTree);
> + }
> + }
>
> - /**
> - * Returns a static content resource from the
> - * resource manager.
> - *
> - * @param name Name of content resource to get
> - * @param encoding Character encoding to use
> - * @return parsed ContentResource object ready for use
> - * @throws ResourceNotFoundException if template not found
> - * from any available source.
> - * @throws ParseErrorException When the template could not be parsed.
> - * @throws Exception Any other error.
> - */
> - public ContentResource getContent(String name, String encoding)
> - throws ResourceNotFoundException, ParseErrorException, Exception
> - {
> - /* must be initialized before using resourceManager */
> - if (!initialized && !initializing)
> - {
> - log.debug("Velocity not initialized yet. Calling init()...");
> - init();
> - }
> + /**
> + * Initializes and renders the AST {@link SimpleNode} using the context into the \
> output writer. + *
> + * @param context
> + * context to use in rendering input string
> + * @param writer
> + * Writer in which to render the output
> + * @param logTag
> + * string to be used as the template name for log messages in case of \
> error + * @param nodeTree
> + * SimpleNode which is the root of the AST to be rendered
> + *
> + * @return true if successful, false otherwise. If false, see Velocity runtime \
> log for errors + * @throws ParseErrorException
> + * The template could not be parsed.
> + * @throws MethodInvocationException
> + * A method on a context object could not be invoked.
> + * @throws ResourceNotFoundException
> + * A referenced resource could not be loaded.
> + * @throws IOException
> + * While rendering to the writer, an I/O problem occured.
> + * @since Velocity 1.6
> + */
> + public boolean render(Context context, Writer writer, String logTag, SimpleNode \
> nodeTree) throws IOException { + /*
> + * we want to init then render
> + */
> + InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
>
> - return (ContentResource)
> - resourceManager.getResource(name,
> - ResourceManager.RESOURCE_CONTENT, encoding);
> - }
> + ica.pushCurrentTemplateName(logTag);
>
> + try {
> + try {
> + nodeTree.init(ica, this);
> + }
> + catch (TemplateInitException pex) {
> + throw new ParseErrorException(pex);
> + }
> + /**
> + * pass through application level runtime exceptions
> + */
> + catch (RuntimeException e) {
> + throw e;
> + }
> + catch (Exception e) {
> + getLog().error("RuntimeInstance.render(): init exception for tag = " + logTag, \
> e); + }
>
> - /**
> - * Determines if a template exists and returns name of the loader that
> - * provides it. This is a slightly less hokey way to support
> - * the Velocity.resourceExists() utility method, which was broken
> - * when per-template encoding was introduced. We can revisit this.
> - *
> - * @param resourceName Name of template or content resource
> - * @return class name of loader than can provide it
> - */
> - public String getLoaderNameForResource(String resourceName)
> - {
> - /* must be initialized before using resourceManager */
> - if (!initialized && !initializing)
> - {
> - log.debug("Velocity was not initialized! Calling init()...");
> - try
> - {
> - init();
> - }
> - catch (Exception e)
> - {
> - getLog().error("Could not initialize Velocity", e);
> - throw new IllegalStateException("Velocity could not be \
> initialized!");
> - }
> - }
> + /*
> + * now render, and let any exceptions fly
> + */
> + nodeTree.render(ica, writer);
> + }
> + finally {
> + ica.popCurrentTemplateName();
> + }
>
> - return resourceManager.getLoaderNameForResource(resourceName);
> - }
> + return true;
> + }
>
> - /**
> - * Returns a convenient Log instance that wraps the current LogChute.
> - * Use this to log error messages. It has the usual methods.
> - *
> - * @return A convenience Log instance that wraps the current LogChute.
> - */
> - public Log getLog()
> - {
> - return log;
> - }
> + /**
> + * Invokes a currently registered Velocimacro with the params provided and places \
> the rendered stream into the writer. <br> + * Note : currently only accepts args \
> to the VM if they are in the context. + *
> + * @param vmName
> + * name of Velocimacro to call
> + * @param logTag
> + * string to be used for template name in case of error. if null, the \
> vmName will be used + * @param params
> + * keys for args used to invoke Velocimacro, in java format rather \
> than VTL (eg "foo" or "bar" rather than "$foo" or "$bar") + * @param context
> + * Context object containing data/objects used for rendering.
> + * @param writer
> + * Writer for output stream
> + * @return true if Velocimacro exists and successfully invoked, false otherwise.
> + * @throws IOException
> + * While rendering to the writer, an I/O problem occured.
> + */
> + public boolean invokeVelocimacro(final String vmName, String logTag, String[] \
> params, final Context context, final Writer writer) throws IOException { + /* \
> check necessary parameters */ + if (vmName == null || context == null || writer == \
> null) { + getLog().error("RuntimeInstance.invokeVelocimacro() : invalid call : \
> vmName, context, and writer must not be null"); + return false;
> + }
>
> - /**
> - * @deprecated Use getLog() and call warn() on it.
> - * @see Log#warn(Object)
> - * @param message The message to log.
> - */
> - public void warn(Object message)
> - {
> - getLog().warn(message);
> - }
> + /* handle easily corrected parameters */
> + if (logTag == null) {
> + logTag = vmName;
> + }
> + if (params == null) {
> + params = new String[0];
> + }
>
> - /**
> - * @deprecated Use getLog() and call info() on it.
> - * @see Log#info(Object)
> - * @param message The message to log.
> - */
> - public void info(Object message)
> - {
> - getLog().info(message);
> - }
> + /* does the VM exist? */
> + if (!isVelocimacro(vmName, logTag)) {
> + getLog().error("RuntimeInstance.invokeVelocimacro() : VM '" + vmName + "' is \
> not registered."); + return false;
> + }
>
> - /**
> - * @deprecated Use getLog() and call error() on it.
> - * @see Log#error(Object)
> - * @param message The message to log.
> - */
> - public void error(Object message)
> - {
> - getLog().error(message);
> - }
> + /* now just create the VM call, and use evaluate */
> + StringBuffer template = new StringBuffer("#");
> + template.append(vmName);
> + template.append("(");
> + for (int i = 0; i < params.length; i++) {
> + template.append(" $");
> + template.append(params[i]);
> + }
> + template.append(" )");
>
> - /**
> - * @deprecated Use getLog() and call debug() on it.
> - * @see Log#debug(Object)
> - * @param message The message to log.
> - */
> - public void debug(Object message)
> - {
> - getLog().debug(message);
> - }
> + return evaluate(context, writer, logTag, template.toString());
> + }
>
> - /**
> - * String property accessor method with default to hide the
> - * configuration implementation.
> - *
> - * @param key property key
> - * @param defaultValue default value to return if key not
> - * found in resource manager.
> - * @return value of key or default
> - */
> - public String getString( String key, String defaultValue)
> - {
> - return configuration.getString(key, defaultValue);
> - }
> + /**
> + * Returns a <code>Template</code> from the resource manager. This method assumes \
> that the character encoding of the template is set by the + * \
> <code>input.encoding</code> property. The default is "ISO-8859-1" + *
> + * @param name
> + * The file name of the desired template.
> + * @return The template.
> + * @throws ResourceNotFoundException
> + * if template not found from any available source.
> + * @throws ParseErrorException
> + * if template cannot be parsed due to syntax (or other) error.
> + * @throws Exception
> + * if an error occurs in template initialization
> + */
> + public Template getTemplate(String name) throws ResourceNotFoundException, \
> ParseErrorException, Exception { + return getTemplate(name, \
> getString(INPUT_ENCODING, ENCODING_DEFAULT)); + }
>
> - /**
> - * Returns the appropriate VelocimacroProxy object if strVMname
> - * is a valid current Velocimacro.
> - *
> - * @param vmName Name of velocimacro requested
> - * @param templateName Name of the template that contains the velocimacro.
> - * @return The requested VelocimacroProxy.
> - */
> - public Directive getVelocimacro(String vmName, String templateName)
> - {
> - return vmFactory.getVelocimacro( vmName, templateName );
> - }
> + /**
> + * Returns a <code>Template</code> from the resource manager
> + *
> + * @param name
> + * The name of the desired template.
> + * @param encoding
> + * Character encoding of the template
> + * @return The template.
> + * @throws ResourceNotFoundException
> + * if template not found from any available source.
> + * @throws ParseErrorException
> + * if template cannot be parsed due to syntax (or other) error.
> + * @throws Exception
> + * if an error occurs in template initialization
> + */
> + public Template getTemplate(String name, String encoding) throws \
> ResourceNotFoundException, ParseErrorException, Exception { + /* must be \
> initialized before using resourceManager */ + if (!initialized && !initializing) {
> + log.debug("Velocity not initialized yet. Calling init()...");
> + init();
> + }
>
> - /**
> - * Adds a new Velocimacro. Usually called by Macro only while parsing.
> - *
> - * @param name Name of velocimacro
> - * @param macro String form of macro body
> - * @param argArray Array of strings, containing the
> - * #macro() arguments. the 0th is the name.
> - * @param sourceTemplate Name of the template that contains the velocimacro.
> - * @return True if added, false if rejected for some
> - * reason (either parameters or permission settings)
> - */
> - public boolean addVelocimacro( String name,
> - String macro,
> - String argArray[],
> - String sourceTemplate )
> - {
> - return vmFactory.addVelocimacro(name, macro, argArray, sourceTemplate);
> - }
> + return (Template) resourceManager.getResource(name, \
> ResourceManager.RESOURCE_TEMPLATE, encoding); + }
>
> - /**
> - * Checks to see if a VM exists
> - *
> - * @param vmName Name of the Velocimacro.
> - * @param templateName Template on which to look for the Macro.
> - * @return True if VM by that name exists, false if not
> - */
> - public boolean isVelocimacro( String vmName, String templateName )
> - {
> - return vmFactory.isVelocimacro(vmName, templateName);
> - }
> + /**
> + * Returns a static content resource from the resource manager. Uses the current \
> value if INPUT_ENCODING as the character encoding. + *
> + * @param name
> + * Name of content resource to get
> + * @return parsed ContentResource object ready for use
> + * @throws ResourceNotFoundException
> + * if template not found from any available source.
> + * @throws ParseErrorException
> + * When the template could not be parsed.
> + * @throws Exception
> + * Any other error.
> + */
> + public ContentResource getContent(String name) throws ResourceNotFoundException, \
> ParseErrorException, Exception { + /*
> + * the encoding is irrelvant as we don't do any converstion the bytestream \
> should be dumped to the output stream + */
>
> - /**
> - * tells the vmFactory to dump the specified namespace. This is to support
> - * clearing the VM list when in inline-VM-local-scope mode
> - * @param namespace Namespace to dump.
> - * @return True if namespace was dumped successfully.
> - */
> - public boolean dumpVMNamespace(String namespace)
> - {
> - return vmFactory.dumpVMNamespace( namespace );
> - }
> + return getContent(name, getString(INPUT_ENCODING, ENCODING_DEFAULT));
> + }
>
> - /* --------------------------------------------------------------------
> - * R U N T I M E A C C E S S O R M E T H O D S
> - * --------------------------------------------------------------------
> - * These are the getXXX() methods that are a simple wrapper
> - * around the configuration object. This is an attempt
> - * to make a the Velocity Runtime the single access point
> - * for all things Velocity, and allow the Runtime to
> - * adhere as closely as possible the the Mediator pattern
> - * which is the ultimate goal.
> - * --------------------------------------------------------------------
> - */
> + /**
> + * Returns a static content resource from the resource manager.
> + *
> + * @param name
> + * Name of content resource to get
> + * @param encoding
> + * Character encoding to use
> + * @return parsed ContentResource object ready for use
> + * @throws ResourceNotFoundException
> + * if template not found from any available source.
> + * @throws ParseErrorException
> + * When the template could not be parsed.
> + * @throws Exception
> + * Any other error.
> + */
> + public ContentResource getContent(String name, String encoding) throws \
> ResourceNotFoundException, ParseErrorException, Exception { + /* must be \
> initialized before using resourceManager */ + if (!initialized && !initializing) {
> + log.debug("Velocity not initialized yet. Calling init()...");
> + init();
> + }
>
> - /**
> - * String property accessor method to hide the configuration implementation
> - * @param key property key
> - * @return value of key or null
> - */
> - public String getString(String key)
> - {
> - return StringUtils.nullTrim(configuration.getString(key));
> - }
> + return (ContentResource) resourceManager.getResource(name, \
> ResourceManager.RESOURCE_CONTENT, encoding); + }
>
> - /**
> - * Int property accessor method to hide the configuration implementation.
> - *
> - * @param key Property key
> - * @return value
> - */
> - public int getInt(String key)
> - {
> - return configuration.getInt(key);
> - }
> + /**
> + * Determines if a template exists and returns name of the loader that provides \
> it. This is a slightly less hokey way to support the + * Velocity.resourceExists() \
> utility method, which was broken when per-template encoding was introduced. We can \
> revisit this. + *
> + * @param resourceName
> + * Name of template or content resource
> + * @return class name of loader than can provide it
> + */
> + public String getLoaderNameForResource(String resourceName) {
> + /* must be initialized before using resourceManager */
> + if (!initialized && !initializing) {
> + log.debug("Velocity was not initialized! Calling init()...");
> + try {
> + init();
> + }
> + catch (Exception e) {
> + getLog().error("Could not initialize Velocity", e);
> + throw new IllegalStateException("Velocity could not be initialized!");
> + }
> + }
>
> - /**
> - * Int property accessor method to hide the configuration implementation.
> - *
> - * @param key property key
> - * @param defaultValue The default value.
> - * @return value
> - */
> - public int getInt(String key, int defaultValue)
> - {
> - return configuration.getInt(key, defaultValue);
> - }
> + return resourceManager.getLoaderNameForResource(resourceName);
> + }
>
> - /**
> - * Boolean property accessor method to hide the configuration implementation.
> - *
> - * @param key property key
> - * @param def The default value if property not found.
> - * @return value of key or default value
> - */
> - public boolean getBoolean(String key, boolean def)
> - {
> - return configuration.getBoolean(key, def);
> - }
> + /**
> + * Returns a convenient Log instance that wraps the current LogChute. Use this to \
> log error messages. It has the usual methods. + *
> + * @return A convenience Log instance that wraps the current LogChute.
> + */
> + public Log getLog() {
> + return log;
> + }
>
> - /**
> - * Return the velocity runtime configuration object.
> - *
> - * @return Configuration object which houses the Velocity runtime
> - * properties.
> - */
> - public ExtendedProperties getConfiguration()
> - {
> - return configuration;
> - }
> + /**
> + * @deprecated Use getLog() and call warn() on it.
> + * @see Log#warn(Object)
> + * @param message
> + * The message to log.
> + */
> + public void warn(Object message) {
> + getLog().warn(message);
> + }
>
> - /**
> - * Return the Introspector for this instance
> - * @return The Introspector for this instance
> - */
> - public Introspector getIntrospector()
> - {
> - return introspector;
> - }
> + /**
> + * @deprecated Use getLog() and call info() on it.
> + * @see Log#info(Object)
> + * @param message
> + * The message to log.
> + */
> + public void info(Object message) {
> + getLog().info(message);
> + }
>
> - /**
> - * Returns the event handlers for the application.
> - * @return The event handlers for the application.
> - */
> - public EventCartridge getApplicationEventCartridge()
> - {
> - return eventCartridge;
> - }
> + /**
> + * @deprecated Use getLog() and call error() on it.
> + * @see Log#error(Object)
> + * @param message
> + * The message to log.
> + */
> + public void error(Object message) {
> + getLog().error(message);
> + }
>
> + /**
> + * @deprecated Use getLog() and call debug() on it.
> + * @see Log#debug(Object)
> + * @param message
> + * The message to log.
> + */
> + public void debug(Object message) {
> + getLog().debug(message);
> + }
>
> - /**
> - * Gets the application attribute for the given key
> - *
> - * @param key
> - * @return The application attribute for the given key.
> - */
> - public Object getApplicationAttribute(Object key)
> - {
> - return applicationAttributes.get(key);
> - }
> + /**
> + * String property accessor method with default to hide the configuration \
> implementation. + *
> + * @param key
> + * property key
> + * @param defaultValue
> + * default value to return if key not found in resource manager.
> + * @return value of key or default
> + */
> + public String getString(String key, String defaultValue) {
> + return configuration.getString(key, defaultValue);
> + }
>
> - /**
> - * Sets the application attribute for the given key
> - *
> - * @param key
> - * @param o The new application attribute.
> - * @return The old value of this attribute or null if it hasn't been set \
> before.
> - */
> - public Object setApplicationAttribute(Object key, Object o)
> - {
> - return applicationAttributes.put(key, o);
> - }
> + /**
> + * Returns the appropriate VelocimacroProxy object if strVMname is a valid \
> current Velocimacro. + *
> + * @param vmName
> + * Name of velocimacro requested
> + * @param templateName
> + * Name of the template that contains the velocimacro.
> + * @return The requested VelocimacroProxy.
> + */
> + public Directive getVelocimacro(String vmName, String templateName) {
> + return vmFactory.getVelocimacro(vmName, templateName);
> + }
>
> - /**
> - * Returns the Uberspect object for this Instance.
> - *
> - * @return The Uberspect object for this Instance.
> - */
> - public Uberspect getUberspect()
> - {
> - return uberSpect;
> - }
> + /**
> + * Adds a new Velocimacro. Usually called by Macro only while parsing.
> + *
> + * @param name
> + * Name of velocimacro
> + * @param macro
> + * String form of macro body
> + * @param argArray
> + * Array of strings, containing the #macro() arguments. the 0th is the \
> name. + * @param sourceTemplate
> + * Name of the template that contains the velocimacro.
> + * @return True if added, false if rejected for some reason (either parameters or \
> permission settings) + */
> + public boolean addVelocimacro(String name, String macro, String argArray[], \
> String sourceTemplate) { + return vmFactory.addVelocimacro(name, macro, argArray, \
> sourceTemplate); + }
>
> - /**
> - * This method is called before a macro is rendered. This method
> - * checks whether a macro call is within the allowed calling depth.
> - * If the macro call exceeds the allowed calling depth it will throw
> - * an exception.
> - *
> - * @param macroName name of the macro
> - * @param templateName name of the template file containing the macro
> - * @throws MacroOverflowException if the number of macro calls
> - * exceeds the specified value
> - */
> - public void startMacroRendering(String macroName, String templateName) throws \
> MacroOverflowException
> - {
> - vmFactory.startMacroRendering(macroName, templateName);
> - }
> + /**
> + * Checks to see if a VM exists
> + *
> + * @param vmName
> + * Name of the Velocimacro.
> + * @param templateName
> + * Template on which to look for the Macro.
> + * @return True if VM by that name exists, false if not
> + */
> + public boolean isVelocimacro(String vmName, String templateName) {
> + return vmFactory.isVelocimacro(vmName, templateName);
> + }
>
> - /**
> - * This method is called after a macro rendering is finished. It cleasr
> - * all the state saved in the VelociMacroFactory about this particular
> - * macro.
> - * @param macroName name of the macro
> - * @param templateName template name that contains the macro
> - */
> - public void endMacroRendering(String macroName, String templateName)
> - {
> - vmFactory.endMacroRendering(macroName, templateName);
> - }
> + /**
> + * tells the vmFactory to dump the specified namespace. This is to support \
> clearing the VM list when in inline-VM-local-scope mode + *
> + * @param namespace
> + * Namespace to dump.
> + * @return True if namespace was dumped successfully.
> + */
> + public boolean dumpVMNamespace(String namespace) {
> + return vmFactory.dumpVMNamespace(namespace);
> + }
> +
> + /*
> + * -------------------------------------------------------------------- R U N T I \
> M E A C C E S S O R M E T H O D S + * \
> -------------------------------------------------------------------- These are the \
> getXXX() methods that are a simple wrapper around the configuration + * object. \
> This is an attempt to make a the Velocity Runtime the single access point for all \
> things Velocity, and allow the Runtime to adhere as closely as + * possible the \
> the Mediator pattern which is the ultimate goal. \
> -------------------------------------------------------------------- + */
> +
> + /**
> + * String property accessor method to hide the configuration implementation
> + *
> + * @param key
> + * property key
> + * @return value of key or null
> + */
> + public String getString(String key) {
> + return StringUtils.nullTrim(configuration.getString(key));
> + }
> +
> + /**
> + * Int property accessor method to hide the configuration implementation.
> + *
> + * @param key
> + * Property key
> + * @return value
> + */
> + public int getInt(String key) {
> + return configuration.getInt(key);
> + }
> +
> + /**
> + * Int property accessor method to hide the configuration implementation.
> + *
> + * @param key
> + * property key
> + * @param defaultValue
> + * The default value.
> + * @return value
> + */
> + public int getInt(String key, int defaultValue) {
> + return configuration.getInt(key, defaultValue);
> + }
> +
> + /**
> + * Boolean property accessor method to hide the configuration implementation.
> + *
> + * @param key
> + * property key
> + * @param def
> + * The default value if property not found.
> + * @return value of key or default value
> + */
> + public boolean getBoolean(String key, boolean def) {
> + return configuration.getBoolean(key, def);
> + }
> +
> + /**
> + * Return the velocity runtime configuration object.
> + *
> + * @return Configuration object which houses the Velocity runtime properties.
> + */
> + public ExtendedProperties getConfiguration() {
> + return configuration;
> + }
> +
> + /**
> + * Return the Introspector for this instance
> + *
> + * @return The Introspector for this instance
> + */
> + public Introspector getIntrospector() {
> + return introspector;
> + }
> +
> + /**
> + * Returns the event handlers for the application.
> + *
> + * @return The event handlers for the application.
> + */
> + public EventCartridge getApplicationEventCartridge() {
> + return eventCartridge;
> + }
> +
> + /**
> + * Gets the application attribute for the given key
> + *
> + * @param key
> + * @return The application attribute for the given key.
> + */
> + public Object getApplicationAttribute(Object key) {
> + return applicationAttributes.get(key);
> + }
> +
> + /**
> + * Sets the application attribute for the given key
> + *
> + * @param key
> + * @param o
> + * The new application attribute.
> + * @return The old value of this attribute or null if it hasn't been set before.
> + */
> + public Object setApplicationAttribute(Object key, Object o) {
> + return applicationAttributes.put(key, o);
> + }
> +
> + /**
> + * Returns the Uberspect object for this Instance.
> + *
> + * @return The Uberspect object for this Instance.
> + */
> + public Uberspect getUberspect() {
> + return uberSpect;
> + }
> +
> + /**
> + * This method is called before a macro is rendered. This method checks whether a \
> macro call is within the allowed calling depth. If the macro call exceeds + * the \
> allowed calling depth it will throw an exception. + *
> + * @param macroName
> + * name of the macro
> + * @param templateName
> + * name of the template file containing the macro
> + * @throws MacroOverflowException
> + * if the number of macro calls exceeds the specified value
> + */
> + public void startMacroRendering(String macroName, String templateName) throws \
> MacroOverflowException { + vmFactory.startMacroRendering(macroName, templateName);
> + }
> +
> + /**
> + * This method is called after a macro rendering is finished. It cleasr all the \
> state saved in the VelociMacroFactory about this particular macro. + *
> + * @param macroName
> + * name of the macro
> + * @param templateName
> + * template name that contains the macro
> + */
> + public void endMacroRendering(String macroName, String templateName) {
> + vmFactory.endMacroRendering(macroName, templateName);
> + }
> }
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
> For additional commands, e-mail: dev-help@velocity.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
For additional commands, e-mail: dev-help@velocity.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic