You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by wg...@apache.org on 2005/09/12 00:24:43 UTC

svn commit: r280189 [1/2] - in /jakarta/velocity/core/trunk: ./ build/ build/lib/ src/java/org/apache/velocity/app/event/ src/java/org/apache/velocity/app/event/implement/ src/java/org/apache/velocity/context/ src/java/org/apache/velocity/runtime/ src/...

Author: wglass
Date: Sun Sep 11 15:24:20 2005
New Revision: 280189

URL: http://svn.apache.org/viewcvs?rev=280189&view=rev
Log:
Enhanced event handler system.
* New handler: IncludeEventHandler
* All handlers have access to context & runtime services
* Handlers can be specified in velocity.properties
* Handlers can chain together to combine effects
* Includes implementation of useful handlers including HTML and other forms of text escaping.
* 100% backwards compatible

This is based upon the code from
http://issues.apache.org/bugzilla/show_bug.cgi?id=28388

Added:
    jakarta/velocity/core/trunk/build/lib/commons-lang-2.1.jar   (with props)
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ContextAware.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandlerUtil.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/IncludeEventHandler.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/RuntimeServicesAware.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeHtmlReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeJavaScriptReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeSqlReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeXmlReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeNotFound.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeRelativePath.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/PrintExceptions.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/BuiltInEventHandlerTest.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/FilteredEventHandlingTestCase.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/IncludeEventHandlingTestCase.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/eventhandler/
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/eventhandler/Handler1.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/eventhandler/Handler2.java
    jakarta/velocity/core/trunk/test/includeevent/
    jakarta/velocity/core/trunk/test/includeevent/compare/
    jakarta/velocity/core/trunk/test/includeevent/compare/test1.cmp
    jakarta/velocity/core/trunk/test/includeevent/compare/test2.cmp
    jakarta/velocity/core/trunk/test/includeevent/compare/test3.cmp
    jakarta/velocity/core/trunk/test/includeevent/compare/test4.cmp
    jakarta/velocity/core/trunk/test/includeevent/compare/test5.cmp
    jakarta/velocity/core/trunk/test/includeevent/compare/test6.vm
    jakarta/velocity/core/trunk/test/includeevent/include-a.vm
    jakarta/velocity/core/trunk/test/includeevent/include-b.vm
    jakarta/velocity/core/trunk/test/includeevent/include4.vm
    jakarta/velocity/core/trunk/test/includeevent/include5.vm
    jakarta/velocity/core/trunk/test/includeevent/notfound.vm
    jakarta/velocity/core/trunk/test/includeevent/parse-a.vm
    jakarta/velocity/core/trunk/test/includeevent/parse-b.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/
    jakarta/velocity/core/trunk/test/includeevent/subdir/include-b.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/include4.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/include5.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/notfound.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/parse-b.vm
    jakarta/velocity/core/trunk/test/includeevent/subdir/test2.vm
    jakarta/velocity/core/trunk/test/includeevent/test1.vm
    jakarta/velocity/core/trunk/test/includeevent/test3.vm
    jakarta/velocity/core/trunk/test/includeevent/test4.vm
    jakarta/velocity/core/trunk/test/includeevent/test5.vm
    jakarta/velocity/core/trunk/test/includeevent/test6.vm
Modified:
    jakarta/velocity/core/trunk/build/build.xml
    jakarta/velocity/core/trunk/build/testcases.xml
    jakarta/velocity/core/trunk/project.xml
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventCartridge.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandler.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/MethodExceptionEventHandler.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/NullSetEventHandler.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/context/VMContext.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeServices.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/defaults/velocity.properties
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/directive/Include.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/EventHandlingTestCase.java
    jakarta/velocity/core/trunk/src/java/org/apache/velocity/test/misc/Test.java

Modified: jakarta/velocity/core/trunk/build/build.xml
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/build/build.xml?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/build/build.xml (original)
+++ jakarta/velocity/core/trunk/build/build.xml Sun Sep 11 15:24:20 2005
@@ -44,6 +44,7 @@
   <property name="log.jar" value="lib/logkit-1.0.1.jar"/>
   <property name="oro.jar" value="lib/oro.jar"/>
   <property name="collections.jar" value="lib/commons-collections.jar" />
+  <property name="lang.jar" value="lib/commons-lang-2.1.jar" />
 
   <!-- PDF generation using FOP -->
   <property name="xdocs.dir" value="../xdocs"/>
@@ -269,6 +270,7 @@
          
     <unzip src="${log.jar}" dest="${build.dest}"/>
     <unzip src="${oro.jar}" dest="${build.dest}"/>
+    <unzip src="${lang.jar}" dest="${build.dest}"/>
  
     <delete dir="${build.dest}/meta-inf" quiet="true"/>
 
@@ -309,6 +311,7 @@
         
     <unzip src="${log.jar}" dest="${build.dest}"/>
     <unzip src="${oro.jar}" dest="${build.dest}"/>
+    <unzip src="${lang.jar}" dest="${build.dest}"/>
 
     <delete dir="${build.dest}/meta-inf" quiet="true"/>
 

Added: jakarta/velocity/core/trunk/build/lib/commons-lang-2.1.jar
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/build/lib/commons-lang-2.1.jar?rev=280189&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/velocity/core/trunk/build/lib/commons-lang-2.1.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: jakarta/velocity/core/trunk/build/testcases.xml
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/build/testcases.xml?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/build/testcases.xml (original)
+++ jakarta/velocity/core/trunk/build/testcases.xml Sun Sep 11 15:24:20 2005
@@ -78,7 +78,10 @@
                                    test-foreach,
                                    test-arithmetic,
                                    test-number-methods,
-                                   test-anakia 
+                                   test-anakia,
+                                   test-includeeventhandler,
+                                   test-filteredeventhandler,
+                                   test-builtineventhandler                                   
                                    "/>
 
   <target name="test-template">
@@ -442,5 +445,38 @@
       </classpath>
     </java>
   </target>
+
+ <target name="test-includeeventhandler">
+    <echo message="Running IncludeEvent Handler tests..."/>
+
+    <java classname="${velocity.test.runner}" fork="yes" failonerror="${testbed.failonerror}">
+      <arg value="org.apache.velocity.test.IncludeEventHandlingTestCase"/>
+      <classpath>
+        <path refid="classpath"/>
+      </classpath>
+    </java>
+   </target>
+   
+ <target name="test-filteredeventhandler">
+    <echo message="Running Filtered Event Handler tests..."/>
+
+    <java classname="${velocity.test.runner}" fork="yes" failonerror="${testbed.failonerror}">
+      <arg value="org.apache.velocity.test.FilteredEventHandlingTestCase"/>
+      <classpath>
+        <path refid="classpath"/>
+      </classpath>
+    </java>
+ </target>
+
+ <target name="test-builtineventhandler">
+    <echo message="Running Built-In Event Handler tests..."/>
+
+    <java classname="${velocity.test.runner}" fork="yes" failonerror="${testbed.failonerror}">
+      <arg value="org.apache.velocity.test.BuiltInEventHandlerTest"/>
+      <classpath>
+        <path refid="classpath"/>
+      </classpath>
+    </java>
+   </target>
 
 </project>

Modified: jakarta/velocity/core/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/project.xml?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/project.xml (original)
+++ jakarta/velocity/core/trunk/project.xml Sun Sep 11 15:24:20 2005
@@ -26,7 +26,7 @@
   <shortDescription>Velocity is a Java-based template engine</shortDescription>
 
   <url>http://jakarta.apache.org/velocity/</url>
-  <issueTrackingUrl>http://nagoya.apache.org/scarab/servlet/scarab/</issueTrackingUrl>
+  <issueTrackingUrl>http://issues.apache.org/jira/browse/VELOCITY</issueTrackingUrl>
   <siteAddress>jakarta.apache.org</siteAddress>
   <siteDirectory>/www/jakarta.apache.org/velocity/</siteDirectory>
   <distributionDirectory>/www/jakarta.apache.org/builds/jakarta-velocity/</distributionDirectory>
