View Javadoc

1   package org.apache.velocity.app.event;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.util.ArrayList;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Set;
27  
28  import org.apache.velocity.context.Context;
29  import org.apache.velocity.context.InternalEventContext;
30  import org.apache.velocity.runtime.RuntimeServices;
31  import org.apache.velocity.util.RuntimeServicesAware;
32  
33  /**
34   * Stores the event handlers. Event handlers can be assigned on a per
35   * VelocityEngine instance basis by specifying the class names in the
36   * velocity.properties file. Event handlers may also be assigned on a per-page
37   * basis by creating a new instance of EventCartridge, adding the event
38   * handlers, and then calling attachToContext. For clarity, it's recommended
39   * that one approach or the other be followed, as the second method is primarily
40   * presented for backwards compatibility.
41   *
42   * <P>
43   * Note that Event Handlers follow a filter pattern, with multiple event
44   * handlers allowed for each event. When the appropriate event occurs, all the
45   * appropriate event handlers are called in the sequence they were added to the
46   * Event Cartridge. See the javadocs of the specific event handler interfaces
47   * for more details.
48   *
49   * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a>
50   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr. </a>
51   * @author <a href="mailto:j_a_fernandez@yahoo.com">Jose Alberto Fernandez </a>
52   * @version $Id: EventCartridge.java 685685 2008-08-13 21:43:27Z nbubna $
53   */
54  public class EventCartridge
55    {
56      private List referenceHandlers = new ArrayList();
57      private List nullSetHandlers = new ArrayList();
58      private List methodExceptionHandlers = new ArrayList();
59      private List includeHandlers = new ArrayList();
60      private List invalidReferenceHandlers = new ArrayList();
61  
62      /**
63       * Ensure that handlers are not initialized more than once.
64       */
65      Set initializedHandlers = new HashSet();
66  
67      /**
68       *  Adds an event handler(s) to the Cartridge.  This method
69       *  will find all possible event handler interfaces supported
70       *  by the passed in object.
71       *
72       *  @param ev object impementing a valid EventHandler-derived interface
73       *  @return true if a supported interface, false otherwise or if null
74       */
75      public boolean addEventHandler( EventHandler ev )
76      {
77          if (ev == null)
78          {
79              return false;
80          }
81  
82          boolean found = false;
83  
84          if ( ev instanceof ReferenceInsertionEventHandler)
85          {
86              addReferenceInsertionEventHandler( (ReferenceInsertionEventHandler) ev );
87              found = true;
88          }
89  
90          if ( ev instanceof NullSetEventHandler )
91          {
92              addNullSetEventHandler( (NullSetEventHandler) ev );
93              found = true;
94          }
95  
96          if ( ev instanceof MethodExceptionEventHandler )
97          {
98              addMethodExceptionHandler( (MethodExceptionEventHandler) ev );
99              found = true;
100         }
101 
102         if ( ev instanceof IncludeEventHandler )
103         {
104             addIncludeEventHandler( (IncludeEventHandler) ev );
105             found = true;
106         }
107 
108         if ( ev instanceof InvalidReferenceEventHandler )
109         {
110             addInvalidReferenceEventHandler( (InvalidReferenceEventHandler) ev );
111             found = true;
112         }
113 
114         return found;
115     }
116 
117     /**
118       *  Add a reference insertion event handler to the Cartridge.
119       *
120       *  @param ev ReferenceInsertionEventHandler
121      * @since 1.5
122      */
123      public void addReferenceInsertionEventHandler( ReferenceInsertionEventHandler ev )
124      {
125          referenceHandlers.add( ev );
126      }
127 
128     /**
129       *  Add a null set event handler to the Cartridge.
130       *
131       *  @param ev NullSetEventHandler
132       * @since 1.5
133       */
134      public void addNullSetEventHandler( NullSetEventHandler ev )
135      {
136          nullSetHandlers.add( ev );
137      }
138 
139     /**
140      *  Add a method exception event handler to the Cartridge.
141      *
142      *  @param ev MethodExceptionEventHandler
143      *  @since 1.5
144      */
145     public void addMethodExceptionHandler( MethodExceptionEventHandler ev )
146     {
147         methodExceptionHandlers.add( ev );
148     }
149 
150     /**
151      *  Add an include event handler to the Cartridge.
152      *
153      *  @param ev IncludeEventHandler
154      *  @since 1.5
155      */
156     public void addIncludeEventHandler( IncludeEventHandler ev )
157     {
158         includeHandlers.add( ev );
159     }
160 
161     /**
162      *  Add an invalid reference event handler to the Cartridge.
163      *
164      *  @param ev InvalidReferenceEventHandler
165      *  @since 1.5
166      */
167     public void addInvalidReferenceEventHandler( InvalidReferenceEventHandler ev )
168     {
169         invalidReferenceHandlers.add( ev );
170     }
171 
172 
173     /**
174      * Removes an event handler(s) from the Cartridge. This method will find all
175      * possible event handler interfaces supported by the passed in object and
176      * remove them.
177      *
178      * @param ev  object impementing a valid EventHandler-derived interface
179      * @return true if event handler was previously registered, false if not
180      *         found
181      */
182     public boolean removeEventHandler( EventHandler ev )
183     {
184         if ( ev == null )
185         {
186             return false;
187         }
188 
189         boolean found = false;
190 
191         if ( ev instanceof ReferenceInsertionEventHandler )
192             return referenceHandlers.remove( ev );
193 
194         if ( ev instanceof NullSetEventHandler )
195             return nullSetHandlers.remove( ev );
196 
197         if ( ev instanceof MethodExceptionEventHandler )
198             return methodExceptionHandlers.remove(ev );
199 
200         if ( ev instanceof IncludeEventHandler )
201             return includeHandlers.remove( ev );
202 
203         if ( ev instanceof InvalidReferenceEventHandler )
204             return invalidReferenceHandlers.remove( ev );
205 
206         return found;
207     }
208 
209     /**
210      * Iterate through all the stored ReferenceInsertionEventHandler objects
211      * 
212      * @return iterator of handler objects, null if there are not handlers
213      * @since 1.5
214      */
215     public Iterator getReferenceInsertionEventHandlers()
216     {
217         return referenceHandlers.size() == 0 ? null : referenceHandlers.iterator();
218     }
219 
220     /**
221      * Iterate through all the stored NullSetEventHandler objects
222      * 
223      * @return iterator of handler objects
224      * @since 1.5
225      */
226     public Iterator getNullSetEventHandlers()
227     {
228         return nullSetHandlers.iterator();
229     }
230 
231     /**
232      * Iterate through all the stored MethodExceptionEventHandler objects
233      * 
234      * @return iterator of handler objects
235      * @since 1.5
236      */
237     public Iterator getMethodExceptionEventHandlers()
238     {
239         return methodExceptionHandlers.iterator();
240     }
241 
242     /**
243      * Iterate through all the stored IncludeEventHandlers objects
244      * 
245      * @return iterator of handler objects
246      */
247     public Iterator getIncludeEventHandlers()
248     {
249         return includeHandlers.iterator();
250     }
251 
252     /**
253      * Iterate through all the stored InvalidReferenceEventHandlers objects
254      * 
255      * @return iterator of handler objects
256      * @since 1.5
257      */
258     public Iterator getInvalidReferenceEventHandlers()
259     {
260         return invalidReferenceHandlers.iterator();
261     }
262 
263     /**
264      *  Attached the EventCartridge to the context
265      *
266      *  Final because not something one should mess with lightly :)
267      *
268      *  @param context context to attach to
269      *  @return true if successful, false otherwise
270      */
271     public final boolean attachToContext( Context context )
272     {
273         if (  context instanceof InternalEventContext )
274         {
275             InternalEventContext iec = (InternalEventContext) context;
276 
277             iec.attachEventCartridge( this );
278 
279             /**
280              * while it's tempting to call setContext on each handler from here,
281              * this needs to be done before each method call.  This is
282              * because the specific context will change as inner contexts
283              * are linked in through macros, foreach, or directly by the user.
284              */
285 
286             return true;
287         }
288         else
289         {
290             return false;
291         }
292     }
293 
294     /**
295      * Initialize the handlers.  For global handlers this is called when Velocity
296      * is initialized. For local handlers this is called when the first handler
297      * is executed.  Handlers will not be initialized more than once.
298      * 
299      * @param rs
300      * @throws Exception
301      * @since 1.5
302      */
303     public void initialize (RuntimeServices rs) throws Exception
304     {
305 
306         for ( Iterator i = referenceHandlers.iterator(); i.hasNext(); )
307         {
308             EventHandler eh = ( EventHandler ) i.next();
309             if ( (eh instanceof RuntimeServicesAware) &&
310                     !initializedHandlers.contains(eh) )
311             {
312                 ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
313                 initializedHandlers.add( eh );
314             }
315         }
316 
317         for ( Iterator i = nullSetHandlers.iterator(); i.hasNext(); )
318         {
319             EventHandler eh = ( EventHandler ) i.next();
320             if ( (eh instanceof RuntimeServicesAware) &&
321                     !initializedHandlers.contains(eh) )
322             {
323                 ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
324                 initializedHandlers.add( eh );
325             }
326         }
327 
328         for ( Iterator i = methodExceptionHandlers.iterator(); i.hasNext(); )
329         {
330             EventHandler eh = ( EventHandler ) i.next();
331             if ( (eh instanceof RuntimeServicesAware) &&
332                     !initializedHandlers.contains(eh) )
333             {
334                 ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
335                 initializedHandlers.add( eh );
336             }
337         }
338 
339         for ( Iterator i = includeHandlers.iterator(); i.hasNext(); )
340         {
341             EventHandler eh = ( EventHandler ) i.next();
342             if ( (eh instanceof RuntimeServicesAware) &&
343                     !initializedHandlers.contains(eh) )
344             {
345                 ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
346                 initializedHandlers.add( eh );
347             }
348         }
349 
350         for ( Iterator i = invalidReferenceHandlers.iterator(); i.hasNext(); )
351         {
352             EventHandler eh = ( EventHandler ) i.next();
353             if ( (eh instanceof RuntimeServicesAware) &&
354                     !initializedHandlers.contains(eh) )
355             {
356                 ((RuntimeServicesAware) eh).setRuntimeServices ( rs );
357                 initializedHandlers.add( eh );
358             }
359         }
360 
361     }
362 
363 
364 }