EMMA Coverage Report (generated Tue May 18 22:13:27 CDT 2004)
[all classes][org.apache.velocity.runtime]

COVERAGE SUMMARY FOR SOURCE FILE [RuntimeInstance.java]

nameclass, %method, %block, %line, %
RuntimeInstance.java100% (1/1)82%  (37/45)68%  (539/790)72%  (139.9/193)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RuntimeInstance100% (1/1)82%  (37/45)68%  (539/790)72%  (139.9/193)
clearProperty (String): void 0%   (0/1)0%   (0/8)0%   (0/3)
debug (Object): void 0%   (0/1)0%   (0/5)0%   (0/2)
getApplicationAttribute (Object): Object 0%   (0/1)0%   (0/5)0%   (0/1)
getContent (String): ContentResource 0%   (0/1)0%   (0/8)0%   (0/1)
getLoaderNameForResource (String): String 0%   (0/1)0%   (0/5)0%   (0/1)
init (String): void 0%   (0/1)0%   (0/9)0%   (0/3)
setApplicationAttribute (Object, Object): Object 0%   (0/1)0%   (0/6)0%   (0/1)
setConfiguration (ExtendedProperties): void 0%   (0/1)0%   (0/16)0%   (0/5)
initializeResourceManager (): void 100% (1/1)36%  (29/80)47%  (9/19)
initializeIntrospection (): void 100% (1/1)42%  (37/88)52%  (11/21)
loadDirective (String, String): void 100% (1/1)49%  (34/69)70%  (7/10)
log (int, Object): void 100% (1/1)52%  (12/23)67%  (3.3/5)
showStackTrace (): boolean 100% (1/1)55%  (6/11)67%  (2/3)
parse (Reader, String, boolean): SimpleNode 100% (1/1)76%  (42/55)69%  (11/16)
initializeLogger (): void 100% (1/1)77%  (20/26)86%  (6/7)
initializeDirectives (): void 100% (1/1)78%  (46/59)83%  (11.6/14)
setDefaultProperties (): void 100% (1/1)86%  (25/29)71%  (5/7)
RuntimeInstance (): void 100% (1/1)100% (45/45)100% (12/12)
addProperty (String, Object): void 100% (1/1)100% (14/14)100% (4/4)
addVelocimacro (String, String, String [], String): boolean 100% (1/1)100% (8/8)100% (1/1)
createNewParser (): Parser 100% (1/1)100% (11/11)100% (3/3)
dumpVMNamespace (String): boolean 100% (1/1)100% (5/5)100% (1/1)
error (Object): void 100% (1/1)100% (5/5)100% (2/2)
getBoolean (String, boolean): boolean 100% (1/1)100% (6/6)100% (1/1)
getConfiguration (): ExtendedProperties 100% (1/1)100% (3/3)100% (1/1)
getContent (String, String): ContentResource 100% (1/1)100% (8/8)100% (1/1)
getInt (String): int 100% (1/1)100% (5/5)100% (1/1)
getInt (String, int): int 100% (1/1)100% (6/6)100% (1/1)
getIntrospector (): Introspector 100% (1/1)100% (3/3)100% (1/1)
getProperty (String): Object 100% (1/1)100% (5/5)100% (1/1)
getString (String): String 100% (1/1)100% (5/5)100% (1/1)
getString (String, String): String 100% (1/1)100% (6/6)100% (1/1)
getTemplate (String): Template 100% (1/1)100% (8/8)100% (1/1)
getTemplate (String, String): Template 100% (1/1)100% (8/8)100% (1/1)
getUberspect (): Uberspect 100% (1/1)100% (3/3)100% (1/1)
getVelocimacro (String, String): Directive 100% (1/1)100% (6/6)100% (1/1)
info (Object): void 100% (1/1)100% (5/5)100% (2/2)
init (): void 100% (1/1)100% (34/34)100% (14/14)
init (Properties): void 100% (1/1)100% (7/7)100% (3/3)
initializeParserPool (): void 100% (1/1)100% (36/36)100% (6/6)
initializeProperties (): void 100% (1/1)100% (15/15)100% (5/5)
isVelocimacro (String, String): boolean 100% (1/1)100% (6/6)100% (1/1)
parse (Reader, String): SimpleNode 100% (1/1)100% (6/6)100% (1/1)
setProperty (String, Object): void 100% (1/1)100% (14/14)100% (4/4)
warn (Object): void 100% (1/1)100% (5/5)100% (2/2)