@@ -42,7 +42,7 @@
 
   <mailingLists>
     <mailingList>
-      <name>Maven User List</name>
+      <name>Velocity User List</name>
       <subscribe>velocity-user-subscribe@jakarta.apache.org</subscribe>
       <unsubscribe>velocity-user-unsubscribe@jakarta.apache.org</unsubscribe>
       <!-- Using mail-archive until there is something in nagoya's eyebrowse...
@@ -51,7 +51,7 @@
       <archive>http://www.mail-archive.com/velocity-user@jakarta.apache.org/</archive>
     </mailingList>
     <mailingList>
-      <name>Maven Developer List</name>
+      <name>Velocity Developer List</name>
       <subscribe>velocity-dev-subscribe@jakarta.apache.org</subscribe>
       <unsubscribe>velocity-dev-unsubscribe@jakarta.apache.org</unsubscribe>
       <!-- Using mail-archive until there is something in nagoya's eyebrowse...
@@ -64,16 +64,16 @@
   <developers>
 
     <developer>
-      <name>Bob McWhirter</name>
-      <id>werken</id>
-      <email>bob@werken.com</email>
-      <organization>Werken and Sons</organization>
+      <name>Will Glass-Husain</name>
+      <id>wglass</id>
+      <email>wglass@forio.com</email>
+      <organization>Forio Business Simulations</organization>
       <roles>
         <role>Java Developer</role>
       </roles>
     </developer>
 
-    <developer>
+   <developer>
       <name>Geir Magnusson Jr.</name>
       <id>geirm</id>
       <email>geirm@optonline.net</email>
@@ -93,26 +93,6 @@
       </roles>
     </developer>
 
-    <developer>
-      <name>Jon Stevens</name>
-      <id>jon</id>
-      <email>jon@latchkey.com</email>
-      <organization>CollabNet, Inc.</organization>
-      <roles>
-        <role>Java Developer</role>
-      </roles>
-    </developer>
-
-    <developer>
-      <name>Jason van Zyl</name>
-      <id>jvanzyl</id>
-      <email>jason@zenplex.com</email>
-      <organization>Zenplex</organization>
-      <roles>
-        <role>Architect</role>
-      </roles>
-    </developer>
-
   </developers>
 
   <contributors/>
@@ -132,6 +112,11 @@
     <dependency>
       <id>commons-collections</id>
       <version>2.0</version>
+    </dependency>
+
+    <dependency>
+      <id>commons-lang</id>
+      <version>2.1</version>
     </dependency>
 
     <dependency>

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ContextAware.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ContextAware.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ContextAware.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ContextAware.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,37 @@
+package org.apache.velocity.app.event;
+
+import org.apache.velocity.context.Context;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Event handlers implementing this interface will automatically
+ * have the method setContext called before each event.  This
+ * allows the event handler to use information in the latest context
+ * when responding to the event.
+ *
+ * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain</a>
+ * @version $Id: GlobalEventHandler.java,v 1.4 2004/03/19 17:13:33 dlr Exp $
+ */
+public interface  ContextAware
+{
+    /**
+     * Initialize the EventHandler.
+     */
+    public void setContext( Context context );
+
+}

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventCartridge.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventCartridge.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventCartridge.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventCartridge.java Sun Sep 11 15:24:20 2005
@@ -16,23 +16,48 @@
  * limitations under the License.
  */
 
-import org.apache.velocity.context.InternalEventContext;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
 import org.apache.velocity.context.Context;
+import org.apache.velocity.context.InternalEventContext;
+import org.apache.velocity.runtime.RuntimeServices;
 
 /**
- *  'Package' of event handlers...
+ * Stores the event handlers. Event handlers can be assigned on a per
+ * VelocityEngine instance basis by specifying the class names in the
+ * velocity.properties file. Event handlers may also be assigned on a per-page
+ * basis by creating a new instance of EventCartridge, adding the event
+ * handlers, and then calling attachToContext. For clarity, it's recommended
+ * that one approach or the other be followed, as the second method is primarily
+ * presented for backwards compatibility.
  *
- * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
- * @author <a href="mailto:j_a_fernandez@yahoo.com">Jose Alberto Fernandez</a>
+ * <P>
+ * Note that Event Handlers follow a filter pattern, with multiple event
+ * handlers allowed for each event. When the appropriate event occurs, all the
+ * appropriate event handlers are called in the sequence they were added to the
+ * Event Cartridge. See the javadocs of the specific event handler interfaces
+ * for more details.
+ *
+ * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a>
+ * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr. </a>
+ * @author <a href="mailto:j_a_fernandez@yahoo.com">Jose Alberto Fernandez </a>
  * @version $Id$
  */
