Hello.

There was a discussion about running multiple instances of Velocity
Runtime
in a single VM. I needed that functionality for my Turbine-like
framework.
(Turbine's deprecation policy makes it virtually impossible to integrate
the things I developed with Turbine 2.2 in mind with any future version
of Turbine)

There is a patch enclosed that adds this capability, it  was made
against
current CVS sources.

It is fully backward compatible for applications that intialize Velocity
through app.Velocity facade class. After calling any of Velocity.init()
methods, the application may call static methods of both Velocity and
Runtime classes and everything will work as expeceted.
If an aplication wishes to use multiple Velocity engines concurrently,
it should create an instance of Runtime, initialize it using the
non-static
methods (addProperty/setProperty/clearProperty/init or init(path) or
init(properties))
and keep the reference to the created object.
Then, it should use Runtime.useRuntime() method to select an apropriate
engine
for use. All subsequent calls to the static methods of the Runtime class
from
the thread that called useRuntime() will be handled by the selected
Runtime instance.
Discarding all references to a Runtime instance makes it (and all it's
assets including
cached templates) eligible to garbage collection.

That's all. I've tested this and it works fine for me.

Many thanks to Jason,Geir and the rest of the band for making a great
product!
 
--
Rafal Krzewski
Senior Internet Developer
mailto:[EMAIL PROTECTED]
+48 22 8534830 http://e-point.pl
diff -ruN src.orig/java/org/apache/velocity/app/Velocity.java 
src/java/org/apache/velocity/app/Velocity.java
--- src.orig/java/org/apache/velocity/app/Velocity.java Fri May 18 14:01:43 2001
+++ src/java/org/apache/velocity/app/Velocity.java      Tue Jun  5 11:24:04 2001
@@ -85,34 +85,47 @@
 import org.apache.commons.collections.ExtendedProperties;
 
 /**
- * This class provides  services to the application 
+ * Provides convenient access to the Velocity engine.
+ *
+ * <p> This class provides  services to the application 
  * developer, such as :
  * <ul>
  * <li> Simple Velocity Runtime engine initialization methods.
  * <li> Functions to apply the template engine to streams and strings
  *      to allow embedding and dynamic template generation.
  * <li> Methods to access Velocimacros directly.
- * </ul>
+ * </ul></p>
  *
- * <br><br>
- * While the most common way to use Velocity is via templates, as 
+ * <p>After one of the <code>init</code> methods is called a {@link Runtime}
+ * object is created and a reference to it is stored in a class variable.
+ * The calling thread and all child threads started by it are implicitly
+ * associated with that <code>Runtime</code> Object. The <code>Runtime</code>
+ * and it's assets (cached templates etc.) stay in memory as long as the
+ * <code>ClassLoader</code> that loaded the <code>Velocity</code> class exists.
+ * </p>
+ * <p> While the most common way to use Velocity is via templates, as 
  * Velocity is a general-purpose template engine, there are other
  * uses that Velocity is well suited for, such as processing dynamically
- * created templates, or processing content streams.
+ * created templates, or processing content streams.</p>
  *
- * <br><br>
- * The methods herein were developed to allow easy access to the Velocity
+ * <p>The methods herein were developed to allow easy access to the Velocity
  * facilities without direct spelunking of the internals.  If there is
- * something you feel is necessary to add here, please, send a patch.
+ * something you feel is necessary to add here, please, send a patch.</p>
  *
  * @author <a href="mailto:[EMAIL PROTECTED]";>Geir Magnusson Jr.</a>
  * @author <a href="[EMAIL PROTECTED]">Christoph Reck</a>
  * @author <a href="[EMAIL PROTECTED]">Jason van Zyl</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Rafal Krzewski</a>
  * @version $Id: Velocity.java,v 1.18 2001/05/18 12:01:43 geirm Exp $
  */
 
 public class Velocity implements RuntimeConstants
 {
+    /** 
+     * The Runtime instance we are the proxy for.
+     */
+    private static Runtime runtime = new Runtime();
+
     /**
      *  initialize the Velocity runtime engine, using the default 
      *  properties of the Velocity distribution
@@ -122,7 +135,7 @@
     public static void init() 
         throws Exception
     {
-        Runtime.init();
+        runtime.init();
     }
 
     /**
@@ -138,7 +151,7 @@
     public static void init( String propsFilename ) 
         throws Exception
     {
-        Runtime.init(propsFilename);
+        runtime.init(propsFilename);
     }
 
     /**
@@ -152,7 +165,7 @@
     public static void init( Properties p )
         throws Exception
     {      
-        Runtime.init( p ); 
+        runtime.init( p ); 
     }
     
     /**
@@ -163,6 +176,7 @@
      */
     public static void setProperty(String key, Object value)
     {
+        runtime.useRuntime();
         Runtime.setProperty(key,value);
     }
 
@@ -234,6 +248,7 @@
      */
     public static Object getProperty( String key )
     {
+        runtime.useRuntime();
         return Runtime.getProperty( key );
     }
 
@@ -321,6 +336,8 @@
                                     String logTag, Reader reader )
         throws ParseErrorException, MethodInvocationException, IOException
     {
+        runtime.useRuntime();
+
         SimpleNode nodeTree = null;
         
         try
@@ -389,6 +406,8 @@
                                               String params[], Context context, 
                                               Writer writer )
     {
+        runtime.useRuntime();
+
         /*
          *  check parms
          */
@@ -521,6 +540,8 @@
                                       Context context, Writer writer )
         throws ResourceNotFoundException, ParseErrorException, 
