<commit_before>package org.apache.velocity.runtime;

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact <EMAIL>.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.io.InputStream;
import java.io.File;
import java.io.IOException;
import java.io.Reader;

import java.util.Map;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;
import java.util.HashMap;

import org.apache.velocity.Template;

import org.apache.velocity.runtime.log.LogManager;
import org.apache.velocity.runtime.log.LogSystem;
import org.apache.velocity.runtime.log.PrimordialLogSystem;
import org.apache.velocity.runtime.log.NullLogSystem;

import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.node.SimpleNode;

import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.VelocimacroFactory;

import org.apache.velocity.runtime.resource.ContentResource;
import org.apache.velocity.runtime.resource.ResourceManager;

import org.apache.velocity.util.SimplePool;
import org.apache.velocity.util.StringUtils;

import org.apache.velocity.util.introspection.Introspector;
import org.apache.velocity.util.introspection.Uberspect;
import org.apache.velocity.util.introspection.UberspectLoggable;

import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;

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.
 *
 * 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);
 * 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
 * -----------------------------------------------------------------------
 * init()
 * 
 * If init() is called by itself the RuntimeInstance will initialize
 * 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
 * default property.
 * -----------------------------------------------------------------------
 * </pre>
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME> Jr.</a>
 * @version $Id: RuntimeInstance.java,v 1.18 2003/05/04 17:14:36 geirm Exp $
 */
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, we dump
     *  all messages out of the primordial one into the real one.
     */
    private  LogSystem logSystem = new PrimordialLogSystem();

    /** 
     * The Runtime parser pool 
     */
    private  SimplePool parserPool;
    
    /** 
     * Indicate whether the Runtime has been fully initialized.
     */
    private  boolean initialized;

    /**
     * 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;

    /**
     * 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;

    /*
     *  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;


    private Uberspect uberSpect;

    public RuntimeInstance()
    {
        /*
         *  create a VM factory, resource manager
         *  and introspector
         */

        vmFactory = new VelocimacroFactory( this );

        /*
         *  make a new introspector and initialize it
         */
         
        introspector = new Introspector( this );

        /*
         * and a store for the application attributes
         */

        applicationAttributes = new HashMap();
    }

    /*
     * 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>Parser Pool</li>
     *   <li>Global Cache</li>
     *   <li>Static Content Include System</li>
     *   <li>Velocimacro System</li>
     * </ul>
     */
    public synchronized void init()
        throws Exception
    {
        if (initialized == false)
        {
            info("************************************************************** ");
            info("Starting Jakarta Velocity v@version@");
            info("RuntimeInstance initializing.");
            initializeProperties();
            initializeLogger();
            initializeResourceManager();
            initializeDirectives();
            initializeParserPool();

            initializeIntrospection();
            /*
             *  initialize the VM Factory.  It will use the properties 
             * accessable from Runtime, so keep this here at the end.
             */
            vmFactory.initVelocimacro();

            info("Velocity successfully started.");
            
            initialized = true;
        }
    }


    /**
     *  Gets the classname for the Uberspect introspection package and
     *  instantiates an instance.
     */
    private void initializeIntrospection()
        throws Exception
    {
        String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);

        if (rm != null && rm.length() > 0)
        {
            Object o = null;

            try
            {
               o = Class.forName(rm).newInstance();
            }
            catch (ClassNotFoundException cnfe)
            {
                String err = "The specified class for Uberspect ("
                    + rm
                    + ") does not exist (or is not accessible to the current classlaoder.";
                 error(err);
                 throw new Exception(err);
            }

            if (!(o instanceof Uberspect))
            {
                String err = "The specified class for Uberspect ("
                    + rm
                    + ") does not implement org.apache.velocity.util.introspector.Uberspect."
                    + " Velocity not initialized correctly.";

                error(err);
                throw new Exception(err);
            }

            uberSpect = (Uberspect) o;

            if (uberSpect instanceof UberspectLoggable)
            {
                ((UberspectLoggable) uberSpect).setRuntimeLogger(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.";

            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()
    {
        ClassLoader classLoader = this.getClass().getClassLoader();

        try
        {
            InputStream inputStream = classLoader
                .getResourceAsStream( DEFAULT_RUNTIME_PROPERTIES );
            
            configuration.load( inputStream );
            
            info ("Default Properties File: " + 
                new File(DEFAULT_RUNTIME_PROPERTIES).getPath());
        }
        catch (IOException ioe)
        {
            System.err.println("Cannot get Velocity Runtime default properties!");
        }
    }

    /**
     * Allows an external system to set a property in
     * the Velocity Runtime.
     *
     * @param String property key
     * @param String property value
     */
    public void setProperty(String key, Object value)
    {
        if (overridingProperties == null)
        {
            overridingProperties = new ExtendedProperties();
        }            
            
        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 ExtendedProperties 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 String key
     * @param String value
     */
    public void addProperty(String key, Object value)
    {
        if (overridingProperties == null)
        {
            overridingProperties = new ExtendedProperties();
        }            
            
        overridingProperties.addProperty( key, value );
    }
    
    /**
     * Clear the values pertaining to a particular
     * property.
     *
     * @param String 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
     */
    public Object getProperty( String key )
    {
        return configuration.getProperty( 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();
        }            
    
        if( overridingProperties != null)
        {        
            configuration.combine(overridingProperties);
        }
    }
    
    /**
     * Initialize the Velocity Runtime with a Properties
     * object.
     *
     * @param Properties
     */
    public void init(Properties p) throws Exception
    {
        overridingProperties = ExtendedProperties.convertProperties(p);
        init();
    }
    
    /**
     * Initialize the Velocity Runtime with the name of
     * ExtendedProperties object.
     *
     * @param Properties
     */
    public void init(String configurationFile)
        throws Exception
    {
        overridingProperties = new ExtendedProperties(configurationFile);
        init();
    }

    private void initializeResourceManager()
        throws Exception
    {
        /*
         * Which resource manager?
         */
         
        String rm = getString( RuntimeConstants.RESOURCE_MANAGER_CLASS );

        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
             */
            
            Object o = null;
            
            try
            {
               o = Class.forName( rm ).newInstance();
            }
            catch (ClassNotFoundException cnfe )
            {
                String err = "The specified class for Resourcemanager ("
                    + rm    
                    + ") does not exist (or is not accessible to the current classlaoder.";
                 error( err );
                 throw new Exception( err );
            }
            
            if (!(o instanceof ResourceManager) )
            {
                String err = "The specified class for ResourceManager ("
                    + rm 
                    + ") does not implement org.apache.runtime.resource.ResourceManager."
                    + " Velocity not initialized correctly.";
                    
                error( err);
                throw new Exception(err);
            }

            resourceManager = (ResourceManager) o;
            
            resourceManager.initialize( this );        
         }
         else
         {
            /*
             *  someone screwed up.  Lets not fool around...
             */
             
            String err = "It appears that no class was specified as the"
            + " ResourceManager.  Please ensure that all configuration"
            + " information is correct.";
            
            error( err);
            throw new Exception( err );
        }                            
    }
    
    /**
     * Initialize the Velocity logging system.
     *
     * @throws Exception
     */
    private void initializeLogger() throws Exception
    { 
        /*
         * Initialize the logger. We will eventually move all
         * logging into the logging manager.
         */
        if (logSystem instanceof PrimordialLogSystem )
        {
            PrimordialLogSystem pls = (PrimordialLogSystem) logSystem;
            logSystem = LogManager.createLogSystem( this );
            
            /*
             * in the event of failure, lets do something to let it 
             * limp along.
             */
             
             if (logSystem == null)
             {
                logSystem = new NullLogSystem();
             }
             else
             {
                pls.dumpLogMessages( logSystem );
             }
        }
   }

    
    /**
     * 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();
        
        Properties directiveProperties = new Properties();
        
        /*
         * Grab the properties file with the list of directives
         * that we should initialize.
         */

        //        ClassLoader classLoader = Runtime.class.getClassLoader();
        ClassLoader classLoader = this.getClass().getClassLoader();

        InputStream inputStream = classLoader
            .getResourceAsStream(DEFAULT_RUNTIME_DIRECTIVES);
    
        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!");
        
        directiveProperties.load(inputStream);
        <commit_msg>* src/java/org/apache/velocity/runtime/RuntimeInstance.java   setDefaultProperties(), initializeDirectives(): Use   Class.getResourceAsStream() rather than   ClassLoader.getResourceAsStream() to avoid the possibility of a null   ClassLoader.<commit_after>package org.apache.velocity.runtime;

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Velocity", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact <EMAIL>.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.io.InputStream;
import java.io.File;
import java.io.IOException;
import java.io.Reader;

import java.util.Map;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;
import java.util.HashMap;

import org.apache.velocity.Template;

import org.apache.velocity.runtime.log.LogManager;
import org.apache.velocity.runtime.log.LogSystem;
import org.apache.velocity.runtime.log.PrimordialLogSystem;
import org.apache.velocity.runtime.log.NullLogSystem;

import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.node.SimpleNode;

import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.VelocimacroFactory;

import org.apache.velocity.runtime.resource.ContentResource;
import org.apache.velocity.runtime.resource.ResourceManager;

import org.apache.velocity.util.SimplePool;
import org.apache.velocity.util.StringUtils;

import org.apache.velocity.util.introspection.Introspector;
import org.apache.velocity.util.introspection.Uberspect;
import org.apache.velocity.util.introspection.UberspectLoggable;

import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;

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.
 *
 * 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);
 * 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
 * -----------------------------------------------------------------------
 * init()
 * 
 * If init() is called by itself the RuntimeInstance will initialize
 * 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
 * default property.
 * -----------------------------------------------------------------------
 * </pre>
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME>.</a>
 * @version $Id: RuntimeInstance.java,v 1.19 2003/09/01 18:57:24 dlr Exp $
 */
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, we dump
     *  all messages out of the primordial one into the real one.
     */
    private  LogSystem logSystem = new PrimordialLogSystem();

    /** 
     * The Runtime parser pool 
     */
    private  SimplePool parserPool;
    
    /** 
     * Indicate whether the Runtime has been fully initialized.
     */
    private  boolean initialized;

    /**
     * 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;

    /**
     * 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;

    /*
     *  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;


    private Uberspect uberSpect;

    public RuntimeInstance()
    {
        /*
         *  create a VM factory, resource manager
         *  and introspector
         */

        vmFactory = new VelocimacroFactory( this );

        /*
         *  make a new introspector and initialize it
         */
         
        introspector = new Introspector( this );

        /*
         * and a store for the application attributes
         */

        applicationAttributes = new HashMap();
    }

    /*
     * 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>Parser Pool</li>
     *   <li>Global Cache</li>
     *   <li>Static Content Include System</li>
     *   <li>Velocimacro System</li>
     * </ul>
     */
    public synchronized void init()
        throws Exception
    {
        if (initialized == false)
        {
            info("************************************************************** ");
            info("Starting Jakarta Velocity v@version@");
            info("RuntimeInstance initializing.");
            initializeProperties();
            initializeLogger();
            initializeResourceManager();
            initializeDirectives();
            initializeParserPool();

            initializeIntrospection();
            /*
             *  initialize the VM Factory.  It will use the properties 
             * accessable from Runtime, so keep this here at the end.
             */
            vmFactory.initVelocimacro();

            info("Velocity successfully started.");
            
            initialized = true;
        }
    }


    /**
     *  Gets the classname for the Uberspect introspection package and
     *  instantiates an instance.
     */
    private void initializeIntrospection()
        throws Exception
    {
        String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);

        if (rm != null && rm.length() > 0)
        {
            Object o = null;

            try
            {
               o = Class.forName(rm).newInstance();
            }
            catch (ClassNotFoundException cnfe)
            {
                String err = "The specified class for Uberspect ("
                    + rm
                    + ") does not exist (or is not accessible to the current classlaoder.";
                 error(err);
                 throw new Exception(err);
            }

            if (!(o instanceof Uberspect))
            {
                String err = "The specified class for Uberspect ("
                    + rm
                    + ") does not implement org.apache.velocity.util.introspector.Uberspect."
                    + " Velocity not initialized correctly.";

                error(err);
                throw new Exception(err);
            }

            uberSpect = (Uberspect) o;

            if (uberSpect instanceof UberspectLoggable)
            {
                ((UberspectLoggable) uberSpect).setRuntimeLogger(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.";

            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()
    {
        try
        {
            InputStream inputStream = getClass()
                .getResourceAsStream('/' + DEFAULT_RUNTIME_PROPERTIES);
            
            configuration.load( inputStream );
            
            info ("Default Properties File: " + 
                new File(DEFAULT_RUNTIME_PROPERTIES).getPath());
        }
        catch (IOException ioe)
        {
            System.err.println("Cannot get Velocity Runtime default properties!");
        }
    }

    /**
     * Allows an external system to set a property in
     * the Velocity Runtime.
     *
     * @param String property key
     * @param String property value
     */
    public void setProperty(String key, Object value)
    {
        if (overridingProperties == null)
        {
            overridingProperties = new ExtendedProperties();
        }            
            
        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 ExtendedProperties 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 String key
     * @param String value
     */
    public void addProperty(String key, Object value)
    {
        if (overridingProperties == null)
        {
            overridingProperties = new ExtendedProperties();
        }            
            
        overridingProperties.addProperty( key, value );
    }
    
    /**
     * Clear the values pertaining to a particular
     * property.
     *
     * @param String 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
     */
    public Object getProperty( String key )
    {
        return configuration.getProperty( 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();
        }            
    
        if( overridingProperties != null)
        {        
            configuration.combine(overridingProperties);
        }
    }
    
    /**
     * Initialize the Velocity Runtime with a Properties
     * object.
     *
     * @param Properties
     */
    public void init(Properties p) throws Exception
    {
        overridingProperties = ExtendedProperties.convertProperties(p);
        init();
    }
    
    /**
     * Initialize the Velocity Runtime with the name of
     * ExtendedProperties object.
     *
     * @param Properties
     */
    public void init(String configurationFile)
        throws Exception
    {
        overridingProperties = new ExtendedProperties(configurationFile);
        init();
    }

    private void initializeResourceManager()
        throws Exception
    {
        /*
         * Which resource manager?
         */
         
        String rm = getString( RuntimeConstants.RESOURCE_MANAGER_CLASS );

        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
             */
            
            Object o = null;
            
            try
            {
               o = Class.forName( rm ).newInstance();
            }
            catch (ClassNotFoundException cnfe )
            {
                String err = "The specified class for Resourcemanager ("
                    + rm    
                    + ") does not exist (or is not accessible to the current classlaoder.";
                 error( err );
                 throw new Exception( err );
            }
            
            if (!(o instanceof ResourceManager) )
            {
                String err = "The specified class for ResourceManager ("
                    + rm 
                    + ") does not implement org.apache.runtime.resource.ResourceManager."
                    + " Velocity not initialized correctly.";
                    
                error( err);
                throw new Exception(err);
            }

            resourceManager = (ResourceManager) o;
            
            resourceManager.initialize( this );        
         }
         else
         {
            /*
             *  someone screwed up.  Lets not fool around...
             */
             
            String err = "It appears that no class was specified as the"
            + " ResourceManager.  Please ensure that all configuration"
            + " information is correct.";
            
            error( err);
            throw new Exception( err );
        }                            
    }
    
    /**
     * Initialize the Velocity logging system.
     *
     * @throws Exception
     */
    private void initializeLogger() throws Exception
    { 
        /*
         * Initialize the logger. We will eventually move all
         * logging into the logging manager.
         */
        if (logSystem instanceof PrimordialLogSystem )
        {
            PrimordialLogSystem pls = (PrimordialLogSystem) logSystem;
            logSystem = LogManager.createLogSystem( this );
            
            /*
             * in the event of failure, lets do something to let it 
             * limp along.
             */
             
             if (logSystem == null)
             {
                logSystem = new NullLogSystem();
             }
             else
             {
                pls.dumpLogMessages( logSystem );
             }
        }
   }

    
    /**
     * 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();
        
        Properties directiveProperties = new Properties();
        
        /*
         * Grab the properties file with the list of directives
         * that we should initialize.
         */

        InputStream inputStream =
            getClass().getResourceAsStream('/' + DEFAULT_RUNTIME_DIRECTIVES);
    
        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!");
        
        directiveProperties.load(inputStream);
        
{'fraction_non_alphanumeric': 0.09288290454436163, 'fraction_numerical': 0.0016350084154844915, 'mean_word_length': 1.9029803866824877, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1369073', 'n_tokens_mistral': 10297, 'n_tokens_neox': 9776, 'n_words': 3538}