-public class EventCartridge implements ReferenceInsertionEventHandler,
-                                       NullSetEventHandler,
-                                       MethodExceptionEventHandler
-{
-    private ReferenceInsertionEventHandler rieh = null;
-    private NullSetEventHandler nseh = null;
-    private MethodExceptionEventHandler meeh = null;
+public class EventCartridge
+  {
+    private List ReferenceHandlers = new ArrayList();
+    private List NullSetHandlers = new ArrayList();
+    private List MethodExceptionHandlers = new ArrayList();
+    private List IncludeHandlers = new ArrayList();
+
+    /**
+     * Ensure that handlers are not initialized more than once.
+     */
+    Set initializedHandlers = new HashSet();
 
     /**
      *  Adds an event handler(s) to the Cartridge.  This method
@@ -48,39 +73,86 @@
         {
             return false;
         }
-        
+
         boolean found = false;
 
         if ( ev instanceof ReferenceInsertionEventHandler)
         {
-            rieh = (ReferenceInsertionEventHandler) ev;
+            addReferenceInsertionEventHandler( (ReferenceInsertionEventHandler) ev );
             found = true;
         }
-       
+
         if ( ev instanceof NullSetEventHandler )
         {
-            nseh = (NullSetEventHandler) ev;
+            addNullSetEventHandler( (NullSetEventHandler) ev );
             found = true;
         }
 
         if ( ev instanceof MethodExceptionEventHandler )
         {
-            meeh = (MethodExceptionEventHandler) ev;
+            addMethodExceptionHandler( (MethodExceptionEventHandler) ev );
             found = true;
         }
- 
+        if ( ev instanceof IncludeEventHandler )
+        {
+            addIncludeEventHandler( (IncludeEventHandler) ev );
+            found = true;
+        }
+
         return found;
     }
-    
+
     /**
-     *  Removes an event handler(s) from the Cartridge.  This method
-     *  will find all possible event handler interfaces supported
-     *  by the passed in object and remove them.
+      *  Add a reference insertion event handler to the Cartridge.
+      *
+      *  @param ev ReferenceInsertionEventHandler
+     */
+     public void addReferenceInsertionEventHandler( ReferenceInsertionEventHandler ev )
+     {
+         ReferenceHandlers.add( ev );
+     }
+
+    /**
+      *  Add a null set event handler to the Cartridge.
+      *
+      *  @param ev NullSetEventHandler
+      */
+     public void addNullSetEventHandler( NullSetEventHandler ev )
+     {
+         NullSetHandlers.add( ev );
+     }
+
+    /**
+     *  Add a method exception event handler to the Cartridge.
      *
-     *  @param ev object impementing a valid EventHandler-derived interface
-     *  @return true if a supported interface, false otherwise or if null
+     *  @param ev MethodExceptionEventHandler
      */
-    public boolean removeEventHandler(EventHandler ev)
+    public void addMethodExceptionHandler( MethodExceptionEventHandler ev )
+    {
+        MethodExceptionHandlers.add( ev );
+    }
+
+    /**
+     *  Add an include event handler to the Cartridge.
+     *
+     *  @param ev IncludeEventHandler
+     */
+    public void addIncludeEventHandler( IncludeEventHandler ev )
+    {
+        IncludeHandlers.add( ev );
+    }
+
+
+    /**
+     * Removes an event handler(s) from the Cartridge. This method will find all
+     * possible event handler interfaces supported by the passed in object and
+     * remove them.
+     *
+     * @param ev  object impementing a valid EventHandler-derived interface
+     * @return true if event handler was previously registered, false if not
+     *         found
+     */
+    public boolean removeEventHandler( EventHandler ev )
     {
         if ( ev == null )
         {
@@ -88,99 +160,58 @@
         }
 
         boolean found = false;
-        
-        if (ev == rieh) 
-        {
-            rieh = null;
-            found = true;
-        }
-	
-        if (ev == nseh) 
-        {
-            nseh = null;
-            found = true;
-        }
 
-        if (ev == meeh) 
-        {
-            meeh = null;
-            found = true;
-        }
+        if ( ev instanceof ReferenceInsertionEventHandler )
+            return ReferenceHandlers.remove( ev );
+
+        if ( ev instanceof NullSetEventHandler )
+            return NullSetHandlers.remove( ev );
+
+        if ( ev instanceof MethodExceptionEventHandler )
+            return MethodExceptionHandlers.remove(ev );
+
+        if ( ev instanceof IncludeEventHandler )
+            return IncludeHandlers.remove( ev );
 
         return found;
     }
 
     /**
-     *  Implementation of ReferenceInsertionEventHandler method
-     *  <code>referenceInsert()</code>.
-     *
-     *  Called during Velocity merge before a reference value will
-     *  be inserted into the output stream.
-     *
-     *  @param reference reference from template about to be inserted
-     *  @param value  value about to be inserted (after toString() )
-     *  @return Object on which toString() should be called for output.
+     * Iterate through all the stored ReferenceInsertionEventHandler objects
+     * @return iterator of handler objects
      */
-    public Object referenceInsert( String reference, Object value  )
+    public Iterator getReferenceInsertionEventHandlers()
     {
-        if (rieh == null)
-        {
-            return value;
-        }
-
-        return rieh.referenceInsert( reference, value );
+        return ReferenceHandlers.iterator();
     }
 
     /**
-     *  Implementation of NullSetEventHandler method
-     *  <code>shouldLogOnNullSet()</code>.
-     *
-     *  Called during Velocity merge to determine if when
-     *  a #set() results in a null assignment, a warning
-     *  is logged.
-     *
-     *  @param reference reference from template about to be inserted
-     *  @return true if to be logged, false otherwise
+     * Iterate through all the stored NullSetEventHandler objects
+     * @return iterator of handler objects
      */
-    public boolean shouldLogOnNullSet( String lhs, String rhs )
+    public Iterator getNullSetEventHandlers()
     {
-        if ( nseh == null)
-        {
-            return true;
-        }
-
-        return nseh.shouldLogOnNullSet( lhs, rhs );
+        return NullSetHandlers.iterator();
     }
-    
+
     /**
-     *  Implementation of MethodExceptionEventHandler  method
-     *  <code>methodException()</code>.
-     *
-     *  Called during Velocity merge if a reference is null
-     *
-     *  @param claz  Class that is causing the exception
-     *  @param method method called that causes the exception
-     *  @param e Exception thrown by the method
-     *  @return Object to return as method result
-     *  @throws exception to be wrapped and propogated to app  
+     * Iterate through all the stored MethodExceptionEventHandler objects
+     * @return iterator of handler objects
      */
-    public Object methodException( Class claz, String method, Exception e )
-        throws Exception
+    public Iterator getMethodExceptionEventHandlers()
     {
-        /*
-         *  if we don't have a handler, just throw what we were handed
-         */
-        if (meeh == null)
-        {
-            throw e;
-        }
+        return MethodExceptionHandlers.iterator();
+    }
 
-        /*
-         *  otherwise, call it..
-         */
-        return meeh.methodException( claz, method, e );
+    /**
+     * Iterate through all the stored IncludeEventHandlers objects
+     * @return iterator of handler objects
+     */
+    public Iterator getIncludeEventHandlers()
+    {
+        return IncludeHandlers.iterator();
     }
-    
+
     /**
      *  Attached the EventCartridge to the context
      *
@@ -192,11 +223,18 @@
     public final boolean attachToContext( Context context )
     {
         if (  context instanceof InternalEventContext )
-        {         
+        {
             InternalEventContext iec = (InternalEventContext) context;
 
             iec.attachEventCartridge( this );
 
+            /**
+             * while it's tempting to call setContext on each handler from here,
+             * this needs to be done before each method call.  This is
+             * because the specific context will change as inner contexts
+             * are linked in through macros, foreach, or directly by the user.
+             */
+
             return true;
         }
         else
@@ -204,4 +242,60 @@
             return false;
         }
     }
