Source Code Cross Referenced for RuntimeInstance.java in  » Template-Engine » Velocity » org » apache » velocity » runtime » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » Velocity » org.apache.velocity.runtime 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.apache.velocity.runtime;
0002:
0003:        /*
0004:         * Licensed to the Apache Software Foundation (ASF) under one
0005:         * or more contributor license agreements.  See the NOTICE file
0006:         * distributed with this work for additional information
0007:         * regarding copyright ownership.  The ASF licenses this file
0008:         * to you under the Apache License, Version 2.0 (the
0009:         * "License"); you may not use this file except in compliance
0010:         * with the License.  You may obtain a copy of the License at
0011:         *
0012:         *   http://www.apache.org/licenses/LICENSE-2.0
0013:         *
0014:         * Unless required by applicable law or agreed to in writing,
0015:         * software distributed under the License is distributed on an
0016:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0017:         * KIND, either express or implied.  See the License for the
0018:         * specific language governing permissions and limitations
0019:         * under the License.    
0020:         */
0021:
0022:        import java.io.File;
0023:        import java.io.IOException;
0024:        import java.io.InputStream;
0025:        import java.io.Reader;
0026:        import java.util.Enumeration;
0027:        import java.util.HashMap;
0028:        import java.util.Hashtable;
0029:        import java.util.Map;
0030:        import java.util.Properties;
0031:
0032:        import org.apache.commons.collections.ExtendedProperties;
0033:        import org.apache.velocity.Template;
0034:        import org.apache.velocity.app.event.EventCartridge;
0035:        import org.apache.velocity.app.event.EventHandler;
0036:        import org.apache.velocity.app.event.IncludeEventHandler;
0037:        import org.apache.velocity.app.event.InvalidReferenceEventHandler;
0038:        import org.apache.velocity.app.event.MethodExceptionEventHandler;
0039:        import org.apache.velocity.app.event.NullSetEventHandler;
0040:        import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
0041:        import org.apache.velocity.exception.ParseErrorException;
0042:        import org.apache.velocity.exception.ResourceNotFoundException;
0043:        import org.apache.velocity.runtime.directive.Directive;
0044:        import org.apache.velocity.runtime.log.Log;
0045:        import org.apache.velocity.runtime.log.LogManager;
0046:        import org.apache.velocity.runtime.parser.ParseException;
0047:        import org.apache.velocity.runtime.parser.Parser;
0048:        import org.apache.velocity.runtime.parser.node.SimpleNode;
0049:        import org.apache.velocity.runtime.resource.ContentResource;
0050:        import org.apache.velocity.runtime.resource.ResourceManager;
0051:        import org.apache.velocity.util.ClassUtils;
0052:        import org.apache.velocity.util.RuntimeServicesAware;
0053:        import org.apache.velocity.util.StringUtils;
0054:        import org.apache.velocity.util.introspection.Introspector;
0055:        import org.apache.velocity.util.introspection.Uberspect;
0056:        import org.apache.velocity.util.introspection.UberspectLoggable;
0057:
0058:        /**
0059:         * This is the Runtime system for Velocity. It is the
0060:         * single access point for all functionality in Velocity.
0061:         * It adheres to the mediator pattern and is the only
0062:         * structure that developers need to be familiar with
0063:         * in order to get Velocity to perform.
0064:         *
0065:         * The Runtime will also cooperate with external
0066:         * systems like Turbine. Runtime properties can
0067:         * set and then the Runtime is initialized.
0068:         *
0069:         * Turbine, for example, knows where the templates
0070:         * are to be loaded from, and where the Velocity
0071:         * log file should be placed.
0072:         *
0073:         * So in the case of Velocity cooperating with Turbine
0074:         * the code might look something like the following:
0075:         *
0076:         * <blockquote><code><pre>
0077:         * ri.setProperty(Runtime.FILE_RESOURCE_LOADER_PATH, templatePath);
0078:         * ri.setProperty(Runtime.RUNTIME_LOG, pathToVelocityLog);
0079:         * ri.init();
0080:         * </pre></code></blockquote>
0081:         *
0082:         * <pre>
0083:         * -----------------------------------------------------------------------
0084:         * 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
0085:         * -----------------------------------------------------------------------
0086:         * init()
0087:         *
0088:         * If init() is called by itself the RuntimeInstance will initialize
0089:         * with a set of default values.
0090:         * -----------------------------------------------------------------------
0091:         * init(String/Properties)
0092:         *
0093:         * In this case the default velocity properties are layed down
0094:         * first to provide a solid base, then any properties provided
0095:         * in the given properties object will override the corresponding
0096:         * default property.
0097:         * -----------------------------------------------------------------------
0098:         * </pre>
0099:         *
0100:         * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
0101:         * @author <a href="mailto:jlb@houseofdistraction.com">Jeff Bowden</a>
0102:         * @author <a href="mailto:geirm@optonline.net">Geir Magusson Jr.</a>
0103:         * @version $Id: RuntimeInstance.java 474051 2006-11-12 21:42:02Z henning $
0104:         */
0105:        public class RuntimeInstance implements  RuntimeConstants,
0106:                RuntimeServices {
0107:            /**
0108:             *  VelocimacroFactory object to manage VMs
0109:             */
0110:            private VelocimacroFactory vmFactory = null;
0111:
0112:            /**
0113:             * The Runtime logger.  We start with an instance of
0114:             * a 'primordial logger', which just collects log messages
0115:             * then, when the log system is initialized, all the
0116:             * messages get dumpted out of the primordial one into the real one.
0117:             */
0118:            private Log log = new Log();
0119:
0120:            /**
0121:             * The Runtime parser pool
0122:             */
0123:            private ParserPool parserPool;
0124:
0125:            /**
0126:             * Indicate whether the Runtime is in the midst of initialization.
0127:             */
0128:            private boolean initializing = false;
0129:
0130:            /**
0131:             * Indicate whether the Runtime has been fully initialized.
0132:             */
0133:            private boolean initialized = false;
0134:
0135:            /**
0136:             * These are the properties that are laid down over top
0137:             * of the default properties when requested.
0138:             */
0139:            private ExtendedProperties overridingProperties = null;
0140:
0141:            /**
0142:             * This is a hashtable of initialized directives.
0143:             * The directives that populate this hashtable are
0144:             * taken from the RUNTIME_DEFAULT_DIRECTIVES
0145:             * property file. This hashtable is passed
0146:             * to each parser that is created.
0147:             */
0148:            private Hashtable runtimeDirectives;
0149:
0150:            /**
0151:             * Object that houses the configuration options for
0152:             * the velocity runtime. The ExtendedProperties object allows
0153:             * the convenient retrieval of a subset of properties.
0154:             * For example all the properties for a resource loader
0155:             * can be retrieved from the main ExtendedProperties object
0156:             * using something like the following:
0157:             *
0158:             * ExtendedProperties loaderConfiguration =
0159:             *         configuration.subset(loaderID);
0160:             *
0161:             * And a configuration is a lot more convenient to deal
0162:             * with then conventional properties objects, or Maps.
0163:             */
0164:            private ExtendedProperties configuration = new ExtendedProperties();
0165:
0166:            private ResourceManager resourceManager = null;
0167:
0168:            /**
0169:             * This stores the engine-wide set of event handlers.  Event handlers for
0170:             * each specific merge are stored in the context.
0171:             */
0172:            private EventCartridge eventCartridge = null;
0173:
0174:            /*
0175:             *  Each runtime instance has it's own introspector
0176:             *  to ensure that each instance is completely separate.
0177:             */
0178:            private Introspector introspector = null;
0179:
0180:            /*
0181:             *  Opaque reference to something specificed by the
0182:             *  application for use in application supplied/specified
0183:             *  pluggable components
0184:             */
0185:            private Map applicationAttributes = null;
0186:
0187:            private Uberspect uberSpect;
0188:
0189:            /**
0190:             * Creates a new RuntimeInstance object.
0191:             */
0192:            public RuntimeInstance() {
0193:                /*
0194:                 *  create a VM factory, introspector, and application attributes
0195:                 */
0196:                vmFactory = new VelocimacroFactory(this );
0197:
0198:                /*
0199:                 *  make a new introspector and initialize it
0200:                 */
0201:                introspector = new Introspector(getLog());
0202:
0203:                /*
0204:                 * and a store for the application attributes
0205:                 */
0206:                applicationAttributes = new HashMap();
0207:            }
0208:
0209:            /**
0210:             * This is the primary initialization method in the Velocity
0211:             * Runtime. The systems that are setup/initialized here are
0212:             * as follows:
0213:             *
0214:             * <ul>
0215:             *   <li>Logging System</li>
0216:             *   <li>ResourceManager</li>
0217:             *   <li>EventHandler</li>
0218:             *   <li>Parser Pool</li>
0219:             *   <li>Global Cache</li>
0220:             *   <li>Static Content Include System</li>
0221:             *   <li>Velocimacro System</li>
0222:             * </ul>
0223:             * @throws Exception When an error occured during initialization.
0224:             */
0225:            public synchronized void init() throws Exception {
0226:                if (!initialized && !initializing) {
0227:                    initializing = true;
0228:
0229:                    log
0230:                            .trace("*******************************************************************");
0231:                    log
0232:                            .debug("Starting Apache Velocity v@build.version@ (compiled: @build.time@)");
0233:                    log.trace("RuntimeInstance initializing.");
0234:
0235:                    initializeProperties();
0236:                    initializeLog();
0237:                    initializeResourceManager();
0238:                    initializeDirectives();
0239:                    initializeEventHandlers();
0240:                    initializeParserPool();
0241:
0242:                    initializeIntrospection();
0243:                    /*
0244:                     *  initialize the VM Factory.  It will use the properties
0245:                     * accessable from Runtime, so keep this here at the end.
0246:                     */
0247:                    vmFactory.initVelocimacro();
0248:
0249:                    log.trace("RuntimeInstance successfully initialized.");
0250:
0251:                    initialized = true;
0252:                    initializing = false;
0253:                }
0254:            }
0255:
0256:            /**
0257:             * Returns true if the RuntimeInstance has been successfully initialized.
0258:             * @return True if the RuntimeInstance has been successfully initialized.
0259:             */
0260:            public boolean isInitialized() {
0261:                return initialized;
0262:            }
0263:
0264:            /**
0265:             *  Gets the classname for the Uberspect introspection package and
0266:             *  instantiates an instance.
0267:             */
0268:            private void initializeIntrospection() throws Exception {
0269:                String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);
0270:
0271:                if (rm != null && rm.length() > 0) {
0272:                    Object o = null;
0273:
0274:                    try {
0275:                        o = ClassUtils.getNewInstance(rm);
0276:                    } catch (ClassNotFoundException cnfe) {
0277:                        String err = "The specified class for Uberspect ("
0278:                                + rm
0279:                                + ") does not exist or is not accessible to the current classloader.";
0280:                        log.error(err);
0281:                        throw new Exception(err);
0282:                    }
0283:
0284:                    if (!(o instanceof  Uberspect)) {
0285:                        String err = "The specified class for Uberspect (" + rm
0286:                                + ") does not implement "
0287:                                + Uberspect.class.getName()
0288:                                + "; Velocity is not initialized correctly.";
0289:
0290:                        log.error(err);
0291:                        throw new Exception(err);
0292:                    }
0293:
0294:                    uberSpect = (Uberspect) o;
0295:
0296:                    if (uberSpect instanceof  UberspectLoggable) {
0297:                        ((UberspectLoggable) uberSpect).setLog(getLog());
0298:                    }
0299:
0300:                    if (uberSpect instanceof  RuntimeServicesAware) {
0301:                        ((RuntimeServicesAware) uberSpect)
0302:                                .setRuntimeServices(this );
0303:                    }
0304:
0305:                    uberSpect.init();
0306:                } else {
0307:                    /*
0308:                     *  someone screwed up.  Lets not fool around...
0309:                     */
0310:
0311:                    String err = "It appears that no class was specified as the"
0312:                            + " Uberspect.  Please ensure that all configuration"
0313:                            + " information is correct.";
0314:
0315:                    log.error(err);
0316:                    throw new Exception(err);
0317:                }
0318:            }
0319:
0320:            /**
0321:             * Initializes the Velocity Runtime with properties file.
0322:             * The properties file may be in the file system proper,
0323:             * or the properties file may be in the classpath.
0324:             */
0325:            private void setDefaultProperties() {
0326:                InputStream inputStream = null;
0327:                try {
0328:                    inputStream = getClass().getResourceAsStream(
0329:                            '/' + DEFAULT_RUNTIME_PROPERTIES);
0330:
0331:                    configuration.load(inputStream);
0332:
0333:                    if (log.isDebugEnabled()) {
0334:                        log.debug("Default Properties File: "
0335:                                + new File(DEFAULT_RUNTIME_PROPERTIES)
0336:                                        .getPath());
0337:                    }
0338:
0339:                } catch (IOException ioe) {
0340:                    log.error(
0341:                            "Cannot get Velocity Runtime default properties!",
0342:                            ioe);
0343:                } finally {
0344:                    try {
0345:                        if (inputStream != null) {
0346:                            inputStream.close();
0347:                        }
0348:                    } catch (IOException ioe) {
0349:                        log
0350:                                .error(
0351:                                        "Cannot close Velocity Runtime default properties!",
0352:                                        ioe);
0353:                    }
0354:                }
0355:            }
0356:
0357:            /**
0358:             * Allows an external system to set a property in
0359:             * the Velocity Runtime.
0360:             *
0361:             * @param key property key
0362:             * @param  value property value
0363:             */
0364:            public void setProperty(String key, Object value) {
0365:                if (overridingProperties == null) {
0366:                    overridingProperties = new ExtendedProperties();
0367:                }
0368:
0369:                overridingProperties.setProperty(key, value);
0370:            }
0371:
0372:            /**
0373:             * Allow an external system to set an ExtendedProperties
0374:             * object to use. This is useful where the external
0375:             * system also uses the ExtendedProperties class and
0376:             * the velocity configuration is a subset of
0377:             * parent application's configuration. This is
0378:             * the case with Turbine.
0379:             *
0380:             * @param  configuration
0381:             */
0382:            public void setConfiguration(ExtendedProperties configuration) {
0383:                if (overridingProperties == null) {
0384:                    overridingProperties = configuration;
0385:                } else {
0386:                    // Avoid possible ConcurrentModificationException
0387:                    if (overridingProperties != configuration) {
0388:                        overridingProperties.combine(configuration);
0389:                    }
0390:                }
0391:            }
0392:
0393:            /**
0394:             * Add a property to the configuration. If it already
0395:             * exists then the value stated here will be added
0396:             * to the configuration entry. For example, if
0397:             *
0398:             * resource.loader = file
0399:             *
0400:             * is already present in the configuration and you
0401:             *
0402:             * addProperty("resource.loader", "classpath")
0403:             *
0404:             * Then you will end up with a Vector like the
0405:             * following:
0406:             *
0407:             * ["file", "classpath"]
0408:             *
0409:             * @param  key
0410:             * @param  value
0411:             */
0412:            public void addProperty(String key, Object value) {
0413:                if (overridingProperties == null) {
0414:                    overridingProperties = new ExtendedProperties();
0415:                }
0416:
0417:                overridingProperties.addProperty(key, value);
0418:            }
0419:
0420:            /**
0421:             * Clear the values pertaining to a particular
0422:             * property.
0423:             *
0424:             * @param key of property to clear
0425:             */
0426:            public void clearProperty(String key) {
0427:                if (overridingProperties != null) {
0428:                    overridingProperties.clearProperty(key);
0429:                }
0430:            }
0431:
0432:            /**
0433:             *  Allows an external caller to get a property.  The calling
0434:             *  routine is required to know the type, as this routine
0435:             *  will return an Object, as that is what properties can be.
0436:             *
0437:             *  @param key property to return
0438:             *  @return Value of the property or null if it does not exist.
0439:             */
0440:            public Object getProperty(String key) {
0441:                Object o = null;
0442:
0443:                /**
0444:                 * Before initialization, check the user-entered properties first.
0445:                 */
0446:                if (!initialized && !initializing
0447:                        && overridingProperties != null) {
0448:                    o = overridingProperties.get(key);
0449:                }
0450:
0451:                /**
0452:                 * After initialization, configuration will hold all properties.
0453:                 */
0454:                if (o == null) {
0455:                    o = configuration.getProperty(key);
0456:                }
0457:                if (o instanceof  String) {
0458:                    return StringUtils.nullTrim((String) o);
0459:                } else {
0460:                    return o;
0461:                }
0462:            }
0463:
0464:            /**
0465:             * Initialize Velocity properties, if the default
0466:             * properties have not been laid down first then
0467:             * do so. Then proceed to process any overriding
0468:             * properties. Laying down the default properties
0469:             * gives a much greater chance of having a
0470:             * working system.
0471:             */
0472:            private void initializeProperties() {
0473:                /*
0474:                 * Always lay down the default properties first as
0475:                 * to provide a solid base.
0476:                 */
0477:                if (configuration.isInitialized() == false) {
0478:                    setDefaultProperties();
0479:                }
0480:
0481:                if (overridingProperties != null) {
0482:                    configuration.combine(overridingProperties);
0483:                }
0484:            }
0485:
0486:            /**
0487:             * Initialize the Velocity Runtime with a Properties
0488:             * object.
0489:             *
0490:             * @param p
0491:             * @throws Exception When an error occurs during initialization.
0492:             */
0493:            public void init(Properties p) throws Exception {
0494:                overridingProperties = ExtendedProperties.convertProperties(p);
0495:                init();
0496:            }
0497:
0498:            /**
0499:             * Initialize the Velocity Runtime with the name of
0500:             * ExtendedProperties object.
0501:             *
0502:             * @param configurationFile
0503:             * @throws Exception When an error occurs during initialization.
0504:             */
0505:            public void init(String configurationFile) throws Exception {
0506:                overridingProperties = new ExtendedProperties(configurationFile);
0507:                init();
0508:            }
0509:
0510:            private void initializeResourceManager() throws Exception {
0511:                /*
0512:                 * Which resource manager?
0513:                 */
0514:
0515:                String rm = getString(RuntimeConstants.RESOURCE_MANAGER_CLASS);
0516:
0517:                if (rm != null && rm.length() > 0) {
0518:                    /*
0519:                     *  if something was specified, then make one.
0520:                     *  if that isn't a ResourceManager, consider
0521:                     *  this a huge error and throw
0522:                     */
0523:
0524:                    Object o = null;
0525:
0526:                    try {
0527:                        o = ClassUtils.getNewInstance(rm);
0528:                    } catch (ClassNotFoundException cnfe) {
0529:                        String err = "The specified class for ResourceManager ("
0530:                                + rm
0531:                                + ") does not exist or is not accessible to the current classloader.";
0532:                        log.error(err);
0533:                        throw new Exception(err);
0534:                    }
0535:
0536:                    if (!(o instanceof  ResourceManager)) {
0537:                        String err = "The specified class for ResourceManager ("
0538:                                + rm
0539:                                + ") does not implement "
0540:                                + ResourceManager.class.getName()
0541:                                + "; Velocity is not initialized correctly.";
0542:
0543:                        log.error(err);
0544:                        throw new Exception(err);
0545:                    }
0546:
0547:                    resourceManager = (ResourceManager) o;
0548:
0549:                    resourceManager.initialize(this );
0550:                } else {
0551:                    /*
0552:                     *  someone screwed up.  Lets not fool around...
0553:                     */
0554:
0555:                    String err = "It appears that no class was specified as the"
0556:                            + " ResourceManager.  Please ensure that all configuration"
0557:                            + " information is correct.";
0558:
0559:                    log.error(err);
0560:                    throw new Exception(err);
0561:                }
0562:            }
0563:
0564:            private void initializeEventHandlers() throws Exception {
0565:
0566:                eventCartridge = new EventCartridge();
0567:
0568:                /**
0569:                 * For each type of event handler, get the class name, instantiate it, and store it.
0570:                 */
0571:
0572:                String[] referenceinsertion = configuration
0573:                        .getStringArray(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION);
0574:                if (referenceinsertion != null) {
0575:                    for (int i = 0; i < referenceinsertion.length; i++) {
0576:                        EventHandler ev = initializeSpecificEventHandler(
0577:                                referenceinsertion[i],
0578:                                RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION,
0579:                                ReferenceInsertionEventHandler.class);
0580:                        if (ev != null)
0581:                            eventCartridge
0582:                                    .addReferenceInsertionEventHandler((ReferenceInsertionEventHandler) ev);
0583:                    }
0584:                }
0585:
0586:                String[] nullset = configuration
0587:                        .getStringArray(RuntimeConstants.EVENTHANDLER_NULLSET);
0588:                if (nullset != null) {
0589:                    for (int i = 0; i < nullset.length; i++) {
0590:                        EventHandler ev = initializeSpecificEventHandler(
0591:                                nullset[i],
0592:                                RuntimeConstants.EVENTHANDLER_NULLSET,
0593:                                NullSetEventHandler.class);
0594:                        if (ev != null)
0595:                            eventCartridge
0596:                                    .addNullSetEventHandler((NullSetEventHandler) ev);
0597:                    }
0598:                }
0599:
0600:                String[] methodexception = configuration
0601:                        .getStringArray(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION);
0602:                if (methodexception != null) {
0603:                    for (int i = 0; i < methodexception.length; i++) {
0604:                        EventHandler ev = initializeSpecificEventHandler(
0605:                                methodexception[i],
0606:                                RuntimeConstants.EVENTHANDLER_METHODEXCEPTION,
0607:                                MethodExceptionEventHandler.class);
0608:                        if (ev != null)
0609:                            eventCartridge
0610:                                    .addMethodExceptionHandler((MethodExceptionEventHandler) ev);
0611:                    }
0612:                }
0613:
0614:                String[] includeHandler = configuration
0615:                        .getStringArray(RuntimeConstants.EVENTHANDLER_INCLUDE);
0616:                if (includeHandler != null) {
0617:                    for (int i = 0; i < includeHandler.length; i++) {
0618:                        EventHandler ev = initializeSpecificEventHandler(
0619:                                includeHandler[i],
0620:                                RuntimeConstants.EVENTHANDLER_INCLUDE,
0621:                                IncludeEventHandler.class);
0622:                        if (ev != null)
0623:                            eventCartridge
0624:                                    .addIncludeEventHandler((IncludeEventHandler) ev);
0625:                    }
0626:                }
0627:
0628:                String[] invalidReferenceSet = configuration
0629:                        .getStringArray(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES);
0630:                if (invalidReferenceSet != null) {
0631:                    for (int i = 0; i < invalidReferenceSet.length; i++) {
0632:                        EventHandler ev = initializeSpecificEventHandler(
0633:                                invalidReferenceSet[i],
0634:                                RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES,
0635:                                InvalidReferenceEventHandler.class);
0636:                        if (ev != null) {
0637:                            eventCartridge
0638:                                    .addInvalidReferenceEventHandler((InvalidReferenceEventHandler) ev);
0639:                        }
0640:                    }
0641:                }
0642:
0643:            }
0644:
0645:            private EventHandler initializeSpecificEventHandler(
0646:                    String classname, String paramName,
0647:                    Class EventHandlerInterface) throws Exception {
0648:                if (classname != null && classname.length() > 0) {
0649:                    Object o = null;
0650:                    try {
0651:                        o = ClassUtils.getNewInstance(classname);
0652:                    } catch (ClassNotFoundException cnfe) {
0653:                        String err = "The specified class for "
0654:                                + paramName
0655:                                + " ("
0656:                                + classname
0657:                                + ") does not exist or is not accessible to the current classloader.";
0658:                        log.error(err);
0659:                        throw new Exception(err);
0660:                    }
0661:
0662:                    if (!EventHandlerInterface
0663:                            .isAssignableFrom(EventHandlerInterface)) {
0664:                        String err = "The specified class for " + paramName
0665:                                + " (" + classname + ") does not implement "
0666:                                + EventHandlerInterface.getName()
0667:                                + "; Velocity is not initialized correctly.";
0668:
0669:                        log.error(err);
0670:                        throw new Exception(err);
0671:                    }
0672:
0673:                    EventHandler ev = (EventHandler) o;
0674:                    if (ev instanceof  RuntimeServicesAware)
0675:                        ((RuntimeServicesAware) ev).setRuntimeServices(this );
0676:                    return ev;
0677:
0678:                } else
0679:                    return null;
0680:            }
0681:
0682:            /**
0683:             * Initialize the Velocity logging system.
0684:             *
0685:             * @throws Exception
0686:             */
0687:            private void initializeLog() throws Exception {
0688:                // since the Log we started with was just placeholding,
0689:                // let's update it with the real LogChute settings.
0690:                LogManager.updateLog(this .log, this );
0691:            }
0692:
0693:            /**
0694:             * This methods initializes all the directives
0695:             * that are used by the Velocity Runtime. The
0696:             * directives to be initialized are listed in
0697:             * the RUNTIME_DEFAULT_DIRECTIVES properties
0698:             * file.
0699:             *
0700:             * @throws Exception
0701:             */
0702:            private void initializeDirectives() throws Exception {
0703:                /*
0704:                 * Initialize the runtime directive table.
0705:                 * This will be used for creating parsers.
0706:                 */
0707:                runtimeDirectives = new Hashtable();
0708:
0709:                Properties directiveProperties = new Properties();
0710:
0711:                /*
0712:                 * Grab the properties file with the list of directives
0713:                 * that we should initialize.
0714:                 */
0715:
0716:                InputStream inputStream = null;
0717:
0718:                try {
0719:                    inputStream = getClass().getResourceAsStream(
0720:                            '/' + DEFAULT_RUNTIME_DIRECTIVES);
0721:
0722:                    if (inputStream == null) {
0723:                        throw new Exception(
0724:                                "Error loading directive.properties! "
0725:                                        + "Something is very wrong if these properties "
0726:                                        + "aren't being located. Either your Velocity "
0727:                                        + "distribution is incomplete or your Velocity "
0728:                                        + "jar file is corrupted!");
0729:                    }
0730:
0731:                    directiveProperties.load(inputStream);
0732:
0733:                } catch (IOException ioe) {
0734:                    log.error("Error while loading directive properties!", ioe);
0735:                } finally {
0736:                    try {
0737:                        if (inputStream != null) {
0738:                            inputStream.close();
0739:                        }
0740:                    } catch (IOException ioe) {
0741:                        log.error("Cannot close directive properties!", ioe);
0742:                    }
0743:                }
0744:
0745:                /*
0746:                 * Grab all the values of the properties. These
0747:                 * are all class names for example:
0748:                 *
0749:                 * org.apache.velocity.runtime.directive.Foreach
0750:                 */
0751:                Enumeration directiveClasses = directiveProperties.elements();
0752:
0753:                while (directiveClasses.hasMoreElements()) {
0754:                    String directiveClass = (String) directiveClasses
0755:                            .nextElement();
0756:                    loadDirective(directiveClass);
0757:                    log.debug("Loaded System Directive: " + directiveClass);
0758:                }
0759:
0760:                /*
0761:                 *  now the user's directives
0762:                 */
0763:
0764:                String[] userdirective = configuration
0765:                        .getStringArray("userdirective");
0766:
0767:                for (int i = 0; i < userdirective.length; i++) {
0768:                    loadDirective(userdirective[i]);
0769:                    if (log.isInfoEnabled()) {
0770:                        log.info("Loaded User Directive: " + userdirective[i]);
0771:                    }
0772:                }
0773:
0774:            }
0775:
0776:            /**
0777:             *  instantiates and loads the directive with some basic checks
0778:             *
0779:             *  @param directiveClass classname of directive to load
0780:             */
0781:            private void loadDirective(String directiveClass) {
0782:                try {
0783:                    Object o = ClassUtils.getNewInstance(directiveClass);
0784:
0785:                    if (o instanceof  Directive) {
0786:                        Directive directive = (Directive) o;
0787:                        runtimeDirectives.put(directive.getName(), directive);
0788:                    } else {
0789:                        log.error(directiveClass + " does not implement "
0790:                                + Directive.class.getName()
0791:                                + "; it cannot be loaded.");
0792:                    }
0793:                }
0794:                // The ugly threesome:  ClassNotFoundException,
0795:                // IllegalAccessException, InstantiationException.
0796:                // Ignore Findbugs complaint for now.
0797:                catch (Exception e) {
0798:                    log.error("Failed to load Directive: " + directiveClass, e);
0799:                }
0800:            }
0801:
0802:            /**
0803:             * Initializes the Velocity parser pool.
0804:             */
0805:            private void initializeParserPool() throws Exception {
0806:                /*
0807:                 * Which parser pool?
0808:                 */
0809:                String pp = getString(RuntimeConstants.PARSER_POOL_CLASS);
0810:
0811:                if (pp != null && pp.length() > 0) {
0812:                    /*
0813:                     *  if something was specified, then make one.
0814:                     *  if that isn't a ParserPool, consider
0815:                     *  this a huge error and throw
0816:                     */
0817:
0818:                    Object o = null;
0819:
0820:                    try {
0821:                        o = ClassUtils.getNewInstance(pp);
0822:                    } catch (ClassNotFoundException cnfe) {
0823:                        String err = "The specified class for ParserPool ("
0824:                                + pp
0825:                                + ") does not exist (or is not accessible to the current classloader.";
0826:                        log.error(err);
0827:                        throw new Exception(err);
0828:                    }
0829:
0830:                    if (!(o instanceof  ParserPool)) {
0831:                        String err = "The specified class for ParserPool ("
0832:                                + pp + ") does not implement "
0833:                                + ParserPool.class
0834:                                + " Velocity not initialized correctly.";
0835:
0836:                        log.error(err);
0837:                        throw new Exception(err);
0838:                    }
0839:
0840:                    parserPool = (ParserPool) o;
0841:
0842:                    parserPool.initialize(this );
0843:                } else {
0844:                    /*
0845:                     *  someone screwed up.  Lets not fool around...
0846:                     */
0847:
0848:                    String err = "It appears that no class was specified as the"
0849:                            + " ParserPool.  Please ensure that all configuration"
0850:                            + " information is correct.";
0851:
0852:                    log.error(err);
0853:                    throw new Exception(err);
0854:                }
0855:
0856:            }
0857:
0858:            /**
0859:             * Returns a JavaCC generated Parser.
0860:             *
0861:             * @return Parser javacc generated parser
0862:             */
0863:            public Parser createNewParser() {
0864:                /* must be initialized before we use runtimeDirectives */
0865:                if (!initialized && !initializing) {
0866:                    log
0867:                            .debug("Velocity was not initialized! Calling init()...");
0868:                    try {
0869:                        init();
0870:                    } catch (Exception e) {
0871:                        getLog().error("Could not auto-initialize Velocity", e);
0872:                        throw new IllegalStateException(
0873:                                "Velocity could not be initialized!");
0874:                    }
0875:                }
0876:
0877:                Parser parser = new Parser(this );
0878:                parser.setDirectives(runtimeDirectives);
0879:                return parser;
0880:            }
0881:
0882:            /**
0883:             * Parse the input and return the root of
0884:             * AST node structure.
0885:             * <br><br>
0886:             *  In the event that it runs out of parsers in the
0887:             *  pool, it will create and let them be GC'd
0888:             *  dynamically, logging that it has to do that.  This
0889:             *  is considered an exceptional condition.  It is
0890:             *  expected that the user will set the
0891:             *  PARSER_POOL_SIZE property appropriately for their
0892:             *  application.  We will revisit this.
0893:             *
0894:             * @param reader Reader retrieved by a resource loader
0895:             * @param templateName name of the template being parsed
0896:             * @return A root node representing the template as an AST tree.
0897:             * @throws ParseException When the template could not be parsed.
0898:             */
0899:            public SimpleNode parse(Reader reader, String templateName)
0900:                    throws ParseException {
0901:                /*
0902:                 *  do it and dump the VM namespace for this template
0903:                 */
0904:                return parse(reader, templateName, true);
0905:            }
0906:
0907:            /**
0908:             *  Parse the input and return the root of the AST node structure.
0909:             *
0910:             * @param reader Reader retrieved by a resource loader
0911:             * @param templateName name of the template being parsed
0912:             * @param dumpNamespace flag to dump the Velocimacro namespace for this template
0913:             * @return A root node representing the template as an AST tree.
0914:             * @throws ParseException When the template could not be parsed.
0915:             */
0916:            public SimpleNode parse(Reader reader, String templateName,
0917:                    boolean dumpNamespace) throws ParseException {
0918:                /* must be initialized before using parserPool */
0919:                if (!initialized && !initializing) {
0920:                    log
0921:                            .debug("Velocity was not initialized! Calling init()...");
0922:                    try {
0923:                        init();
0924:                    } catch (Exception e) {
0925:                        getLog().error("Could not auto-initialize Velocity", e);
0926:                        throw new IllegalStateException(
0927:                                "Velocity could not be initialized!");
0928:                    }
0929:                }
0930:
0931:                SimpleNode ast = null;
0932:                Parser parser = (Parser) parserPool.get();
0933:
0934:                if (parser == null) {
0935:                    /*
0936:                     *  if we couldn't get a parser from the pool
0937:                     *  make one and log it.
0938:                     */
0939:
0940:                    if (log.isInfoEnabled()) {
0941:                        log
0942:                                .info("Runtime : ran out of parsers. Creating a new one. "
0943:                                        + " Please increment the parser.pool.size property."
0944:                                        + " The current value is too small.");
0945:                    }
0946:
0947:                    parser = createNewParser();
0948:
0949:                }
0950:
0951:                /*
0952:                 *  now, if we have a parser
0953:                 */
0954:
0955:                if (parser != null) {
0956:                    try {
0957:                        /*
0958:                         *  dump namespace if we are told to.  Generally, you want to
0959:                         *  do this - you don't in special circumstances, such as
0960:                         *  when a VM is getting init()-ed & parsed
0961:                         */
0962:
0963:                        if (dumpNamespace) {
0964:                            dumpVMNamespace(templateName);
0965:                        }
0966:
0967:                        ast = parser.parse(reader, templateName);
0968:                    } finally {
0969:                        /*
0970:                         *  put it back
0971:                         */
0972:                        parserPool.put(parser);
0973:
0974:                    }
0975:                } else {
0976:                    log
0977:                            .error("Runtime : ran out of parsers and unable to create more.");
0978:                }
0979:                return ast;
0980:            }
0981:
0982:            /**
0983:             * Returns a <code>Template</code> from the resource manager.
0984:             * This method assumes that the character encoding of the
0985:             * template is set by the <code>input.encoding</code>
0986:             * property.  The default is "ISO-8859-1"
0987:             *
0988:             * @param name The file name of the desired template.
0989:             * @return     The template.
0990:             * @throws ResourceNotFoundException if template not found
0991:             *          from any available source.
0992:             * @throws ParseErrorException if template cannot be parsed due
0993:             *          to syntax (or other) error.
0994:             * @throws Exception if an error occurs in template initialization
0995:             */
0996:            public Template getTemplate(String name)
0997:                    throws ResourceNotFoundException, ParseErrorException,
0998:                    Exception {
0999:                return getTemplate(name, getString(INPUT_ENCODING,
1000:                        ENCODING_DEFAULT));
1001:            }
1002:
1003:            /**
1004:             * Returns a <code>Template</code> from the resource manager
1005:             *
1006:             * @param name The  name of the desired template.
1007:             * @param encoding Character encoding of the template
1008:             * @return     The template.
1009:             * @throws ResourceNotFoundException if template not found
1010:             *          from any available source.
1011:             * @throws ParseErrorException if template cannot be parsed due
1012:             *          to syntax (or other) error.
1013:             * @throws Exception if an error occurs in template initialization
1014:             */
1015:            public Template getTemplate(String name, String encoding)
1016:                    throws ResourceNotFoundException, ParseErrorException,
1017:                    Exception {
1018:                /* must be initialized before using resourceManager */
1019:                if (!initialized && !initializing) {
1020:                    log.info("Velocity not initialized yet. Calling init()...");
1021:                    init();
1022:                }
1023:
1024:                return (Template) resourceManager.getResource(name,
1025:                        ResourceManager.RESOURCE_TEMPLATE, encoding);
1026:            }
1027:
1028:            /**
1029:             * Returns a static content resource from the
1030:             * resource manager.  Uses the current value
1031:             * if INPUT_ENCODING as the character encoding.
1032:             *
1033:             * @param name Name of content resource to get
1034:             * @return parsed ContentResource object ready for use
1035:             * @throws ResourceNotFoundException if template not found
1036:             *          from any available source.
1037:             * @throws ParseErrorException When the template could not be parsed.
1038:             * @throws Exception Any other error.
1039:             */
1040:            public ContentResource getContent(String name)
1041:                    throws ResourceNotFoundException, ParseErrorException,
1042:                    Exception {
1043:                /*
1044:                 *  the encoding is irrelvant as we don't do any converstion
1045:                 *  the bytestream should be dumped to the output stream
1046:                 */
1047:
1048:                return getContent(name, getString(INPUT_ENCODING,
1049:                        ENCODING_DEFAULT));
1050:            }
1051:
1052:            /**
1053:             * Returns a static content resource from the
1054:             * resource manager.
1055:             *
1056:             * @param name Name of content resource to get
1057:             * @param encoding Character encoding to use
1058:             * @return parsed ContentResource object ready for use
1059:             * @throws ResourceNotFoundException if template not found
1060:             *          from any available source.
1061:             * @throws ParseErrorException When the template could not be parsed.
1062:             * @throws Exception Any other error.
1063:             */
1064:            public ContentResource getContent(String name, String encoding)
1065:                    throws ResourceNotFoundException, ParseErrorException,
1066:                    Exception {
1067:                /* must be initialized before using resourceManager */
1068:                if (!initialized && !initializing) {
1069:                    log.info("Velocity not initialized yet. Calling init()...");
1070:                    init();
1071:                }
1072:
1073:                return (ContentResource) resourceManager.getResource(name,
1074:                        ResourceManager.RESOURCE_CONTENT, encoding);
1075:            }
1076:
1077:            /**
1078:             *  Determines if a template exists and returns name of the loader that
1079:             *  provides it.  This is a slightly less hokey way to support
1080:             *  the Velocity.resourceExists() utility method, which was broken
1081:             *  when per-template encoding was introduced.  We can revisit this.
1082:             *
1083:             *  @param resourceName Name of template or content resource
1084:             *  @return class name of loader than can provide it
1085:             */
1086:            public String getLoaderNameForResource(String resourceName) {
1087:                /* must be initialized before using resourceManager */
1088:                if (!initialized && !initializing) {
1089:                    log
1090:                            .debug("Velocity was not initialized! Calling init()...");
1091:                    try {
1092:                        init();
1093:                    } catch (Exception e) {
1094:                        getLog().error("Could not initialize Velocity", e);
1095:                        throw new IllegalStateException(
1096:                                "Velocity could not be initialized!");
1097:                    }
1098:                }
1099:
1100:                return resourceManager.getLoaderNameForResource(resourceName);
1101:            }
1102:
1103:            /**
1104:             * Returns a convenient Log instance that wraps the current LogChute.
1105:             * Use this to log error messages. It has the usual methods.
1106:             *
1107:             * @return A convenience Log instance that wraps the current LogChute.
1108:             */
1109:            public Log getLog() {
1110:                return log;
1111:            }
1112:
1113:            /**
1114:             * @deprecated Use getLog() and call warn() on it.
1115:             * @see Log#warn(Object)
1116:             * @param message The message to log.
1117:             */
1118:            public void warn(Object message) {
1119:                getLog().warn(message);
1120:            }
1121:
1122:            /**
1123:             * @deprecated Use getLog() and call info() on it.
1124:             * @see Log#info(Object)
1125:             * @param message The message to log.
1126:             */
1127:            public void info(Object message) {
1128:                getLog().info(message);
1129:            }
1130:
1131:            /**
1132:             * @deprecated Use getLog() and call error() on it.
1133:             * @see Log#error(Object)
1134:             * @param message The message to log.
1135:             */
1136:            public void error(Object message) {
1137:                getLog().error(message);
1138:            }
1139:
1140:            /**
1141:             * @deprecated Use getLog() and call debug() on it.
1142:             * @see Log#debug(Object)
1143:             * @param message The message to log.
1144:             */
1145:            public void debug(Object message) {
1146:                getLog().debug(message);
1147:            }
1148:
1149:            /**
1150:             * String property accessor method with default to hide the
1151:             * configuration implementation.
1152:             *
1153:             * @param key property key
1154:             * @param defaultValue  default value to return if key not
1155:             *               found in resource manager.
1156:             * @return value of key or default
1157:             */
1158:            public String getString(String key, String defaultValue) {
1159:                return configuration.getString(key, defaultValue);
1160:            }
1161:
1162:            /**
1163:             * Returns the appropriate VelocimacroProxy object if strVMname
1164:             * is a valid current Velocimacro.
1165:             *
1166:             * @param vmName Name of velocimacro requested
1167:             * @param templateName Name of the template that contains the velocimacro.
1168:             * @return The requested VelocimacroProxy.
1169:             */
1170:            public Directive getVelocimacro(String vmName, String templateName) {
1171:                return vmFactory.getVelocimacro(vmName, templateName);
1172:            }
1173:
1174:            /**
1175:             * Adds a new Velocimacro. Usually called by Macro only while parsing.
1176:             *
1177:             * @param name Name of velocimacro
1178:             * @param macro String form of macro body
1179:             * @param argArray Array of strings, containing the
1180:             *                         #macro() arguments.  the 0th is the name.
1181:             * @param sourceTemplate Name of the template that contains the velocimacro.
1182:             * @return True if added, false if rejected for some
1183:             *                  reason (either parameters or permission settings)
1184:             */
1185:            public boolean addVelocimacro(String name, String macro,
1186:                    String argArray[], String sourceTemplate) {
1187:                return vmFactory.addVelocimacro(name, macro, argArray,
1188:                        sourceTemplate);
1189:            }
1190:
1191:            /**
1192:             *  Checks to see if a VM exists
1193:             *
1194:             * @param vmName Name of the Velocimacro.
1195:             * @param templateName Template on which to look for the Macro.
1196:             * @return True if VM by that name exists, false if not
1197:             */
1198:            public boolean isVelocimacro(String vmName, String templateName) {
1199:                return vmFactory.isVelocimacro(vmName, templateName);
1200:            }
1201:
1202:            /**
1203:             * tells the vmFactory to dump the specified namespace.  This is to support
1204:             * clearing the VM list when in inline-VM-local-scope mode
1205:             * @param namespace Namespace to dump.
1206:             * @return True if namespace was dumped successfully.
1207:             */
1208:            public boolean dumpVMNamespace(String namespace) {
1209:                return vmFactory.dumpVMNamespace(namespace);
1210:            }
1211:
1212:            /* --------------------------------------------------------------------
1213:             * R U N T I M E  A C C E S S O R  M E T H O D S
1214:             * --------------------------------------------------------------------
1215:             * These are the getXXX() methods that are a simple wrapper
1216:             * around the configuration object. This is an attempt
1217:             * to make a the Velocity Runtime the single access point
1218:             * for all things Velocity, and allow the Runtime to
1219:             * adhere as closely as possible the the Mediator pattern
1220:             * which is the ultimate goal.
1221:             * --------------------------------------------------------------------
1222:             */
1223:
1224:            /**
1225:             * String property accessor method to hide the configuration implementation
1226:             * @param key  property key
1227:             * @return   value of key or null
1228:             */
1229:            public String getString(String key) {
1230:                return StringUtils.nullTrim(configuration.getString(key));
1231:            }
1232:
1233:            /**
1234:             * Int property accessor method to hide the configuration implementation.
1235:             *
1236:             * @param key Property key
1237:             * @return value
1238:             */
1239:            public int getInt(String key) {
1240:                return configuration.getInt(key);
1241:            }
1242:
1243:            /**
1244:             * Int property accessor method to hide the configuration implementation.
1245:             *
1246:             * @param key  property key
1247:             * @param defaultValue The default value.
1248:             * @return value
1249:             */
1250:            public int getInt(String key, int defaultValue) {
1251:                return configuration.getInt(key, defaultValue);
1252:            }
1253:
1254:            /**
1255:             * Boolean property accessor method to hide the configuration implementation.
1256:             *
1257:             * @param key property key
1258:             * @param def The default value if property not found.
1259:             * @return value of key or default value
1260:             */
1261:            public boolean getBoolean(String key, boolean def) {
1262:                return configuration.getBoolean(key, def);
1263:            }
1264:
1265:            /**
1266:             * Return the velocity runtime configuration object.
1267:             *
1268:             * @return Configuration object which houses the Velocity runtime
1269:             * properties.
1270:             */
1271:            public ExtendedProperties getConfiguration() {
1272:                return configuration;
1273:            }
1274:
1275:            /**
1276:             *  Return the Introspector for this instance
1277:             * @return The Introspector for this instance
1278:             */
1279:            public Introspector getIntrospector() {
1280:                return introspector;
1281:            }
1282:
1283:            /**
1284:             * Returns the event handlers for the application.
1285:             * @return The event handlers for the application.
1286:             */
1287:            public EventCartridge getApplicationEventCartridge() {
1288:                return eventCartridge;
1289:            }
1290:
1291:            /**
1292:             *  Gets the application attribute for the given key
1293:             *
1294:             * @param key
1295:             * @return The application attribute for the given key.
1296:             */
1297:            public Object getApplicationAttribute(Object key) {
1298:                return applicationAttributes.get(key);
1299:            }
1300:
1301:            /**
1302:             *   Sets the application attribute for the given key
1303:             *
1304:             * @param key
1305:             * @param o The new application attribute.
1306:             * @return The old value of this attribute or null if it hasn't been set before.
1307:             */
1308:            public Object setApplicationAttribute(Object key, Object o) {
1309:                return applicationAttributes.put(key, o);
1310:            }
1311:
1312:            /**
1313:             * Returns the Uberspect object for this Instance.
1314:             *
1315:             * @return The Uberspect object for this Instance.
1316:             */
1317:            public Uberspect getUberspect() {
1318:                return uberSpect;
1319:            }
1320:
1321:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.