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 }