+
+    /**
+     * Initialize the handlers.  For global handlers this is called when Velocity
+     * is initialized. For local handlers this is called when the first handler
+     * is executed.  Handlers will not be initialized more than once.
+     */
+    public void initialize (RuntimeServices rs) throws Exception
+    {
+
+        for ( Iterator i = ReferenceHandlers.iterator(); i.hasNext(); )
+        {
+            EventHandler eh = ( EventHandler ) i.next();
+            if ( (eh instanceof RuntimeServicesAware) &&
+                    !initializedHandlers.contains(eh) )
+            {
+                ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
+                initializedHandlers.add( eh );
+            }
+        }
+
+        for ( Iterator i = NullSetHandlers.iterator(); i.hasNext(); )
+        {
+            EventHandler eh = ( EventHandler ) i.next();
+            if ( (eh instanceof RuntimeServicesAware) &&
+                    !initializedHandlers.contains(eh) )
+            {
+                ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
+                initializedHandlers.add( eh );
+            }
+        }
+
+        for ( Iterator i = MethodExceptionHandlers.iterator(); i.hasNext(); )
+        {
+            EventHandler eh = ( EventHandler ) i.next();
+            if ( (eh instanceof RuntimeServicesAware) &&
+                    !initializedHandlers.contains(eh) )
+            {
+                ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
+                initializedHandlers.add( eh );
+            }
+        }
+
+        for ( Iterator i = IncludeHandlers.iterator(); i.hasNext(); )
+        {
+            EventHandler eh = ( EventHandler ) i.next();
+            if ( (eh instanceof RuntimeServicesAware) &&
+                    !initializedHandlers.contains(eh) )
+            {
+                ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
+                initializedHandlers.add( eh );
+            }
+        }
+
+    }
+
+
 }

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandler.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandler.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandler.java Sun Sep 11 15:24:20 2005
@@ -17,7 +17,7 @@
  */
 
 /**
- *  Base interface for all event handlers
+ * Base interface for all event handlers
  *
  * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  * @version $Id$

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandlerUtil.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandlerUtil.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandlerUtil.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/EventHandlerUtil.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,275 @@
+package org.apache.velocity.app.event;
+
+import java.util.Iterator;
+
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.RuntimeServices;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Calls on request all registered event handlers for a particular event. Each
+ * method accepts two event cartridges (typically one from the application and
+ * one from the context). All appropriate event handlers are executed in order
+ * until a stopping condition is met. See the docs for the individual methods to
+ * see what the stopping condition is for that method.
+ *
+ * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+public class EventHandlerUtil {
+
+    /**
+     * Called before a reference is inserted. All event handlers are called in
+     * sequence. The default implementation inserts the reference as is.
+     *
+     * @param reference reference from template about to be inserted
+     * @param value value about to be inserted (after toString() )
+     * @return Object on which toString() should be called for output.
+     */
+    public static Object referenceInsert(RuntimeServices rsvc,
+            InternalContextAdapter context, String reference, Object value)
+    {
+        EventCartridge ev1 = rsvc.getApplicationEventCartridge();
+
+        /**
+         * retrieve and initialize the event cartridge handlers attached to the
+         * context (if they have not been already)
+         */
+        EventCartridge ev2 = context.getEventCartridge();
+
+        if (ev2 != null)
+        {
+            try {
+                ev2.initialize(rsvc);
+            }
+            catch (Exception E)
+            {
+                rsvc.error("Couldn't initialize event handler.  " + E);
+            }
+        }
+
+        Object returnValue = value;
+
+        if (ev1 != null)
+            for (Iterator i = ev1.getReferenceInsertionEventHandlers(); i.hasNext();)
+            {
+                ReferenceInsertionEventHandler eh = (ReferenceInsertionEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = eh.referenceInsert(reference, returnValue);
+            }
+
+        if (ev2 != null)
+            for (Iterator i = ev2.getReferenceInsertionEventHandlers(); i
+                    .hasNext();)
+            {
+                ReferenceInsertionEventHandler eh = (ReferenceInsertionEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = eh.referenceInsert(reference, returnValue);
+            }
+
+        return returnValue;
+    }
+
+    /**
+     * Called when a null is evaluated during a #set. All event handlers are
+     * called in sequence until a false is returned. The default implementation
+     * always returns true.
+     *
+     * @param reference
+     *            reference from template about to be inserted
+     * @return true if to be logged, false otherwise
+     */
+    public static boolean shouldLogOnNullSet(RuntimeServices rsvc,
+            InternalContextAdapter context, String lhs, String rhs)
+    {
+        EventCartridge ev1 = rsvc.getApplicationEventCartridge();
+
+        /**
+         * retrieve and initialize the event cartridge handlers attached to the
+         * context (if they have not been already)
+         */
+        EventCartridge ev2 = context.getEventCartridge();
+
+        if (ev2 != null)
+        {
+            try
+            {
+                ev2.initialize(rsvc);
+            }
+            catch (Exception E)
+            {
+                rsvc.error("Couldn't initialize event handler.  " + E);
+            }
+        }
+
+        boolean returnValue = true;
+
+        if (ev1 != null)
+            for (Iterator i = ev1.getNullSetEventHandlers(); i.hasNext();)
+            {
+                NullSetEventHandler eh = (NullSetEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = returnValue
+                        && eh.shouldLogOnNullSet(lhs, rhs);
+            }
+
+        if (ev2 != null)
+            for (Iterator i = ev2.getNullSetEventHandlers(); i.hasNext();)
+            {
+                NullSetEventHandler eh = (NullSetEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = returnValue
+                        && eh.shouldLogOnNullSet(lhs, rhs);
+            }
+
+        return returnValue;
+    }
+
+    /**
+     * Called when a method exception is generated during Velocity merge. Only
+     * the first valid event handler in the sequence is called. The default
+     * implementation simply rethrows the exception.
+     *
+     * @param claz
+     *            Class that is causing the exception
+     * @param method
+     *            method called that causes the exception
+     * @param e
+     *            Exception thrown by the method
+     * @return Object to return as method result
+     * @throws exception
+     *             to be wrapped and propogated to app
+     */
+    public static Object methodException(RuntimeServices rsvc,
+            InternalContextAdapter context, Class claz, String method,
+            Exception e) throws Exception {
+        EventCartridge ev1 = rsvc.getApplicationEventCartridge();
+
+        /**
+         * retrieve and initialize the event cartridge handlers attached to the
+         * context (if they have not been already)
+         */
+        EventCartridge ev2 = context.getEventCartridge();
+
+        if (ev2 != null)
+        {
+            try
+            {
+                ev2.initialize(rsvc);
+            }
+            catch (Exception E)
+            {
+                rsvc.error("Couldn't initialize event handler.  " + E);
+            }
+        }
+
+        if (ev1 != null)
+            for (Iterator i = ev1.getMethodExceptionEventHandlers(); i
+                    .hasNext();)
+            {
+                MethodExceptionEventHandler eh = (MethodExceptionEventHandler) i
+                        .next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                return eh.methodException(claz, method, e);
+            }
+
+        if (ev2 != null)
+            for (Iterator i = ev2.getMethodExceptionEventHandlers(); i
+                    .hasNext();)
+            {
+                MethodExceptionEventHandler eh = (MethodExceptionEventHandler) i
+                        .next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                return eh.methodException(claz, method, e);
+            }
+
+        throw e;
+    }
+
+    /**
+     * Called when an include-type directive is encountered (#include or
+     * #parse). All the registered event handlers are called unless null is
+     * returned. The default implementation always processes the included
+     * resource.
+     *
+     * @param includeResourcePath
+     *            the path as given in the include directive.
+     * @param currentResourcePath
+     *            the path of the currently rendering template that includes the
+     *            include directive.
+     * @param directiveName
+     *            name of the directive used to include the resource. (With the
+     *            standard directives this is either "parse" or "include").
+     *
+     * @return a new resource path for the directive, or null to block the
+     *         include from occurring.
+     */
+    public static String includeEvent(RuntimeServices rsvc,
+            InternalContextAdapter context, String includeResourcePath,
+            String currentResourcePath, String directiveName)
+    {
+        EventCartridge ev1 = rsvc.getApplicationEventCartridge();
+
+        /**
+         * retrieve and initialize the event cartridge handlers attached to the
+         * context (if they have not been already)
+         */
+        EventCartridge ev2 = context.getEventCartridge();
+
+        if (ev2 != null)
+        {
+            try
+            {
+                ev2.initialize(rsvc);
+            }
+            catch (Exception E)
+            {
+                rsvc.error("Couldn't initialize event handler.  " + E);
+            }
+        }
+
+        String returnValue = includeResourcePath;
+
+        if (ev1 != null)
+            for (Iterator i = ev1.getIncludeEventHandlers(); i.hasNext();)
+            {
+                IncludeEventHandler eh = (IncludeEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = eh.includeEvent(returnValue, currentResourcePath, directiveName);
+            }
+
+        if (ev2 != null)
+            for (Iterator i = ev2.getIncludeEventHandlers(); i.hasNext();)
+            {
+                IncludeEventHandler eh = (IncludeEventHandler) i.next();
+                if (eh instanceof ContextAware)
+                    ((ContextAware) eh).setContext(context);
+                returnValue = eh.includeEvent(returnValue, currentResourcePath, directiveName);
+            }
+
+        return returnValue;
+    }
+
+}
\ No newline at end of file

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/IncludeEventHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/IncludeEventHandler.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/IncludeEventHandler.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/IncludeEventHandler.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,46 @@
+package org.apache.velocity.app.event;
+
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *  Event handler for include type directives (e.g. <code>#include()</code>, <code>#parse()</code>)
+ *  Allows the developer to modify the path of the resource returned.
+ *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+public interface  IncludeEventHandler extends EventHandler
+{
+    /**
+     * Called when an include-type directive is encountered (
+     * <code>#include</code> or <code>#parse</code>). May modify the path
+     * of the resource to be included or may block the include entirely. All the
+     * registered IncludeEventHandlers are called unless null is returned. If
+     * none are registered the template at the includeResourcePath is retrieved.
+     * 
+     * @param includeResourcePath  the path as given in the include directive.
+     * @param currentResourcePath the path of the currently rendering template that includes the
+     *            include directive.
+     * @param directiveName  name of the directive used to include the resource. (With the
+     *            standard directives this is either "parse" or "include").
+     * 
+     * @return a new resource path for the directive, or null to block the
+     *         include from occurring.
+     */
+    public String includeEvent( String includeResourcePath, String currentResourcePath, String directiveName );
+}

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/MethodExceptionEventHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/MethodExceptionEventHandler.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/MethodExceptionEventHandler.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/MethodExceptionEventHandler.java Sun Sep 11 15:24:20 2005
@@ -1,4 +1,6 @@
 package org.apache.velocity.app.event;
+
+
 /*
  * Copyright 2001-2004 The Apache Software Foundation.
  *
@@ -16,17 +18,29 @@
  */
 
 /**
- *  Called when a method throws an exception.  This gives the
+ *  Event handler called when a method throws an exception.  This gives the
  *  application a chance to deal with it and either
  *  return something nice, or throw.
  *
  *  Please return what you want rendered into the output stream.
  *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
  * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  * @version $Id$
  */
 public interface MethodExceptionEventHandler extends EventHandler
 {
+    /**
+     * Called when a method throws an exception.
+     * Only the first registered MethodExceptionEventHandler is called.  If
+     * none are registered a MethodInvocationException is thrown.
+     *
+     * @param claz the class of the object the method is being applied to
+     * @param method the method
+     * @param e the thrown exception
+     * @return an object to insert in the page
+     * @throws Exception an exception to be thrown instead inserting an object
+     */
     public Object methodException( Class claz, String method, Exception e )
          throws Exception;
 }

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/NullSetEventHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/NullSetEventHandler.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/NullSetEventHandler.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/NullSetEventHandler.java Sun Sep 11 15:24:20 2005
@@ -17,17 +17,20 @@
  */
 
 /**
- *  Event handler : lets an app approve / veto
- *  writing a log message when RHS of #set() is null.
+ *  Event handler called when the RHS of #set is null.  Lets an app approve / veto
+ *  writing a log message based on the specific reference.
  *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
  * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  * @version $Id$
  */
 public interface NullSetEventHandler extends EventHandler
 {
     /**
-     *  Called when the RHS of a #set() is null, which will result
-     *  in a null LHS.
+     * Called when the RHS of a #set() is null, which will result
+     * in a null LHS. All NullSetEventHandlers
+     * are called in sequence until a false is returned.  If no NullSetEventHandler
+     * is registered all nulls will be logged.
      *
      *  @param lhs  reference literal of left-hand-side of set statement
      *  @param rhs  reference literal of right-hand-side of set statement

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/ReferenceInsertionEventHandler.java Sun Sep 11 15:24:20 2005
@@ -1,4 +1,6 @@
 package org.apache.velocity.app.event;
+
+
 /*
  * Copyright 2001-2004 The Apache Software Foundation.
  *
@@ -21,20 +23,25 @@
  *
  *  Please return an Object that will toString() nicely :)
  *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
  * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  * @version $Id$
  */
 public interface  ReferenceInsertionEventHandler extends EventHandler
 {
     /**
-     * A call-back which is executed during Velocity merge before a
-     * reference value is inserted into the output stream.
-     *
+     * A call-back which is executed during Velocity merge before a reference
+     * value is inserted into the output stream. All registered
+     * ReferenceInsertionEventHandlers are called in sequence. If no
+     * ReferenceInsertionEventHandlers are are registered then reference value
+     * is inserted into the output stream as is.
+     * 
+     * @param context the current velocity context
      * @param reference Reference from template about to be inserted.
-     * @param value Value about to be inserted (after its
-     * <code>toString()</code> method is called).
-     * @return Object on which <code>toString()</code> should be
-     * called for output.
+     * @param value Value about to be inserted (after its <code>toString()</code>
+     *            method is called).
+     * @return Object on which <code>toString()</code> should be called for
+     *         output.
      */
     public Object referenceInsert( String reference, Object value  );
 }

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/RuntimeServicesAware.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/RuntimeServicesAware.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/RuntimeServicesAware.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/RuntimeServicesAware.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,36 @@
+package org.apache.velocity.app.event;
+
+import org.apache.velocity.runtime.RuntimeServices;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Event handlers implementing this interface will automatically
+ * have the method setRuntimeServices called when the associated
+ * EventCartridge is attached to the context.  
+ * 
+ * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain</a>
+ * @version $Id: GlobalEventHandler.java,v 1.4 2004/03/19 17:13:33 dlr Exp $
+ */
+public interface  RuntimeServicesAware
+{
+    /**
+     * Initialize the EventHandler.
+     */
+    public void setRuntimeServices( RuntimeServices rs ) throws Exception;
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeHtmlReference.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeHtmlReference.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeHtmlReference.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeHtmlReference.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,30 @@
+package org.apache.velocity.app.event.implement;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+/**
+ * Escape all HTML entities.
+ * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeHtml(java.lang.String)
+ * @author wglass
+ */
+public class EscapeHtmlReference extends EscapeReference
+{
+
+    /**
+     * Escape all HTML entities.  
+     * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeHtml(java.lang.String)
+     */
+    protected String escape(Object text)
+    {
+        return StringEscapeUtils.escapeHtml(text.toString());
+    }
+
+    /**
+     * @return attribute "eventhandler.escape.html.match"
+     */
+    protected String getMatchAttribute()
+    {
+        return "eventhandler.escape.html.match";
+    }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeJavaScriptReference.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeJavaScriptReference.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeJavaScriptReference.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeJavaScriptReference.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,30 @@
+package org.apache.velocity.app.event.implement;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+/**
+ * Escapes the characters in a String to be suitable for use in JavaScript.
+ * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeJavaScript(java.lang.String)
+ * @author wglass
+ */
+public class EscapeJavaScriptReference extends EscapeReference
+{
+
+    /**
+     * Escapes the characters in a String to be suitable for use in JavaScript.
+     * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeXml(java.lang.String)
+     */
+    protected String escape(Object text)
+    {
+        return StringEscapeUtils.escapeJavaScript(text.toString());
+    }
+
+    /**
+     * @return attribute "eventhandler.escape.javascript.match"
+     */
+    protected String getMatchAttribute()
+    {
+        return "eventhandler.escape.javascript.match";
+    }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeReference.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeReference.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeReference.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeReference.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,138 @@
+package org.apache.velocity.app.event.implement;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.oro.text.perl.MalformedPerl5PatternException;
+import org.apache.oro.text.perl.Perl5Util;
+import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
+import org.apache.velocity.app.event.RuntimeServicesAware;
+import org.apache.velocity.runtime.RuntimeServices;
+
+/**
+ * Base class for escaping references.  To use it, override the following methods:
+ * <DL>
+ * <DT><code>String escape(String text)</code></DT> 
+ * <DD>escape the provided text</DD>
+ * <DT><code>String getMatchAttribute()</code></DT>
+ * <DD>retrieve the configuration attribute used to match references (see below)</DD>
+ * </DL>
+ * 
+ * <P>By default, all references are escaped.  However, by setting the match attribute 
+ * in the configuration file to a regular expression, users can specify which references 
+ * to escape.  For example the following configuration property tells the EscapeSqlReference
+ * event handler to only escape references that start with "sql".  
+ * (e.g. <code>$sql</code>, <code>$sql.toString(),</code>, etc).
+ * 
+ * <PRE>
+ * <CODE>eventhandler.escape.sql.match = /sql.*<!-- -->/ 
+ * </CODE>
+ * </PRE>
+ * <!-- note: ignore empty HTML comment above - breaks up star slash avoiding javadoc end -->
+ *
+ * Regular expressions should follow the "Perl5" format used by the ORO regular expression
+ * library.  More info is at 
+ * <a href="http://jakarta.apache.org/oro/api/org/apache/oro/text/perl/package-summary.html">http://jakarta.apache.org/oro/api/org/apache/oro/text/perl/package-summary.html</a>.
+ * 
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain </a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+public abstract class EscapeReference implements ReferenceInsertionEventHandler,RuntimeServicesAware {
+
+   
+    private Perl5Util perl = new Perl5Util();    
+
+    private RuntimeServices rs;
+   
+    private String matchRegExp = null;
+
+    /**
+     * Escape the given text.  Override this in a subclass to do the actual
+     * escaping.
+     * 
+     * @param text the text to escape
+     * @return the escaped text
+     */
+    protected abstract String escape(Object text);
+    
+    /**
+     * Specify the configuration attribute that specifies the 
+     * regular expression.  Ideally should be in a form
+     * <pre><code>eventhandler.escape.XYZ.match</code></pre>
+     * 
+     * <p>where <code>XYZ</code> is the type of escaping being done. 
+     * @return configuration attribute
+     */
+    protected abstract String getMatchAttribute();
+    
+    /**
+     * Escape the provided text if it matches the configured regular expression.
+     */
+    public Object referenceInsert(String reference, Object value) 
+    {
+        if (matchRegExp == null)
+            return escape(value);
+        
+        else if (perl.match(matchRegExp,reference))
+            return escape(value);
+        
+        else
+            return value;
+    }
+
+    /**
+     * Called automatically when event cartridge is initialized.
+     */
+    public void setRuntimeServices(RuntimeServices rs) throws Exception 
+    {
+        this.rs = rs;
+
+        /**
+         * Get the regular expression pattern.
+         */
+        matchRegExp = rs.getConfiguration().getString(getMatchAttribute());
+        if ((matchRegExp != null) && (matchRegExp.trim().length() == 0))
+            matchRegExp = null;
+        
+        /**
+         * Test the regular expression for a well formed pattern
+         */
+        if (matchRegExp != null) 
+        {
+            try 
+            {
+                perl.match(matchRegExp,"");
+            } 
+            catch (MalformedPerl5PatternException E) 
+            {
+                rs.error("Invalid regular expression '" + matchRegExp + "'.  No escaping will be performed.");
+                matchRegExp = null;
+            }
+        }
+        
+    }
+
+    /**
+     * Retrieve a reference to RuntimeServices.  Use this for checking additional 
+     * configuration properties.
+     * @return
+     */
+    protected RuntimeServices getRuntimeServices()
+    {
+        return rs;
+    }
+    
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeSqlReference.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeSqlReference.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeSqlReference.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeSqlReference.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,30 @@
+package org.apache.velocity.app.event.implement;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+/**
+ * Escapes the characters in a String to be suitable to pass to an SQL query.
+ * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeSql(java.lang.String)
+ * @author wglass
+ */
+public class EscapeSqlReference extends EscapeReference
+{
+
+    /**
+     * Escapes the characters in a String to be suitable to pass to an SQL query.
+     * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeXml(java.lang.String)
+     */
+    protected String escape(Object text)
+    {
+        return StringEscapeUtils.escapeSql(text.toString());
+    }
+
+    /**
+     * @return attribute "eventhandler.escape.sql.match"
+     */
+    protected String getMatchAttribute()
+    {
+        return "eventhandler.escape.sql.match";
+    }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeXmlReference.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeXmlReference.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeXmlReference.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/EscapeXmlReference.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,30 @@
+package org.apache.velocity.app.event.implement;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+/**
+ * Escape all XML entities.
+ * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeHtml(java.lang.String)
+ * @author wglass
+ */
+public class EscapeXmlReference extends EscapeReference
+{
+
+    /**
+     * Escape all XML entities.  
+     * @see http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/StringEscapeUtils.html#escapeXml(java.lang.String)
+     */
+    protected String escape(Object text)
+    {
+        return StringEscapeUtils.escapeXml(text.toString());
+    }
+
+    /**
+     * @return attribute "eventhandler.escape.xml.match"
+     */
+    protected String getMatchAttribute()
+    {
+        return "eventhandler.escape.xml.match";
+    }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeNotFound.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeNotFound.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeNotFound.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeNotFound.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,88 @@
+package org.apache.velocity.app.event.implement;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.velocity.app.event.RuntimeServicesAware;
+import org.apache.velocity.app.event.IncludeEventHandler;
+import org.apache.velocity.runtime.RuntimeServices;
+
+/**
+ * Simple event handler that checks to see if an included page is available.
+ * If not, it includes a designated replacement page instead.
+ *
+ * <P>By default, the name of the replacement page is "notfound.vm", however this
+ * page name can be changed by setting the Velocity property
+ * <code>eventhandler.include.notfound</code>, for example:
+ * <code>
+ * <PRE>
+ * eventhandler.include.notfound = error.vm
+ * </PRE>
+ * </code>
+ *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+
+public class IncludeNotFound implements IncludeEventHandler,RuntimeServicesAware {
+
+    private static final String DEFAULT_NOT_FOUND = "notfound.vm";
+    private static final String PROPERTY_NOT_FOUND = "eventhandler.include.notfound";
+    private RuntimeServices rs;
+    String notfound;
+
+    /**
+     * Chseck to see if included file exists, and display "not found" page if it
+     * doesn't. If "not found" page does not exist, log an error and return
+     * null.
+     */
+    public String includeEvent(
+        String includeResourcePath,
+        String currentResourcePath,
+        String directiveName)
+    {
+
+        /**
+         * check to see if page exists
+         */
+        boolean exists = (rs.getLoaderNameForResource(includeResourcePath) != null);
+        if (!exists)
+        {
+            if (rs.getLoaderNameForResource(notfound) == null)
+                return notfound;
+
+            /**
+             * can't find not found, so display nothing
+             */
+            else
+            {
+                rs.error("Can't find include not found page: " + notfound);
+                return null;
+            }
+
+        }
+        else
+            return includeResourcePath;
+    }
+
+
+    public void setRuntimeServices(RuntimeServices rs) throws Exception
+    {
+         this.rs = rs;
+         notfound = rs.getString(PROPERTY_NOT_FOUND,DEFAULT_NOT_FOUND).trim();
+     }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeRelativePath.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeRelativePath.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeRelativePath.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/IncludeRelativePath.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,80 @@
+package org.apache.velocity.app.event.implement;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.velocity.app.event.RuntimeServicesAware;
+import org.apache.velocity.app.event.IncludeEventHandler;
+import org.apache.velocity.runtime.RuntimeServices;
+
+/**
+ * Event handler that looks for included files relative to the path of the
+ * current template. The handler assumes that paths are separated by a forward
+ * slash "/" or backwards slash "\".
+ *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain </a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+
+public class IncludeRelativePath implements IncludeEventHandler,RuntimeServicesAware {
+
+    private RuntimeServices rs;
+    String notfound;
+
+    /**
+     * Return path relative to the current template's path.
+     */
+    public String includeEvent(
+        String includeResourcePath,
+        String currentResourcePath,
+        String directiveName)
+    {
+
+        // strip the starting slash from includeResourcePath, if it exists
+        if (includeResourcePath.startsWith("/") || includeResourcePath.startsWith("\\") )
+            includeResourcePath = includeResourcePath.substring(1);
+
+        int slashpos1 = currentResourcePath.lastIndexOf("/");
+        int slashpos2 = currentResourcePath.lastIndexOf("\\");
+        int lastslashpos = -1;
+        if ( (slashpos1 != -1) && (slashpos2 != -1) && (slashpos1 <= slashpos2) )
+            lastslashpos = slashpos2;
+
+        else if ( (slashpos1 != -1) && (slashpos2 != -1) && (slashpos1 > slashpos2) )
+            lastslashpos = slashpos1;
+
+        else if ( (slashpos1 != -1) && (slashpos2 == -1) )
+            lastslashpos = slashpos1;
+
+        else if ( (slashpos1 == -1) && (slashpos2 != -1) )
+            lastslashpos = slashpos2;
+
+        // root of resource tree
+        if ( (lastslashpos == -1) || (lastslashpos == 0) )
+            return includeResourcePath;
+
+        // prepend path to the include path
+        else
+            return currentResourcePath.substring(0,lastslashpos) + "/" + includeResourcePath;
+
+    }
+
+
+    public void setRuntimeServices(RuntimeServices rs) throws Exception {
+         this.rs = rs;
+     }
+
+}

Added: jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/PrintExceptions.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/PrintExceptions.java?rev=280189&view=auto
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/PrintExceptions.java (added)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/app/event/implement/PrintExceptions.java Sun Sep 11 15:24:20 2005
@@ -0,0 +1,110 @@
+package org.apache.velocity.app.event.implement;
+
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.velocity.app.event.RuntimeServicesAware;
+import org.apache.velocity.app.event.MethodExceptionEventHandler;
+import org.apache.velocity.runtime.RuntimeServices;
+
+/**
+ * Simple event handler that renders method exceptions in the page
+ * rather than throwing the exception.  Useful for debugging.
+ *
+ * <P>By default this event handler renders the exception name only.
+ * To include both the exception name and the message, set the property
+ * <code>eventhandler.methodexception.message</code> to <code>true</code>.  To render
+ * the stack trace, set the property <code>eventhandler.methodexception.stacktrace</code>
+ * to <code>true</code>.
+ *
+ * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
+ * @version $Id: EventCartridge.java,v 1.5 2004/03/19 17:13:33 dlr Exp $
+ */
+public class PrintExceptions implements MethodExceptionEventHandler,RuntimeServicesAware
+{
+
+    private static String SHOW_MESSAGE = "eventhandler.methodexception.message";
+    private static String SHOW_STACK_TRACE = "eventhandler.methodexception.stacktrace";
+    private RuntimeServices rs;
+
+    /**
+     * Render the method exception, and optionally the exception message and stack trace.
+     */
+    public Object methodException(Class claz, String method, Exception e) throws Exception
+    {
+        boolean showMessage = rs.getBoolean(SHOW_MESSAGE,false);
+        boolean showStackTrace = rs.getBoolean(SHOW_STACK_TRACE,false);
+
+        StringBuffer st;
+        if (showMessage && showStackTrace)
+        {
+            st = new StringBuffer(200);
+            st.append(e.getClass().getName()).append("\n");
+            st.append(e.getMessage()).append("\n");
+            st.append(getStackTrace(e));
+
+        } else if (showMessage)
+        {
+            st = new StringBuffer(50);
+            st.append(e.getClass().getName()).append("\n");
+            st.append(e.getMessage()).append("\n");
+
+        } else if (showStackTrace)
+        {
+            st = new StringBuffer(200);
+            st.append(e.getClass().getName()).append("\n");
+            st.append(getStackTrace(e));
+
+        } else
+        {
+            st = new StringBuffer(15);
+            st.append(e.getClass().getName()).append("\n");
+        }
+
+        return st.toString();
+
+    }
+
+
+    private static String getStackTrace(Throwable E)
+    {
+        try
+        {
+            StringWriter StackTraceWriter = new StringWriter();
+            E.printStackTrace(new PrintWriter(StackTraceWriter));
+            StackTraceWriter.flush();
+            String StackTrace = StackTraceWriter.toString();
+            StackTraceWriter.close();
+            return StackTraceWriter.toString() ;
+        }
+        catch (IOException ioe)
+        {
+            return "";
+        }
+    }
+
+
+
+    public void setRuntimeServices(RuntimeServices rs) throws Exception
+    {
+        this.rs = rs;
+    }
+
+}

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/context/VMContext.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/context/VMContext.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/context/VMContext.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/context/VMContext.java Sun Sep 11 15:24:20 2005
@@ -280,7 +280,8 @@
 
     public EventCartridge attachEventCartridge( EventCartridge ec )
     {
-        return innerContext.attachEventCartridge( ec );
+        EventCartridge cartridge = innerContext.attachEventCartridge( ec );
+        return cartridge;
     }
 
     public EventCartridge getEventCartridge()

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java Sun Sep 11 15:24:20 2005
@@ -204,6 +204,45 @@
 
     /*
      * ----------------------------------------------------------------------
+     *  E V E N T  H A N D L E R  C O N F I G U R A T I O N
+     * ----------------------------------------------------------------------
+     */
+     
+    /**
+     * The <code>eventhandler.referenceinsertion.class</code> property
+     * specifies a list of the {@link
+     * org.apache.velocity.app.event.ReferenceInsertionEventHandler}
+     * implementations to use.
+     */
+    public static final String EVENTHANDLER_REFERENCEINSERTION = "eventhandler.referenceinsertion.class";
+
+    /**
+     * The <code>eventhandler.nullset.class</code> property
+     * specifies a list of the {@link
+     * org.apache.velocity.app.event.NullSetEventHandler}
+     * implementations to use.
+     */
+    public static final String EVENTHANDLER_NULLSET = "eventhandler.nullset.class";
+
+    /**
+     * The <code>eventhandler.methodexception.class</code> property
+     * specifies a list of the {@link
+     * org.apache.velocity.app.event.MethoExceptionEventHandler}
+     * implementations to use.
+     */
+    public static final String EVENTHANDLER_METHODEXCEPTION = "eventhandler.methodexception.class";
+ 
+    /**
+     * The <code>eventhandler.include.class</code> property
+     * specifies a list of the {@link
+     * org.apache.velocity.app.event.IncludeEventHandler}
+     * implementations to use.
+     */
+    public static final String EVENTHANDLER_INCLUDE = "eventhandler.include.class";
+
+
+    /*
+     * ----------------------------------------------------------------------
      * V E L O C I M A C R O  C O N F I G U R A T I O N
      * ----------------------------------------------------------------------
      */
@@ -284,7 +323,7 @@
     /*
      * ----------------------------------------------------------------------
      * These constants are used internally by the Velocity runtime i.e.
-     * the constansts listed below are strictly used in the Runtime
+     * the constants listed below are strictly used in the Runtime
      * class itself.
      * ----------------------------------------------------------------------
      */

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java Sun Sep 11 15:24:20 2005
@@ -16,47 +16,44 @@
  * limitations under the License.
  */
 
-import java.io.InputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Reader;
-
-import java.util.Map;
-import java.util.Hashtable;
-import java.util.Properties;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
 
+import org.apache.commons.collections.ExtendedProperties;
 import org.apache.velocity.Template;
-
+import org.apache.velocity.app.event.EventCartridge;
+import org.apache.velocity.app.event.EventHandler;
+import org.apache.velocity.app.event.RuntimeServicesAware;
+import org.apache.velocity.app.event.IncludeEventHandler;
+import org.apache.velocity.app.event.MethodExceptionEventHandler;
+import org.apache.velocity.app.event.NullSetEventHandler;
+import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.directive.Directive;
 import org.apache.velocity.runtime.log.LogManager;
 import org.apache.velocity.runtime.log.LogSystem;
-import org.apache.velocity.runtime.log.PrimordialLogSystem;
 import org.apache.velocity.runtime.log.NullLogSystem;
-
-import org.apache.velocity.runtime.parser.Parser;
+import org.apache.velocity.runtime.log.PrimordialLogSystem;
 import org.apache.velocity.runtime.parser.ParseException;
+import org.apache.velocity.runtime.parser.Parser;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-
-import org.apache.velocity.runtime.directive.Directive;
-import org.apache.velocity.runtime.VelocimacroFactory;
-
 import org.apache.velocity.runtime.resource.ContentResource;
 import org.apache.velocity.runtime.resource.ResourceManager;
-
 import org.apache.velocity.util.ClassUtils;
 import org.apache.velocity.util.SimplePool;
 import org.apache.velocity.util.StringUtils;
-
 import org.apache.velocity.util.introspection.Introspector;
 import org.apache.velocity.util.introspection.Uberspect;
 import org.apache.velocity.util.introspection.UberspectLoggable;
 
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.ParseErrorException;
-
-import org.apache.commons.collections.ExtendedProperties;
-
 /**
  * This is the Runtime system for Velocity. It is the
  * single access point for all functionality in Velocity.
@@ -162,6 +159,12 @@
 
     private ResourceManager resourceManager = null;
 
+    /**
+     * This stores the engine-wide set of event handlers.  Event handlers for
+     * each specific merge are stored in the context.
+     */
+    private EventCartridge eventCartridge = null;
+
     /*
      *  Each runtime instance has it's own introspector
      *  to ensure that each instance is completely separate.
@@ -209,6 +212,7 @@
      * <ul>
      *   <li>Logging System</li>
      *   <li>ResourceManager</li>
+     *   <li>EventHandler</li>
      *   <li>Parser Pool</li>
      *   <li>Global Cache</li>
      *   <li>Static Content Include System</li>
@@ -227,6 +231,7 @@
             initializeLogger();
             initializeResourceManager();
             initializeDirectives();
+            initializeEventHandlers();
             initializeParserPool();
 
             initializeIntrospection();
@@ -537,6 +542,105 @@
         }                            
     }
     
+    private void initializeEventHandlers()
+        throws Exception
+    {
+        
+        eventCartridge = new EventCartridge();
+        
+        /**
+         * For each type of event handler, get the class name, instantiate it, and store it.
+         */
+         
+        String[] referenceinsertion = configuration.getStringArray(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION);
+        if ( referenceinsertion != null )
+        { 
+            for ( int i=0; i < referenceinsertion.length; i++ ) 
+            {
+                EventHandler ev = initializeSpecificEventHandler(referenceinsertion[i],RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION,ReferenceInsertionEventHandler.class); 
+                if (ev != null)
+                    eventCartridge.addReferenceInsertionEventHandler((ReferenceInsertionEventHandler) ev);
+            }
+        }
+        
+        String[] nullset = configuration.getStringArray(RuntimeConstants.EVENTHANDLER_NULLSET);
+        if ( nullset != null )
+        { 
+            for ( int i=0; i < nullset.length; i++ ) 
+            {
+                EventHandler ev = initializeSpecificEventHandler(nullset[i],RuntimeConstants.EVENTHANDLER_NULLSET,NullSetEventHandler.class); 
+                if (ev != null)
+                    eventCartridge.addNullSetEventHandler((NullSetEventHandler) ev);
+            }
+        }
+        
+        String[] methodexception = configuration.getStringArray(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION);
+        if ( methodexception != null )
+        { 
+            for ( int i=0; i < methodexception.length; i++ ) 
+            {
+                EventHandler ev = initializeSpecificEventHandler(methodexception[i],RuntimeConstants.EVENTHANDLER_METHODEXCEPTION,MethodExceptionEventHandler.class); 
+                if (ev != null)
+                    eventCartridge.addMethodExceptionHandler((MethodExceptionEventHandler) ev);
+            }
+        }
+        
+        String[] includeHandler = configuration.getStringArray(RuntimeConstants.EVENTHANDLER_INCLUDE);
+        if ( includeHandler != null )
+        { 
+            for ( int i=0; i < includeHandler.length; i++ ) 
+            {
+                EventHandler ev = initializeSpecificEventHandler(includeHandler[i],RuntimeConstants.EVENTHANDLER_INCLUDE,IncludeEventHandler.class); 
+                if (ev != null)
+                    eventCartridge.addIncludeEventHandler((IncludeEventHandler) ev);
+            }
+        }
+        
+    }
+    
+    private EventHandler initializeSpecificEventHandler(String classname, String paramName, Class EventHandlerInterface)
+        throws Exception
+    {
+        if ( classname != null && classname.length() > 0) 
+        {   
+            Object o = null;
+            try {
+                o = Class.forName(classname).newInstance();
+            }
+            catch (ClassNotFoundException cnfe )
+            {
+                String err = "The specified class for " 
+                    + paramName 
+                    + " ("
+                    + classname    
+                    + ") does not exist (or is not accessible to the current classlaoder.";
+                 error(err);
+                 throw new Exception(err);
+            }
+            
+            if (!EventHandlerInterface.isAssignableFrom(EventHandlerInterface))
+            {
+                String err = "The specified class for " 
+                    + paramName 
+                    + " ("
+                    + classname 
+                    + ") does not implement "
+                    + EventHandlerInterface.getName()
+                    + " Velocity not initialized correctly.";
+                    
+                error(err);
+                throw new Exception(err);
+            }
+
+            EventHandler ev = (EventHandler) o;   
+            if ( ev instanceof RuntimeServicesAware )
+                ((RuntimeServicesAware) ev).setRuntimeServices(this);
+            return ev;
+        
+        } else
+            return null;
+    }
+ 
     /**
      * Initialize the Velocity logging system.
      *
@@ -1119,6 +1223,15 @@
     {
         return introspector;
     }
+    
+    /**
+     * Returns the event handlers for the application.
+     */
+     public EventCartridge getApplicationEventCartridge()
+     {
+         return eventCartridge;
+     }
+    
 
     /**
      *  Gets the application attribute for the given key

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeServices.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeServices.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeServices.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeServices.java Sun Sep 11 15:24:20 2005
@@ -17,25 +17,20 @@
  */
 
 import java.io.Reader;
-
 import java.util.Properties;
 
+import org.apache.commons.collections.ExtendedProperties;
 import org.apache.velocity.Template;
-
+import org.apache.velocity.app.event.EventCartridge;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.directive.Directive;
 import org.apache.velocity.runtime.parser.ParseException;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-
-import org.apache.velocity.runtime.directive.Directive;
 import org.apache.velocity.runtime.resource.ContentResource;
-
 import org.apache.velocity.util.introspection.Introspector;
 import org.apache.velocity.util.introspection.Uberspect;
 
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.ParseErrorException;
-
-import org.apache.commons.collections.ExtendedProperties;
-
 
 /**
  * Interface for internal runtime services that are needed by the 
@@ -340,6 +335,12 @@
      * implemenation.
      */
     public Uberspect getUberspect();
+
+    /**
+      * Returns the event handlers for the application.
+      */
+     public EventCartridge getApplicationEventCartridge();
+
 
     /**
      * Returns the configured method introspection/reflection

Modified: jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java
URL: http://svn.apache.org/viewcvs/jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java?rev=280189&r1=280188&r2=280189&view=diff
==============================================================================
--- jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java (original)
+++ jakarta/velocity/core/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java Sun Sep 11 15:24:20 2005
@@ -17,25 +17,18 @@
  */
 
 import java.io.Reader;
-
 import java.util.Properties;
 
+import org.apache.commons.collections.ExtendedProperties;
 import org.apache.velocity.Template;
-
-
-import org.apache.velocity.runtime.parser.Parser;
+import org.apache.velocity.app.event.EventCartridge;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.directive.Directive;
 import org.apache.velocity.runtime.parser.ParseException;
+import org.apache.velocity.runtime.parser.Parser;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-
-import org.apache.velocity.runtime.directive.Directive;
-
 import org.apache.velocity.runtime.resource.ContentResource;
-
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.ParseErrorException;
-
-import org.apache.commons.collections.ExtendedProperties;
-
 import org.apache.velocity.util.introspection.Introspector;
 import org.apache.velocity.util.introspection.Uberspect;
 
@@ -102,6 +95,7 @@
      * <ul>
      *   <li>Logging System</li>
      *   <li>ResourceManager</li>
+     *   <li>Event Handlers</li>
      *   <li>Parser Pool</li>
      *   <li>Global Cache</li>
      *   <li>Static Content Include System</li>
@@ -532,6 +526,14 @@
     {
         return ri.getIntrospector();
     }
+    
+    /**
+      * Returns the event handlers for the application.
+      */
+     public EventCartridge getEventCartridge()
+     {
+         return ri.getApplicationEventCartridge();
+     }
     
     /**
      * @see org.apache.velocity.runtime.RuntimeServices#getApplicationAttribute(Object)



---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org