MethodInvocationException, Exception
     {
+        runtime.useRuntime();
+
         Template template = Runtime.getTemplate(templateName, encoding);
         
         if ( template == null )
@@ -551,6 +572,8 @@
     public static Template getTemplate(String name)
         throws ResourceNotFoundException, ParseErrorException, Exception
     {
+        runtime.useRuntime();
+
         return Runtime.getTemplate( name );
     }
 
@@ -592,6 +615,8 @@
      */
     public static boolean templateExists( String templateName )
     {
+        runtime.getRuntime();
+
         return (Runtime.getLoaderNameForResource(templateName) != null);
     }
 } 
diff -ruN src.orig/java/org/apache/velocity/context/VMContext.java 
src/java/org/apache/velocity/context/VMContext.java
--- src.orig/java/org/apache/velocity/context/VMContext.java    Sun May 20 21:44:35 
2001
+++ src/java/org/apache/velocity/context/VMContext.java Tue Jun  5 15:29:57 2001
@@ -91,7 +91,7 @@
     InternalContextAdapter wrappedContext = null;
 
     /** support for local context scope feature, where all references are local */
-    static boolean localcontextscope = 
+    boolean localcontextscope = 
         Runtime.getBoolean(Runtime.VM_CONTEXT_LOCALSCOPE, true);
 
     /**
diff -ruN src.orig/java/org/apache/velocity/runtime/Runtime.java 
src/java/org/apache/velocity/runtime/Runtime.java
--- src.orig/java/org/apache/velocity/runtime/Runtime.java      Fri May 11 06:00:58 
2001
+++ src/java/org/apache/velocity/runtime/Runtime.java   Tue Jun  5 15:33:37 2001
@@ -62,7 +62,6 @@
 
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Map;
 import java.util.Hashtable;
 import java.util.Properties;
 import java.util.Stack;
@@ -70,6 +69,8 @@
 import java.util.TreeMap;
 import java.util.Vector;
 
+import java.lang.ref.WeakReference;
+
 import org.apache.log.Logger;
 
 import org.apache.velocity.Template;
@@ -97,84 +98,79 @@
 import org.apache.commons.collections.ExtendedProperties;
 
 /**
- * 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.
+ * This is the Runtime system for Velocity. 
  *
- * So in the case of Velocity cooperating with Turbine
- * the code might look something like the following:
+ * <p> 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 within order to get Velocity to perform.</p>
  *
- * <pre>
- * Runtime.setProperty(Runtime.FILE_RESOURCE_LOADER_PATH, templatePath);
- * Runtime.setProperty(Runtime.RUNTIME_LOG, pathToVelocityLog);
- * Runtime.init();
- * </pre>
+ * <p>This class allows advanced applications to create multiple Velocity
+ * engines at runtime, and discard them when no longer neccessary, and switch
+ * the engine used in the current execution context.</p>
  *
- * <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
- * -----------------------------------------------------------------------
- * Runtime.init()
+ * <p>After an instance of <code>Runtime</code> is created it should be
+ * initialized using one of the <code>init</code> methods. A conservative set
+ * of default settings is always loaded before the actual configuration.
+ * <code>setProperty</code>, <code>addProperty</code> and
+ * <code>clearProperty</code> methods can be used to manipulate settings
+ * programatically, but only before <code>init</code> method is called. The
+ * application should keep the reference to the Runtime object created all the
+ * time that the engine is used. {@link #useRuntime()} method is used for
+ * switching between the available engines.</p>
  * 
- * If Runtime.init() is called by itself the Runtime will
- * initialize with a set of default values.
- * -----------------------------------------------------------------------
- * Runtime.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
- * default property.
- * -----------------------------------------------------------------------
- * </pre>
+ * <p>In the simple case when only one Velocity engine is used by the
+ * application throughout it's whole lifetime, {@link 
+ * org.apache.velocity.app.Velocity} class can be used to simplify the task of
+ * initializing the Runtime.</p>
  *
  * @author <a href="mailto:[EMAIL PROTECTED]";>Jason van Zyl</a>
  * @author <a href="mailto:[EMAIL PROTECTED]";>Jeff Bowden</a>
  * @author <a href="mailto:[EMAIL PROTECTED]";>Geir Magusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Rafal Krzewski</a>
  * @version $Id: Runtime.java,v 1.110 2001/05/11 04:00:58 geirm Exp $
  */
 public class Runtime implements RuntimeConstants
 {    
+    /** 
+     * The mapping between Velocity Runtime objects and application's Threads. 
+     */
+    private static InheritableThreadLocal threadRuntime = new 
+InheritableThreadLocal();
+
     /**
      *  VelocimacroFactory object to manage VMs
      */
-    private static VelocimacroFactory vmFactory = new VelocimacroFactory();
+    private VelocimacroFactory vmFactory = new VelocimacroFactory();
+
+    /**
+     * ResourceManager to manage templates & static content
+     */
+    private ResourceManager resourceManager = new ResourceManager();
 
     /** 
      * The Runtime logger.
      */
-    private static LogSystem logSystem = null;
+    private LogSystem logSystem = null;
 
     /** 
      * The caching system used by the Velocity Runtime 
      */
-    private static Hashtable globalCache;
+    private Hashtable[] globalCache;
     
     /** 
      * The Runtime parser pool 
      */
-    private static SimplePool parserPool;
+    private SimplePool parserPool;
     
     /** 
      * Indicate whether the Runtime has been fully initialized.
      */
-    private static boolean initialized;
+    private boolean initialized;
 
     /**
      * These are the properties that are laid down over top
      * of the default properties when requested.
      */
-    private static ExtendedProperties overridingProperties = null;
+    private ExtendedProperties overridingProperties = null;
 
     /**
      * The logging systems initialization may be defered if
@@ -183,7 +179,7 @@
      * logger is instantiated. They will be stored here
      * until the logger is alive.
      */
-    private static Vector pendingMessages = new Vector();
+    private Vector pendingMessages = new Vector();
 
     /**
      * This is a hashtable of initialized directives.
@@ -192,7 +188,7 @@
      * property file. This hashtable is passed
      * to each parser that is created.
      */
-    private static Hashtable runtimeDirectives;
+    private Hashtable runtimeDirectives;
 
     /**
      * Object that houses the configuration options for
@@ -208,7 +204,74 @@
      * And a configuration is a lot more convenient to deal
      * with then conventional properties objects, or Maps.
      */
-    private static ExtendedProperties configuration = new ExtendedProperties();
+    private ExtendedProperties configuration = new ExtendedProperties();
+
+    /**
+     * Associates this instance of Velocity Runtime with the calling Thread.
+     *
+     * <p> The method creates a weak refernece to this object and puts into
+     * an InheritableThreadLocal object. This is done so, to allow the Runtime
+     * object to be relcaimed when only thread local variables refer to it.
+     * Otherwise, the Runtime object might ``stick'' to the threads sitting
+     * in the Servlet runner's (or other) thread pool and consume memory after
+     * the application that actually used it is terminated and discarded.
+     * The other solution of this problem was to request that those users
+     * that use Velocity with multiple, pooled threads to call releaseRuntime() 
+     * whenever the thread of control leaves their code. That would be really
+     * error prone... </p>
+     * <p> As a consequence of this, if you are using the Runtime class directly
+     * you need to hold an explicit reference to the instance that you created.
+     * When you discard this reference (for exaple when your Servlet class gets
+     * unloaded) Velocity Runtime will become reclaimable to the GC. </p>
+     */
+    public void useRuntime()
+    {
+        threadRuntime.set(new WeakReference(this));
+    }
+
+    /**
+     * Unassociates the calling thread with the Velocity Runtime.
+     *
+     * <p> You may call this method to explicitly unassociate your thread
+     * with any Velocity Runtime it might have been associated with. 
+     * A subsequent call to {@link #getRuntime()} will result in a
+     * RuntimeException being thrown, unless you call {@link #useRuntime()}
+     * on some Runtime object before. </p>
+     */
+    public void releaseRuntime()
+    {
+        threadRuntime.set(null);
+    }
+
+    /**
+     * Returns the instance of Velocity Runtime associated with the calling 
+     * Thread.
+     *
+     * @return a Velocity Runtime
+     */
+    public static Runtime getRuntime()
+    {
+        try
+        {
+            Runtime runtime = (Runtime)((WeakReference)
+                                        threadRuntime.get()).get();
+            // throw NPE if runtime is null
+            runtime.hashCode();
+            return runtime;
+        }
+        catch(NullPointerException e)
+        {
+            throw new RuntimeException(
+                "Velocity Runtime is not available.\nThis means that either "+
+                "you forgot to call useRuntime() on some\n Runtime instance "+
+                "to associate it with your thread, or the \nreference to the "+
+                "Runtime object you have created and initialzed\nwas lost "+
+                "and the object got GC'ed, or you forgot to intitialize\n "+
+                "the Runtime. If you any don't understand any of the above, "+
+                "use \norg.apache.velocity.app.Velocity class to initialize "+
+                "Velocity.\n");
+        }
+    }
 
     /*
      * This is the primary initialization method in the Velocity
@@ -224,16 +287,18 @@
      *   <li>Velocimacro System</li>
      * </ul>
      */
-    public synchronized static void init()
+    public synchronized void init()
         throws Exception
     {
         if (initialized == false)
         {
             try
             {
+                useRuntime();
+
                 initializeProperties();
                 initializeLogger();
-                ResourceManager.initialize();
+                resourceManager.initialize();
                 initializeDirectives();
                 initializeParserPool();
                 initializeGlobalCache();
@@ -261,7 +326,7 @@
      * The properties file may be in the file system proper,
      * or the properties file may be in the classpath.
      */
-    private static void setDefaultProperties()
+    private void setDefaultProperties()
     {
         ClassLoader classLoader = Runtime.class.getClassLoader();
         try
@@ -289,12 +354,14 @@
      */
     public static void setProperty(String key, Object value)
     {
-        if (overridingProperties == null)
+        Runtime runtime = getRuntime();
+        
+        if (runtime.overridingProperties == null)
         {
-            overridingProperties = new ExtendedProperties();
+            runtime.overridingProperties = new ExtendedProperties();
         }            
             
-        overridingProperties.setProperty( key, value );
+        runtime.overridingProperties.setProperty( key, value );
     }        
 
     /**
@@ -309,13 +376,15 @@
      */
     public static void setConfiguration( ExtendedProperties configuration)
     {
-        if (overridingProperties == null)
+        Runtime runtime = getRuntime();
+
+        if (runtime.overridingProperties == null)
         {
-            overridingProperties = configuration;
+            runtime.overridingProperties = configuration;
         }
         else
         {
-            overridingProperties.combine(configuration);
+            runtime.overridingProperties.combine(configuration);
         }
     }
 
@@ -340,12 +409,14 @@
      */
     public static void addProperty(String key, Object value)
     {
-        if (overridingProperties == null)
+        Runtime runtime = getRuntime();
+
+        if (runtime.overridingProperties == null)
         {
-            overridingProperties = new ExtendedProperties();
+            runtime.overridingProperties = new ExtendedProperties();
         }            
             
-        overridingProperties.addProperty( key, value );
+        runtime.overridingProperties.addProperty( key, value );
     }
     
     /**
@@ -356,9 +427,11 @@
      */
     public static void clearProperty(String key)
     {
-        if (overridingProperties != null)
+        Runtime runtime = getRuntime();
+
+        if (runtime.overridingProperties != null)
         {
-            overridingProperties.clearProperty(key);
+            runtime.overridingProperties.clearProperty(key);
         }            
     }
     
@@ -371,7 +444,7 @@
      */
     public static Object getProperty( String key )
     {
-        return configuration.getProperty( key );
+        return getRuntime().configuration.getProperty( key );
     }
 
     /**
@@ -382,7 +455,7 @@
      * gives a much greater chance of having a
      * working system.
      */
-    private static void initializeProperties()
+    private void initializeProperties()
     {
         /* 
          * Always lay down the default properties first as
@@ -405,7 +478,7 @@
      *
      * @param Properties
      */
-    public static void init(Properties p) throws Exception
+    public void init(Properties p) throws Exception
     {
         overridingProperties = ExtendedProperties.convertProperties(p);
         init();
@@ -417,7 +490,7 @@
      *
      * @param Properties
      */
-    public static void init(String configurationFile)
+    public void init(String configurationFile)
         throws Exception
     {
         overridingProperties = new ExtendedProperties(configurationFile);
@@ -429,7 +502,7 @@
      *
      * @throws Exception
      */
-    private static void initializeLogger() throws Exception
+    private void initializeLogger() throws Exception
     { 
         /*
          * Initialize the logger. We will eventually move all
@@ -449,7 +522,7 @@
     /*
      * Dump the pending messages
      */
-    private static void dumpPendingMessages()
+    private void dumpPendingMessages()
     {
         if ( !pendingMessages.isEmpty())
         {
@@ -474,7 +547,7 @@
      *
      * @throws Exception
      */
-    private static void initializeDirectives() throws Exception
+    private void initializeDirectives() throws Exception
     {
         /*
          * Initialize the runtime directive table.
@@ -541,7 +614,7 @@
      * Initializes the Velocity parser pool.
      * This still needs to be implemented.
      */
-    private static void initializeParserPool()
+    private void initializeParserPool()
     {
         int numParsers = getInt( PARSER_POOL_SIZE, NUMBER_OF_PARSERS);
 
@@ -563,7 +636,7 @@
     public static Parser createNewParser()
     {
         Parser parser = new Parser();
-        parser.setDirectives(runtimeDirectives);
+        parser.setDirectives(getRuntime().runtimeDirectives);
         return parser;
     }
 
@@ -585,6 +658,7 @@
     public static SimpleNode parse( Reader reader, String templateName )
         throws ParseException
     {
+        SimplePool parserPool = getRuntime().parserPool;
         SimpleNode ast = null;
         Parser parser = (Parser) parserPool.get();
         boolean madeNew = false;
@@ -643,11 +717,27 @@
      * directive. Who knows what else we'll find to
      * cache.
      */
-    private static void initializeGlobalCache()
+    private void initializeGlobalCache()
     {
-        globalCache = new Hashtable();
+        globalCache = new Hashtable[2];
+        globalCache[GLOBAL_CACHE_RESOURCES] = new Hashtable();
+        globalCache[GLOBAL_CACHE_INTROSPECTION] = new Hashtable();
     }
-    
+
+    /**
+     * Returns the specified global cache facility.
+     *
+     * <p> The returned objects to not enforce any synchronization policy. This
+     * is left to the application. </p>
+     *
+     * @param cacheId the identifier of cache facility
+     * @return a global cache
+     */
+    public static Hashtable getGlobalCache(int cacheId)
+    {
+        return getRuntime().globalCache[cacheId];
+    }
+
     /**
      * Returns a <code>Template</code> from the resource manager.
      * This method assumes that the character encoding of the 
@@ -683,7 +773,7 @@
     public static Template getTemplate(String name, String  encoding)
         throws ResourceNotFoundException, ParseErrorException, Exception
     {
-        return (Template) ResourceManager
+        return (Template) getRuntime().resourceManager
             .getResource(name,ResourceManager.RESOURCE_TEMPLATE, encoding);
     }
 
@@ -721,7 +811,7 @@
     public static ContentResource getContent( String name, String encoding )
         throws ResourceNotFoundException, ParseErrorException, Exception
     {
-        return (ContentResource) ResourceManager
+        return (ContentResource) getRuntime().resourceManager
             .getResource(name,ResourceManager.RESOURCE_CONTENT, encoding );
     }
 
@@ -737,7 +827,8 @@
      */
     public static String getLoaderNameForResource( String resourceName )
     {
-        return ResourceManager.getLoaderNameForResource( resourceName );
+        return getRuntime().resourceManager.
+            getLoaderNameForResource( resourceName );
     }
 
     /**
@@ -748,7 +839,7 @@
      */
     private static boolean showStackTrace()
     {
-        if (configuration.isInitialized())
+        if (getRuntime().configuration.isInitialized())
         {
             return getBoolean(RUNTIME_LOG_WARN_STACKTRACE, false);
         }            
@@ -803,20 +894,21 @@
             out += message.toString();    
         }            
 
+        Runtime runtime = getRuntime();
         /*
          *  now, if we have a log system, log it
          *  otherwise, queue it up for later
          */
-        if (logSystem != null)
+        if (runtime.logSystem != null)
         {
-            logSystem.logVelocityMessage( level, out);
+            runtime.logSystem.logVelocityMessage( level, out);
         }
         else
         {
             Object[] data = new Object[2];
             data[0] = new Integer(level);
             data[1] = out;
-            pendingMessages.addElement(data);
+            runtime.pendingMessages.addElement(data);
         }
     }
 
@@ -871,7 +963,7 @@
      */
     public static String getString( String key, String defaultValue)
     {
-        return configuration.getString(key, defaultValue);
+        return getRuntime().configuration.getString(key, defaultValue);
     }
 
     /**
@@ -883,7 +975,7 @@
      */
     public static Directive getVelocimacro( String vmName, String templateName  )
     {
-        return vmFactory.getVelocimacro( vmName, templateName );
+        return getRuntime().vmFactory.getVelocimacro( vmName, templateName );
     }
 
    /**
@@ -901,7 +993,7 @@
                                           String argArray[], 
                                           String sourceTemplate )
     {    
-        return vmFactory.addVelocimacro(  name, macro,  argArray,  sourceTemplate );
+        return getRuntime().vmFactory.addVelocimacro(  name, macro,  argArray,  
+sourceTemplate );
     }
  
     /**
@@ -912,7 +1004,7 @@
      */
     public static boolean isVelocimacro( String vmName, String templateName )
     {
-        return vmFactory.isVelocimacro( vmName, templateName );
+        return getRuntime().vmFactory.isVelocimacro( vmName, templateName );
     }
 
     /**
@@ -921,7 +1013,7 @@
      */
     public static boolean dumpVMNamespace( String namespace )
     {
-        return vmFactory.dumpVMNamespace( namespace );
+        return getRuntime().vmFactory.dumpVMNamespace( namespace );
     }
 
     /* --------------------------------------------------------------------
@@ -943,7 +1035,7 @@
      */
     public static String getString(String key)
     {
-        return configuration.getString( key );
+        return getRuntime().configuration.getString( key );
     }
 
     /**
@@ -954,7 +1046,7 @@
      */
     public static int getInt( String key )
     {
-        return configuration.getInt( key );
+        return getRuntime().configuration.getInt( key );
     }
 
     /**
@@ -966,7 +1058,7 @@
      */
     public static int getInt( String key, int defaultValue )
     {
-        return configuration.getInt( key, defaultValue );
+        return getRuntime().configuration.getInt( key, defaultValue );
     }
 
     /**
@@ -978,7 +1070,7 @@
      */
     public static boolean getBoolean( String key, boolean def )
     {
-        return configuration.getBoolean( key, def );
+        return getRuntime().configuration.getBoolean( key, def );
     }
 
     /**
@@ -989,6 +1081,6 @@
      */
     public static ExtendedProperties getConfiguration()
     {
-        return configuration;
+        return getRuntime().configuration;
     }        
 }
diff -ruN src.orig/java/org/apache/velocity/runtime/RuntimeConstants.java 
src/java/org/apache/velocity/runtime/RuntimeConstants.java
--- src.orig/java/org/apache/velocity/runtime/RuntimeConstants.java     Sun May 20 
23:40:40 2001
+++ src/java/org/apache/velocity/runtime/RuntimeConstants.java  Tue Jun  5 10:42:04 
+2001
@@ -326,6 +326,22 @@
         "velocimacro.context.localscope";
 
     /*
+     *-----------------------------------------------------------------------
+     * G L O B A L  C A C H E 
+     *-----------------------------------------------------------------------
+     */
+
+    /** 
+     * Cache indentifier for templates and static content. 
+     */
+    public static final int GLOBAL_CACHE_RESOURCES = 0;
+
+    /** 
+     * Cache identifier for introspection class maps 
+     */
+    public static final int GLOBAL_CACHE_INTROSPECTION = 1;
+
+    /*
      * ----------------------------------------------------------------------
      * G E N E R A L  R U N T I M E  C O N F I G U R A T I O N
      * ----------------------------------------------------------------------
diff -ruN src.orig/java/org/apache/velocity/runtime/directive/Foreach.java 
src/java/org/apache/velocity/runtime/directive/Foreach.java
--- src.orig/java/org/apache/velocity/runtime/directive/Foreach.java    Sun Apr  8 
23:14:21 2001
+++ src/java/org/apache/velocity/runtime/directive/Foreach.java Tue Jun  5 10:42:04 
+2001
@@ -142,13 +142,13 @@
      * the counter value into the context. Right
      * now the default is $velocityCount.
      */
-    private final static String COUNTER_NAME =
+    private final String COUNTER_NAME =
         Runtime.getString(Runtime.COUNTER_NAME);
     
     /**
      * What value to start the loop counter at.
      */
-    private final static int COUNTER_INITIAL_VALUE =
+    private final int COUNTER_INITIAL_VALUE =
         Runtime.getInt(Runtime.COUNTER_INITIAL_VALUE);
 
     /**
diff -ruN src.orig/java/org/apache/velocity/runtime/directive/Parse.java 
src/java/org/apache/velocity/runtime/directive/Parse.java
--- src.orig/java/org/apache/velocity/runtime/directive/Parse.java      Mon Apr 23 
01:08:42 2001
+++ src/java/org/apache/velocity/runtime/directive/Parse.java   Tue Jun  5 10:42:04 
+2001
@@ -93,6 +93,12 @@
     private boolean ready = false;
 
     /**
+     * Parse depth limit.
+     */
+    private final int maxDepth = 
+        Runtime.getInt(Runtime.PARSE_DIRECTIVE_MAXDEPTH, 20);
+
+    /**
      * Return name of this directive.
      */
     public String getName()
@@ -149,8 +155,7 @@
 
         Object[] templateStack = context.getTemplateNameStack();
 
-        if ( templateStack.length >= 
-                Runtime.getInt(Runtime.PARSE_DIRECTIVE_MAXDEPTH, 20) )
+        if ( templateStack.length >= maxDepth )
         {
             StringBuffer path = new StringBuffer();
 
diff -ruN src.orig/java/org/apache/velocity/runtime/parser/node/ASTReference.java 
src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
--- src.orig/java/org/apache/velocity/runtime/parser/node/ASTReference.java     Sun 
May 20 21:50:06 2001
+++ src/java/org/apache/velocity/runtime/parser/node/ASTReference.java  Tue Jun  5 
+12:02:53 2001
@@ -103,6 +103,8 @@
 
     private int numChildren = 0;
 
+    private boolean logInvalid = true;
+
     public ASTReference(int id)
     {
         super(id);
@@ -128,6 +130,8 @@
 
         super.init( context, data );
 
+        logInvalid = Runtime.getBoolean( 
+RuntimeConstants.RUNTIME_LOG_REFERENCE_LOG_INVALID, true);
+
         /*
          *  the only thing we can do in init() is getRoot()
          *  as that is template based, not context based,
@@ -282,9 +286,7 @@
             writer.write( prefix );
             writer.write( nullString );
             
-            if (referenceType != QUIET_REFERENCE 
-                && Runtime.getBoolean( 
-                                      
RuntimeConstants.RUNTIME_LOG_REFERENCE_LOG_INVALID, true) )
+            if (referenceType != QUIET_REFERENCE && logInvalid)
             {
                 Runtime.warn(new ReferenceException("reference : template = " 
                                                     + 
context.getCurrentTemplateName(), this));
diff -ruN src.orig/java/org/apache/velocity/runtime/resource/ResourceManager.java 
src/java/org/apache/velocity/runtime/resource/ResourceManager.java
--- src.orig/java/org/apache/velocity/runtime/resource/ResourceManager.java     Sun 
May 20 23:40:40 2001
+++ src/java/org/apache/velocity/runtime/resource/ResourceManager.java  Tue Jun  5 
+14:32:02 2001
@@ -101,16 +101,10 @@
     private static final String RESOURCE_LOADER_IDENTIFIER = 
"_RESOURCE_LOADER_IDENTIFIER_";
 
     /**
-     * Hashtable used to store templates that have been
-     * processed. Our simple caching mechanism.
-     */
-    private static Hashtable globalCache = new Hashtable();
-    
-    /**
      * The List of templateLoaders that the Runtime will
      * use to locate the InputStream source of a template.
      */
-    private static ArrayList resourceLoaders = new ArrayList();
+    private ArrayList resourceLoaders = new ArrayList();
     
     /**
      * This is a list of the template input stream source
@@ -120,7 +114,7 @@
      *
      * <loader-id>.resource.loader.<property> = <value>
      */
-    private static ArrayList sourceInitializerList = new ArrayList();
+    private ArrayList sourceInitializerList = new ArrayList();
     
     /**
      * This is a map of public name of the template
@@ -132,7 +126,7 @@
      * change the resource.path property for the
      * file template stream source.
      */
-    private static Hashtable sourceInitializerMap = new Hashtable();
+    private Hashtable sourceInitializerMap = new Hashtable();
 
     /**
      * Each loader needs a configuration object for
@@ -140,20 +134,20 @@
      * or not the configuration objects have been created
      * for the resource loaders.
      */
-    private static boolean resourceLoaderInitializersActive = false;
+    private boolean resourceLoaderInitializersActive = false;
 
     /**
      *  switch to turn off log notice when a resource is found for
      *  the first time.
      */
-    private static boolean logWhenFound = true;
+    private boolean logWhenFound = true;
     
     /**
      * Initialize the ResourceManager. It is assumed
      * that assembleSourceInitializers() has been
      * called before this is run.
      */
-    public static void initialize() throws Exception
+    public void initialize() throws Exception
     {
         ResourceLoader resourceLoader;
         
@@ -194,7 +188,7 @@
      * will be passed in when initializing the
      * the template loader.
      */
-    private static void assembleResourceLoaderInitializers()
+    private void assembleResourceLoaderInitializers()
     {
         if (resourceLoaderInitializersActive)
         {
@@ -253,7 +247,7 @@
      *          to syntax (or other) error.
      * @throws Exception if a problem in parse
      */
-    public static Resource getResource(String resourceName, int resourceType, String 
encoding )
+    public Resource getResource(String resourceName, int resourceType, String 
+encoding )
         throws ResourceNotFoundException, ParseErrorException, Exception
     {        
         /* 
@@ -262,7 +256,10 @@
          * the cached version of the resource. If not we
          * will load it.
          */
-        
+
+        Map globalCache = Runtime.
+            getGlobalCache(Runtime.GLOBAL_CACHE_RESOURCES);
+
         Resource resource = (Resource) globalCache.get(resourceName);
 
         if( resource != null)
@@ -485,7 +482,7 @@
      *  {@link #getResource(String resourceName, int resourceType, 
      *          String encoding )}
      */
-    public static Resource getResource(String resourceName, int resourceType  )
+    public Resource getResource(String resourceName, int resourceType  )
         throws ResourceNotFoundException, ParseErrorException, Exception
     {  
         return getResource( resourceName, resourceType, Runtime.ENCODING_DEFAULT);
@@ -500,7 +497,7 @@
      *  @param resourceName Name of template or content resource
      *  @return class name of loader than can provide it
      */
-    public static String getLoaderNameForResource(String resourceName )
+    public String getLoaderNameForResource(String resourceName )
     {
         ResourceLoader resourceLoader = null;
        
diff -ruN src.orig/java/org/apache/velocity/test/view/TemplateNodeView.java 
src/java/org/apache/velocity/test/view/TemplateNodeView.java
--- src.orig/java/org/apache/velocity/test/view/TemplateNodeView.java   Sun Apr 22 
20:22:30 2001
+++ src/java/org/apache/velocity/test/view/TemplateNodeView.java        Tue Jun  5 
+12:07:28 2001
@@ -60,6 +60,7 @@
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 
+import org.apache.velocity.app.Velocity;
 import org.apache.velocity.runtime.Runtime;
 
 import org.apache.velocity.runtime.visitor.NodeViewMode;
@@ -95,7 +96,7 @@
     {
         try
         {
-            Runtime.init("velocity.properties");
+            Velocity.init("velocity.properties");
 
             InputStreamReader isr = new InputStreamReader(
                                        new FileInputStream(template),
diff -ruN src.orig/java/org/apache/velocity/util/introspection/Introspector.java 
src/java/org/apache/velocity/util/introspection/Introspector.java
--- src.orig/java/org/apache/velocity/util/introspection/Introspector.java      Mon 
Mar  5 12:48:49 2001
+++ src/java/org/apache/velocity/util/introspection/Introspector.java   Tue Jun  5 
+15:25:59 2001
@@ -59,6 +59,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
+import org.apache.velocity.runtime.Runtime;
 import org.apache.velocity.util.StringUtils;
 
 /**
@@ -89,8 +90,6 @@
  */
 public class Introspector
 {
-    private static Hashtable classMethodMaps = new Hashtable();
-
     public static Method getMethod(Class c, String name, Object[] params)
         throws Exception
     {
@@ -100,12 +99,17 @@
                 "Introspector.getMethod(): Class method key was null: " + name );
         }                
 
+        Hashtable classMethodMaps = Runtime.
+            getGlobalCache(Runtime.GLOBAL_CACHE_INTROSPECTION);
+
+        ClassMap map = (ClassMap)classMethodMaps.get(c);
+
         /* 
          * If this is the first time seeing this class
          * then create a method map for this class and
          * store it in Hashtable of class method maps.
          */
-        if (!classMethodMaps.containsKey(c))
+        if (map == null)
         {
             /*
              * Lots of threads might be whizzing through here,
@@ -130,20 +134,7 @@
                 }
             }
         }
-        return findMethod(c, name, params);
-    }
-
-    /**
-     * Find a method in a class.
-     *
-     * @param Class class to search
-     * @param String name of method
-     * @param Object[] parameters
-     */
-    private static Method findMethod(Class c, String name, Object[] params)
-    {
-        ClassMap classMethodMap = (ClassMap) classMethodMaps.get(c);
-        return classMethodMap.findMethod(name, params);
+        return map.findMethod(name, params);
     }
 
     /**

Reply via email to