1package org.apache.velocity.runtime;
2 
3/*
4 * Copyright 2000-2001,2004 The Apache Software Foundation.
5 * 
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * 
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 * 
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 
19import java.io.InputStream;
20import java.io.File;
21import java.io.IOException;
22import java.io.Reader;
23 
24import java.util.Map;
25import java.util.Hashtable;
26import java.util.Properties;
27import java.util.Enumeration;
28import java.util.HashMap;
29 
30import org.apache.velocity.Template;
31 
32import org.apache.velocity.runtime.log.LogManager;
33import org.apache.velocity.runtime.log.LogSystem;
34import org.apache.velocity.runtime.log.PrimordialLogSystem;
35import org.apache.velocity.runtime.log.NullLogSystem;
36 
37import org.apache.velocity.runtime.parser.Parser;
38import org.apache.velocity.runtime.parser.ParseException;
39import org.apache.velocity.runtime.parser.node.SimpleNode;
40 
41import org.apache.velocity.runtime.directive.Directive;
42import org.apache.velocity.runtime.VelocimacroFactory;
43 
44import org.apache.velocity.runtime.resource.ContentResource;
45import org.apache.velocity.runtime.resource.ResourceManager;
46 
47import org.apache.velocity.util.SimplePool;
48import org.apache.velocity.util.StringUtils;
49 
50import org.apache.velocity.util.introspection.Introspector;
51import org.apache.velocity.util.introspection.Uberspect;
52import org.apache.velocity.util.introspection.UberspectLoggable;
53 
54import org.apache.velocity.exception.ResourceNotFoundException;
55import org.apache.velocity.exception.ParseErrorException;
56 
57import org.apache.commons.collections.ExtendedProperties;
58 
59/**
60 * This is the Runtime system for Velocity. It is the
61 * single access point for all functionality in Velocity.
62 * It adheres to the mediator pattern and is the only
63 * structure that developers need to be familiar with
64 * in order to get Velocity to perform.
65 *
66 * The Runtime will also cooperate with external
67 * systems like Turbine. Runtime properties can
68 * set and then the Runtime is initialized.
69 *
70 * Turbine, for example, knows where the templates
71 * are to be loaded from, and where the Velocity
72 * log file should be placed.
73 *
74 * So in the case of Velocity cooperating with Turbine
75 * the code might look something like the following:
76 *
77 * <blockquote><code><pre>
78 * ri.setProperty(Runtime.FILE_RESOURCE_LOADER_PATH, templatePath);
79 * ri.setProperty(Runtime.RUNTIME_LOG, pathToVelocityLog);
80 * ri.init();
81 * </pre></code></blockquote>
82 *
83 * <pre>
84 * -----------------------------------------------------------------------
85 * 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
86 * -----------------------------------------------------------------------
87 * init()
88 * 
89 * If init() is called by itself the RuntimeInstance will initialize
90 * with a set of default values.
91 * -----------------------------------------------------------------------
92 * init(String/Properties)
93 *
94 * In this case the default velocity properties are layed down
95 * first to provide a solid base, then any properties provided
96 * in the given properties object will override the corresponding
97 * default property.
98 * -----------------------------------------------------------------------
99 * </pre>
100 *
101 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
102 * @author <a href="mailto:jlb@houseofdistraction.com">Jeff Bowden</a>
103 * @author <a href="mailto:geirm@optonline.net">Geir Magusson Jr.</a>
104 * @version $Id: RuntimeInstance.java,v 1.19.4.1 2004/03/03 23:22:55 geirm Exp $
105 */
106public class RuntimeInstance implements RuntimeConstants, RuntimeServices
107{    
108    /**
109     *  VelocimacroFactory object to manage VMs
110     */
111    private  VelocimacroFactory vmFactory = null;
112 
113    /** 
114     *  The Runtime logger.  We start with an instance of
115     *  a 'primordial logger', which just collects log messages
116     *  then, when the log system is initialized, we dump
117     *  all messages out of the primordial one into the real one.
118     */
119    private  LogSystem logSystem = new PrimordialLogSystem();
120 
121    /** 
122     * The Runtime parser pool 
123     */
124    private  SimplePool parserPool;
125    
126    /** 
127     * Indicate whether the Runtime has been fully initialized.
128     */
129    private  boolean initialized;
130 
131    /**
132     * These are the properties that are laid down over top
133     * of the default properties when requested.
134     */
135    private  ExtendedProperties overridingProperties = null;
136 
137    /**
138     * This is a hashtable of initialized directives.
139     * The directives that populate this hashtable are
140     * taken from the RUNTIME_DEFAULT_DIRECTIVES
141     * property file. This hashtable is passed
142     * to each parser that is created.
143     */
144    private Hashtable runtimeDirectives;
145 
146    /**
147     * Object that houses the configuration options for
148     * the velocity runtime. The ExtendedProperties object allows
149     * the convenient retrieval of a subset of properties.
150     * For example all the properties for a resource loader
151     * can be retrieved from the main ExtendedProperties object
152     * using something like the following:
153     *
154     * ExtendedProperties loaderConfiguration = 
155     *         configuration.subset(loaderID);
156     *
157     * And a configuration is a lot more convenient to deal
158     * with then conventional properties objects, or Maps.
159     */
160    private  ExtendedProperties configuration = new ExtendedProperties();
161 
162    private ResourceManager resourceManager = null;
163 
164    /*
165     *  Each runtime instance has it's own introspector
166     *  to ensure that each instance is completely separate.
167     */
168    private Introspector introspector = null;
169 
170 
171    /*
172     *  Opaque reference to something specificed by the 
173     *  application for use in application supplied/specified
174     *  pluggable components
175     */
176    private Map applicationAttributes = null;
177 
178 
179    private Uberspect uberSpect;
180 
181    public RuntimeInstance()
182    {
183        /*
184         *  create a VM factory, resource manager
185         *  and introspector
186         */
187 
188        vmFactory = new VelocimacroFactory( this );
189 
190        /*
191         *  make a new introspector and initialize it
192         */
193         
194        introspector = new Introspector( this );
195 
196        /*
197         * and a store for the application attributes
198         */
199 
200        applicationAttributes = new HashMap();
201    }
202 
203    /*
204     * This is the primary initialization method in the Velocity
205     * Runtime. The systems that are setup/initialized here are
206     * as follows:
207     *
208     * <ul>
209     *   <li>Logging System</li>
210     *   <li>ResourceManager</li>
211     *   <li>Parser Pool</li>
212     *   <li>Global Cache</li>
213     *   <li>Static Content Include System</li>
214     *   <li>Velocimacro System</li>
215     * </ul>
216     */
217    public synchronized void init()
218        throws Exception
219    {
220        if (initialized == false)
221        {
222            info("************************************************************** ");
223            info("Starting Jakarta Velocity v1.4");
224            info("RuntimeInstance initializing.");
225            initializeProperties();
226            initializeLogger();
227            initializeResourceManager();
228            initializeDirectives();
229            initializeParserPool();
230 
231            initializeIntrospection();
232            /*
233             *  initialize the VM Factory.  It will use the properties 
234             * accessable from Runtime, so keep this here at the end.
235             */
236            vmFactory.initVelocimacro();
237 
238            info("Velocity successfully started.");
239            
240            initialized = true;
241        }
242    }
243 
244 
245    /**
246     *  Gets the classname for the Uberspect introspection package and
247     *  instantiates an instance.
248     */
249    private void initializeIntrospection()
250        throws Exception
251    {
252        String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);
253 
254        if (rm != null && rm.length() > 0)
255        {
256            Object o = null;
257 
258            try
259            {
260               o = Class.forName(rm).newInstance();
261            }
262            catch (ClassNotFoundException cnfe)
263            {
264                String err = "The specified class for Uberspect ("
265                    + rm
266                    + ") does not exist (or is not accessible to the current classlaoder.";
267                 error(err);
268                 throw new Exception(err);
269            }
270 
271            if (!(o instanceof Uberspect))
272            {
273                String err = "The specified class for Uberspect ("
274                    + rm
275                    + ") does not implement org.apache.velocity.util.introspector.Uberspect."
276                    + " Velocity not initialized correctly.";
277 
278                error(err);
279                throw new Exception(err);
280            }
281 
282            uberSpect = (Uberspect) o;
283 
284            if (uberSpect instanceof UberspectLoggable)
285            {
286                ((UberspectLoggable) uberSpect).setRuntimeLogger(this);
287            }
288 
289            uberSpect.init();
290         }
291         else
292         {
293            /*
294             *  someone screwed up.  Lets not fool around...
295             */
296 
297            String err = "It appears that no class was specified as the"
298            + " Uberspect.  Please ensure that all configuration"
299            + " information is correct.";
300 
301            error(err);
302            throw new Exception(err);
303        }
304    }
305 
306    /**
307     * Initializes the Velocity Runtime with properties file.
308     * The properties file may be in the file system proper,
309     * or the properties file may be in the classpath.
310     */
311    private void setDefaultProperties()
312    {
313        try
314        {
315            InputStream inputStream = getClass()
316                .getResourceAsStream('/' + DEFAULT_RUNTIME_PROPERTIES);
317            
318            configuration.load( inputStream );
319            
320            info ("Default Properties File: " + 
321                new File(DEFAULT_RUNTIME_PROPERTIES).getPath());
322        }
323        catch (IOException ioe)
324        {
325            System.err.println("Cannot get Velocity Runtime default properties!");
326        }
327    }
328 
329    /**
330     * Allows an external system to set a property in
331     * the Velocity Runtime.
332     *
333     * @param String property key
334     * @param String property value
335     */
336    public void setProperty(String key, Object value)
337    {
338        if (overridingProperties == null)
339        {
340            overridingProperties = new ExtendedProperties();
341        }            
342            
343        overridingProperties.setProperty( key, value );
344    }        
345 
346    /**
347     * Allow an external system to set an ExtendedProperties
348     * object to use. This is useful where the external
349     * system also uses the ExtendedProperties class and
350     * the velocity configuration is a subset of
351     * parent application's configuration. This is
352     * the case with Turbine.
353     *
354     * @param ExtendedProperties configuration
355     */
356    public void setConfiguration( ExtendedProperties configuration)
357    {
358        if (overridingProperties == null)
359        {
360            overridingProperties = configuration;
361        }
362        else
363        {
364            // Avoid possible ConcurrentModificationException
365            if (overridingProperties != configuration)
366            {
367                overridingProperties.combine(configuration);
368            }
369        }
370    }
371 
372    /**
373     * Add a property to the configuration. If it already
374     * exists then the value stated here will be added
375     * to the configuration entry. For example, if
376     *
377     * resource.loader = file
378     *
379     * is already present in the configuration and you
380     *
381     * addProperty("resource.loader", "classpath")
382     *
383     * Then you will end up with a Vector like the
384     * following:
385     *
386     * ["file", "classpath"]
387     *
388     * @param String key
389     * @param String value
390     */
391    public void addProperty(String key, Object value)
392    {
393        if (overridingProperties == null)
394        {
395            overridingProperties = new ExtendedProperties();
396        }            
397            
398        overridingProperties.addProperty( key, value );
399    }
400    
401    /**
402     * Clear the values pertaining to a particular
403     * property.
404     *
405     * @param String key of property to clear
406     */
407    public void clearProperty(String key)
408    {
409        if (overridingProperties != null)
410        {
411            overridingProperties.clearProperty(key);
412        }            
413    }
414    
415    /**
416     *  Allows an external caller to get a property.  The calling
417     *  routine is required to know the type, as this routine
418     *  will return an Object, as that is what properties can be.
419     *
420     *  @param key property to return
421     */
422    public Object getProperty( String key )
423    {
424        return configuration.getProperty( key );
425    }
426 
427    /**
428     * Initialize Velocity properties, if the default
429     * properties have not been laid down first then
430     * do so. Then proceed to process any overriding
431     * properties. Laying down the default properties
432     * gives a much greater chance of having a
433     * working system.
434     */
435    private void initializeProperties()
436    {
437        /* 
438         * Always lay down the default properties first as
439         * to provide a solid base.
440         */
441        if (configuration.isInitialized() == false)
442        {
443            setDefaultProperties();
444        }            
445    
446        if( overridingProperties != null)
447        {        
448            configuration.combine(overridingProperties);
449        }
450    }
451    
452    /**
453     * Initialize the Velocity Runtime with a Properties
454     * object.
455     *
456     * @param Properties
457     */
458    public void init(Properties p) throws Exception
459    {
460        overridingProperties = ExtendedProperties.convertProperties(p);
461        init();
462    }
463    
464    /**
465     * Initialize the Velocity Runtime with the name of
466     * ExtendedProperties object.
467     *
468     * @param Properties
469     */
470    public void init(String configurationFile)
471        throws Exception
472    {
473        overridingProperties = new ExtendedProperties(configurationFile);
474        init();
475    }
476 
477    private void initializeResourceManager()
478        throws Exception
479    {
480        /*
481         * Which resource manager?
482         */
483         
484        String rm = getString( RuntimeConstants.RESOURCE_MANAGER_CLASS );
485 
486        if ( rm != null && rm.length() > 0 )
487        {
488            /*
489             *  if something was specified, then make one.
490             *  if that isn't a ResourceManager, consider
491             *  this a huge error and throw
492             */
493            
494            Object o = null;
495            
496            try
497            {
498               o = Class.forName( rm ).newInstance();
499            }
500            catch (ClassNotFoundException cnfe )
501            {
502                String err = "The specified class for Resourcemanager ("
503                    + rm    
504                    + ") does not exist (or is not accessible to the current classlaoder.";
505                 error( err );
506                 throw new Exception( err );
507            }
508            
509            if (!(o instanceof ResourceManager) )
510            {
511                String err = "The specified class for ResourceManager ("
512                    + rm 
513                    + ") does not implement org.apache.runtime.resource.ResourceManager."
514                    + " Velocity not initialized correctly.";
515                    
516                error( err);
517                throw new Exception(err);
518            }
519 
520            resourceManager = (ResourceManager) o;
521            
522            resourceManager.initialize( this );        
523         }
524         else
525         {
526            /*
527             *  someone screwed up.  Lets not fool around...
528             */
529             
530            String err = "It appears that no class was specified as the"
531            + " ResourceManager.  Please ensure that all configuration"
532            + " information is correct.";
533            
534            error( err);
535            throw new Exception( err );
536        }                            
537    }
538    
539    /**
540     * Initialize the Velocity logging system.
541     *
542     * @throws Exception
543     */
544    private void initializeLogger() throws Exception
545    { 
546        /*
547         * Initialize the logger. We will eventually move all
548         * logging into the logging manager.
549         */
550        if (logSystem instanceof PrimordialLogSystem )
551        {
552            PrimordialLogSystem pls = (PrimordialLogSystem) logSystem;
553            logSystem = LogManager.createLogSystem( this );
554            
555            /*
556             * in the event of failure, lets do something to let it 
557             * limp along.
558             */
559             
560             if (logSystem == null)
561             {
562                logSystem = new NullLogSystem();
563             }
564             else
565             {
566                pls.dumpLogMessages( logSystem );
567             }
568        }
569   }
570 
571    
572    /**
573     * This methods initializes all the directives
574     * that are used by the Velocity Runtime. The
575     * directives to be initialized are listed in
576     * the RUNTIME_DEFAULT_DIRECTIVES properties
577     * file.
578     *
579     * @throws Exception
580     */
581    private void initializeDirectives() throws Exception
582    {
583        /*
584         * Initialize the runtime directive table.
585         * This will be used for creating parsers.
586         */
587        runtimeDirectives = new Hashtable();
588        
589        Properties directiveProperties = new Properties();
590        
591        /*
592         * Grab the properties file with the list of directives
593         * that we should initialize.
594         */
595 
596        InputStream inputStream =
597            getClass().getResourceAsStream('/' + DEFAULT_RUNTIME_DIRECTIVES);
598    
599        if (inputStream == null)
600            throw new Exception("Error loading directive.properties! " +
601                                "Something is very wrong if these properties " +
602                                "aren't being located. Either your Velocity " +
603                                "distribution is incomplete or your Velocity " +
604                                "jar file is corrupted!");
605        
606        directiveProperties.load(inputStream);
607        
608        /*
609         * Grab all the values of the properties. These
610         * are all class names for example:
611         *
612         * org.apache.velocity.runtime.directive.Foreach
613         */
614        Enumeration directiveClasses = directiveProperties.elements();
615        
616        while (directiveClasses.hasMoreElements())
617        {
618            String directiveClass = (String) directiveClasses.nextElement();
619            loadDirective( directiveClass, "System" );
620        }
621        
622        /*
623         *  now the user's directives
624         */
625         
626        String[] userdirective = configuration.getStringArray("userdirective");
627        
628        for( int i = 0; i < userdirective.length; i++)
629        {
630            loadDirective( userdirective[i], "User");
631        }
632        
633    }
634    
635    /**
636     *  instantiates and loads the directive with some basic checks
637     * 
638     *  @param directiveClass classname of directive to load 
639     */
640    private void loadDirective( String directiveClass, String caption )
641    {    
642        try
643        {
644            Object o = Class.forName( directiveClass ).newInstance();
645            
646            if ( o instanceof Directive )
647            {
648                Directive directive = (Directive) o;
649                runtimeDirectives.put(directive.getName(), directive);
650                    
651                info("Loaded " + caption + " Directive: " 
652                    + directiveClass);
653            }
654            else
655            {
656                error( caption + " Directive " + directiveClass 
657                    + " is not org.apache.velocity.runtime.directive.Directive."
658                    + " Ignoring. " );
659            }
660        }
661        catch (Exception e)
662        {
663            error("Exception Loading " + caption + " Directive: " 
664                + directiveClass + " : " + e);    
665        }
666    }
667    
668    
669    /**
670     * Initializes the Velocity parser pool.
671     * This still needs to be implemented.
672     */
673    private void initializeParserPool()
674    {
675        int numParsers = getInt( PARSER_POOL_SIZE, NUMBER_OF_PARSERS);
676 
677        parserPool = new SimplePool( numParsers);
678 
679        for (int i=0; i < numParsers ;i++ )
680        {
681            parserPool.put (createNewParser());
682        }
683 
684        info ("Created: " + numParsers + " parsers.");
685    }
686 
687    /**
688     * Returns a JavaCC generated Parser.
689     *
690     * @return Parser javacc generated parser
691     */
692    public Parser createNewParser()
693    {
694        Parser parser = new Parser( this );
695        parser.setDirectives(runtimeDirectives);
696        return parser;
697    }
698 
699    /**
700     * Parse the input and return the root of
701     * AST node structure.
702     * <br><br>
703     *  In the event that it runs out of parsers in the
704     *  pool, it will create and let them be GC'd 
705     *  dynamically, logging that it has to do that.  This
706     *  is considered an exceptional condition.  It is
707     *  expected that the user will set the 
708     *  PARSER_POOL_SIZE property appropriately for their
709     *  application.  We will revisit this.
710     *
711     * @param InputStream inputstream retrieved by a resource loader
712     * @param String name of the template being parsed
713     */
714    public SimpleNode parse( Reader reader, String templateName )
715        throws ParseException
716    {
717        /*
718         *  do it and dump the VM namespace for this template
719         */
720        return parse( reader, templateName, true );
721    }
722 
723    /**
724     *  Parse the input and return the root of the AST node structure.
725     *
726     * @param InputStream inputstream retrieved by a resource loader
727     * @param String name of the template being parsed
728     * @param dumpNamespace flag to dump the Velocimacro namespace for this template
729     */
730    public SimpleNode parse( Reader reader, String templateName, boolean dumpNamespace )
731        throws ParseException
732    {
733 
734        SimpleNode ast = null;
735        Parser parser = (Parser) parserPool.get();
736        boolean madeNew = false;
737 
738        if (parser == null)
739        {
740            /*
741             *  if we couldn't get a parser from the pool
742             *  make one and log it.
743             */
744            
745            error("Runtime : ran out of parsers. Creating new.  "
746                  + " Please increment the parser.pool.size property."
747                  + " The current value is too small.");
748 
749            parser = createNewParser();
750 
751            if( parser != null )
752            {
753                madeNew = true;
754            }
755        }
756 
757        /*
758         *  now, if we have a parser
759         */
760 
761        if (parser != null)
762        {
763            try
764            {
765                /*
766                 *  dump namespace if we are told to.  Generally, you want to 
767                 *  do this - you don't in special circumstances, such as 
768                 *  when a VM is getting init()-ed & parsed
769                 */
770 
771                if ( dumpNamespace )
772                {
773                    dumpVMNamespace( templateName );
774                }
775 
776                ast = parser.parse( reader, templateName );
777            }
778            finally
779            {
780                /*
781                 *  if this came from the pool, then put back
782                 */
783                if (!madeNew)
784                {
785                    parserPool.put(parser);
786                }
787            }
788        }
789        else
790        {
791            error("Runtime : ran out of parsers and unable to create more.");
792        }
793        return ast;
794    }
795    
796    /**
797     * Returns a <code>Template</code> from the resource manager.
798     * This method assumes that the character encoding of the 
799     * template is set by the <code>input.encoding</code>
800     * property.  The default is "ISO-8859-1"
801     *
802     * @param name The file name of the desired template.
803     * @return     The template.
804     * @throws ResourceNotFoundException if template not found
805     *          from any available source.
806     * @throws ParseErrorException if template cannot be parsed due
807     *          to syntax (or other) error.
808     * @throws Exception if an error occurs in template initialization
809     */
810    public Template getTemplate(String name)
811        throws ResourceNotFoundException, ParseErrorException, Exception
812    {
813        return getTemplate( name, getString( INPUT_ENCODING, ENCODING_DEFAULT) );
814    }
815 
816    /**
817     * Returns a <code>Template</code> from the resource manager
818     *
819     * @param name The  name of the desired template.
820     * @param encoding Character encoding of the template
821     * @return     The template.
822     * @throws ResourceNotFoundException if template not found
823     *          from any available source.
824     * @throws ParseErrorException if template cannot be parsed due
825     *          to syntax (or other) error.
826     * @throws Exception if an error occurs in template initialization
827     */
828    public Template getTemplate(String name, String  encoding)
829        throws ResourceNotFoundException, ParseErrorException, Exception
830    {
831        return (Template) resourceManager.getResource(name, ResourceManager.RESOURCE_TEMPLATE, encoding);
832    }
833 
834    /**
835     * Returns a static content resource from the
836     * resource manager.  Uses the current value
837     * if INPUT_ENCODING as the character encoding.
838     *
839     * @param name Name of content resource to get
840     * @return parsed ContentResource object ready for use
841     * @throws ResourceNotFoundException if template not found
842     *          from any available source.
843     */
844    public ContentResource getContent(String name)
845        throws ResourceNotFoundException, ParseErrorException, Exception
846    {
847        /*
848         *  the encoding is irrelvant as we don't do any converstion
849         *  the bytestream should be dumped to the output stream
850         */
851 
852        return getContent( name,  getString( INPUT_ENCODING, ENCODING_DEFAULT));
853    }
854 
855    /**
856     * Returns a static content resource from the
857     * resource manager.
858     *
859     * @param name Name of content resource to get
860     * @param encoding Character encoding to use
861     * @return parsed ContentResource object ready for use
862     * @throws ResourceNotFoundException if template not found
863     *          from any available source.
864     */
865    public ContentResource getContent( String name, String encoding )
866        throws ResourceNotFoundException, ParseErrorException, Exception
867    {
868        return (ContentResource) resourceManager.getResource(name,ResourceManager.RESOURCE_CONTENT, encoding );
869    }
870 
871 
872    /**
873     *  Determines is a template exists, and returns name of the loader that 
874     *  provides it.  This is a slightly less hokey way to support
875     *  the Velocity.templateExists() utility method, which was broken
876     *  when per-template encoding was introduced.  We can revisit this.
877     *
878     *  @param resourceName Name of template or content resource
879     *  @return class name of loader than can provide it
880     */
881    public String getLoaderNameForResource( String resourceName )
882    {
883        return resourceManager.getLoaderNameForResource( resourceName );
884    }
885 
886    /**
887     * Added this to check and make sure that the configuration
888     * is initialized before trying to get properties from it.
889     * This occurs when there are errors during initialization
890     * and the default properties have yet to be layed down.
891     */
892    private boolean showStackTrace()
893    {
894        if (configuration.isInitialized())
895        {
896            return getBoolean(RUNTIME_LOG_WARN_STACKTRACE, false);
897        }            
898        else
899        {
900            return false;
901        }            
902    }
903 
904    /**
905     * Handle logging.
906     *
907     * @param String message to log
908     */
909    private void log(int level, Object message)
910    {
911        String out;
912     
913        /*
914         *  now,  see if the logging stacktrace is on
915         *  and modify the message to suit
916         */
917        if ( showStackTrace() &&
918            (message instanceof Throwable || message instanceof Exception) )
919        {
920            out = StringUtils.stackTrace((Throwable)message);
921        }
922        else
923        {
924            out = message.toString();    
925        }            
926 
927        /*
928         *  just log it, as we are guaranteed now to have some
929         *  kind of logger - save the if()
930         */
931        logSystem.logVelocityMessage( level, out);
932    }
933 
934    /**
935     * Log a warning message.
936     *
937     * @param Object message to log
938     */
939    public void warn(Object message)
940    {
941        log(LogSystem.WARN_ID, message);
942    }
943    
944    /** 
945     * Log an info message.
946     *
947     * @param Object message to log
948     */
949    public void info(Object message)
950    {
951        log(LogSystem.INFO_ID, message);
952    }
953    
954    /**
955     * Log an error message.
956     *
957     * @param Object message to log
958     */
959    public void error(Object message)
960    {
961        log(LogSystem.ERROR_ID, message);
962    }
963    
964    /**
965     * Log a debug message.
966     *
967     * @param Object message to log
968     */
969    public void debug(Object message)
970    {
971        log(LogSystem.DEBUG_ID, message);
972    }
973 
974    /**
975     * String property accessor method with default to hide the
976     * configuration implementation.
977     * 
978     * @param String key property key
979     * @param String defaultValue  default value to return if key not 
980     *               found in resource manager.
981     * @return String  value of key or default 
982     */
983    public String getString( String key, String defaultValue)
984    {
985        return configuration.getString(key, defaultValue);
986    }
987 
988    /**
989     * Returns the appropriate VelocimacroProxy object if strVMname
990     * is a valid current Velocimacro.
991     *
992     * @param String vmName  Name of velocimacro requested
993     * @return String VelocimacroProxy 
994     */
995    public Directive getVelocimacro( String vmName, String templateName  )
996    {
997        return vmFactory.getVelocimacro( vmName, templateName );
998    }
999 
1000   /**
1001     * Adds a new Velocimacro. Usually called by Macro only while parsing.
1002     *
1003     * @param String name  Name of velocimacro 
1004     * @param String macro  String form of macro body
1005     * @param String argArray  Array of strings, containing the 
1006     *                         #macro() arguments.  the 0th is the name.
1007     * @return boolean  True if added, false if rejected for some 
1008     *                  reason (either parameters or permission settings) 
1009     */
1010    public boolean addVelocimacro( String name, 
1011                                          String macro, 
1012                                          String argArray[], 
1013                                          String sourceTemplate )
1014    {    
1015        return vmFactory.addVelocimacro(  name, macro,  argArray,  sourceTemplate );
1016    }
1017 
1018    /**
1019     *  Checks to see if a VM exists
1020     *
1021     * @param name  Name of velocimacro
1022     * @return boolean  True if VM by that name exists, false if not
1023     */
1024    public boolean isVelocimacro( String vmName, String templateName )
1025    {
1026        return vmFactory.isVelocimacro( vmName, templateName );
1027    }
1028 
1029    /**
1030     *  tells the vmFactory to dump the specified namespace.  This is to support
1031     *  clearing the VM list when in inline-VM-local-scope mode
1032     */
1033    public boolean dumpVMNamespace( String namespace )
1034    {
1035        return vmFactory.dumpVMNamespace( namespace );
1036    }
1037 
1038    /* --------------------------------------------------------------------
1039     * R U N T I M E  A C C E S S O R  M E T H O D S
1040     * --------------------------------------------------------------------
1041     * These are the getXXX() methods that are a simple wrapper
1042     * around the configuration object. This is an attempt
1043     * to make a the Velocity Runtime the single access point
1044     * for all things Velocity, and allow the Runtime to
1045     * adhere as closely as possible the the Mediator pattern
1046     * which is the ultimate goal.
1047     * --------------------------------------------------------------------
1048     */
1049 
1050    /**
1051     * String property accessor method to hide the configuration implementation
1052     * @param key  property key
1053     * @return   value of key or null
1054     */
1055    public String getString(String key)
1056    {
1057        return configuration.getString( key );
1058    }
1059 
1060    /**
1061     * Int property accessor method to hide the configuration implementation.
1062     *
1063     * @param String key property key
1064     * @return int value
1065     */
1066    public int getInt( String key )
1067    {
1068        return configuration.getInt( key );
1069    }
1070 
1071    /**
1072     * Int property accessor method to hide the configuration implementation.
1073     *
1074     * @param key  property key
1075     * @param int default value
1076     * @return int  value
1077     */
1078    public int getInt( String key, int defaultValue )
1079    {
1080        return configuration.getInt( key, defaultValue );
1081    }
1082 
1083    /**
1084     * Boolean property accessor method to hide the configuration implementation.
1085     * 
1086     * @param String key  property key
1087     * @param boolean default default value if property not found
1088     * @return boolean  value of key or default value
1089     */
1090    public boolean getBoolean( String key, boolean def )
1091    {
1092        return configuration.getBoolean( key, def );
1093    }
1094 
1095    /**
1096     * Return the velocity runtime configuration object.
1097     *
1098     * @return ExtendedProperties configuration object which houses
1099     *                       the velocity runtime properties.
1100     */
1101    public ExtendedProperties getConfiguration()
1102    {
1103        return configuration;
1104    }        
1105    
1106    /**
1107     *  Return the Introspector for this instance
1108     */
1109    public Introspector getIntrospector()
1110    {
1111        return introspector;
1112    }
1113 
1114    public Object getApplicationAttribute( Object key)
1115    {
1116        return applicationAttributes.get( key );
1117    }
1118 
1119    public Object setApplicationAttribute( Object key, Object o )
1120    {
1121        return applicationAttributes.put( key, o );
1122    }
1123 
1124    public Uberspect getUberspect()
1125    {
1126        return uberSpect;
1127    }
1128 
1129}

[all classes][org.apache.velocity.runtime]
EMMA 2.0.4015 (stable) (C) Vladimir Roubtsov