001: package org.apache.velocity.app.event;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.util.ArrayList;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Set;
027:
028: import org.apache.velocity.context.Context;
029: import org.apache.velocity.context.InternalEventContext;
030: import org.apache.velocity.runtime.RuntimeServices;
031: import org.apache.velocity.util.RuntimeServicesAware;
032:
033: /**
034: * Stores the event handlers. Event handlers can be assigned on a per
035: * VelocityEngine instance basis by specifying the class names in the
036: * velocity.properties file. Event handlers may also be assigned on a per-page
037: * basis by creating a new instance of EventCartridge, adding the event
038: * handlers, and then calling attachToContext. For clarity, it's recommended
039: * that one approach or the other be followed, as the second method is primarily
040: * presented for backwards compatibility.
041: *
042: * <P>
043: * Note that Event Handlers follow a filter pattern, with multiple event
044: * handlers allowed for each event. When the appropriate event occurs, all the
045: * appropriate event handlers are called in the sequence they were added to the
046: * Event Cartridge. See the javadocs of the specific event handler interfaces
047: * for more details.
048: *
049: * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a>
050: * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr. </a>
051: * @author <a href="mailto:j_a_fernandez@yahoo.com">Jose Alberto Fernandez </a>
052: * @version $Id: EventCartridge.java 470256 2006-11-02 07:20:36Z wglass $
053: */
054: public class EventCartridge {
055: private List referenceHandlers = new ArrayList();
056: private List nullSetHandlers = new ArrayList();
057: private List methodExceptionHandlers = new ArrayList();
058: private List includeHandlers = new ArrayList();
059: private List invalidReferenceHandlers = new ArrayList();
060:
061: /**
062: * Ensure that handlers are not initialized more than once.
063: */
064: Set initializedHandlers = new HashSet();
065:
066: /**
067: * Adds an event handler(s) to the Cartridge. This method
068: * will find all possible event handler interfaces supported
069: * by the passed in object.
070: *
071: * @param ev object impementing a valid EventHandler-derived interface
072: * @return true if a supported interface, false otherwise or if null
073: */
074: public boolean addEventHandler(EventHandler ev) {
075: if (ev == null) {
076: return false;
077: }
078:
079: boolean found = false;
080:
081: if (ev instanceof ReferenceInsertionEventHandler) {
082: addReferenceInsertionEventHandler((ReferenceInsertionEventHandler) ev);
083: found = true;
084: }
085:
086: if (ev instanceof NullSetEventHandler) {
087: addNullSetEventHandler((NullSetEventHandler) ev);
088: found = true;
089: }
090:
091: if (ev instanceof MethodExceptionEventHandler) {
092: addMethodExceptionHandler((MethodExceptionEventHandler) ev);
093: found = true;
094: }
095:
096: if (ev instanceof IncludeEventHandler) {
097: addIncludeEventHandler((IncludeEventHandler) ev);
098: found = true;
099: }
100:
101: if (ev instanceof InvalidReferenceEventHandler) {
102: addInvalidReferenceEventHandler((InvalidReferenceEventHandler) ev);
103: found = true;
104: }
105:
106: return found;
107: }
108:
109: /**
110: * Add a reference insertion event handler to the Cartridge.
111: *
112: * @param ev ReferenceInsertionEventHandler
113: */
114: public void addReferenceInsertionEventHandler(
115: ReferenceInsertionEventHandler ev) {
116: referenceHandlers.add(ev);
117: }
118:
119: /**
120: * Add a null set event handler to the Cartridge.
121: *
122: * @param ev NullSetEventHandler
123: */
124: public void addNullSetEventHandler(NullSetEventHandler ev) {
125: nullSetHandlers.add(ev);
126: }
127:
128: /**
129: * Add a method exception event handler to the Cartridge.
130: *
131: * @param ev MethodExceptionEventHandler
132: */
133: public void addMethodExceptionHandler(MethodExceptionEventHandler ev) {
134: methodExceptionHandlers.add(ev);
135: }
136:
137: /**
138: * Add an include event handler to the Cartridge.
139: *
140: * @param ev IncludeEventHandler
141: */
142: public void addIncludeEventHandler(IncludeEventHandler ev) {
143: includeHandlers.add(ev);
144: }
145:
146: /**
147: * Add an invalid reference event handler to the Cartridge.
148: *
149: * @param ev InvalidReferenceEventHandler
150: */
151: public void addInvalidReferenceEventHandler(
152: InvalidReferenceEventHandler ev) {
153: invalidReferenceHandlers.add(ev);
154: }
155:
156: /**
157: * Removes an event handler(s) from the Cartridge. This method will find all
158: * possible event handler interfaces supported by the passed in object and
159: * remove them.
160: *
161: * @param ev object impementing a valid EventHandler-derived interface
162: * @return true if event handler was previously registered, false if not
163: * found
164: */
165: public boolean removeEventHandler(EventHandler ev) {
166: if (ev == null) {
167: return false;
168: }
169:
170: boolean found = false;
171:
172: if (ev instanceof ReferenceInsertionEventHandler)
173: return referenceHandlers.remove(ev);
174:
175: if (ev instanceof NullSetEventHandler)
176: return nullSetHandlers.remove(ev);
177:
178: if (ev instanceof MethodExceptionEventHandler)
179: return methodExceptionHandlers.remove(ev);
180:
181: if (ev instanceof IncludeEventHandler)
182: return includeHandlers.remove(ev);
183:
184: if (ev instanceof InvalidReferenceEventHandler)
185: return invalidReferenceHandlers.remove(ev);
186:
187: return found;
188: }
189:
190: /**
191: * Iterate through all the stored ReferenceInsertionEventHandler objects
192: *
193: * @return iterator of handler objects
194: */
195: public Iterator getReferenceInsertionEventHandlers() {
196: return referenceHandlers.iterator();
197: }
198:
199: /**
200: * Iterate through all the stored NullSetEventHandler objects
201: *
202: * @return iterator of handler objects
203: */
204: public Iterator getNullSetEventHandlers() {
205: return nullSetHandlers.iterator();
206: }
207:
208: /**
209: * Iterate through all the stored MethodExceptionEventHandler objects
210: *
211: * @return iterator of handler objects
212: */
213: public Iterator getMethodExceptionEventHandlers() {
214: return methodExceptionHandlers.iterator();
215: }
216:
217: /**
218: * Iterate through all the stored IncludeEventHandlers objects
219: *
220: * @return iterator of handler objects
221: */
222: public Iterator getIncludeEventHandlers() {
223: return includeHandlers.iterator();
224: }
225:
226: /**
227: * Iterate through all the stored InvalidReferenceEventHandlers objects
228: *
229: * @return iterator of handler objects
230: */
231: public Iterator getInvalidReferenceEventHandlers() {
232: return invalidReferenceHandlers.iterator();
233: }
234:
235: /**
236: * Attached the EventCartridge to the context
237: *
238: * Final because not something one should mess with lightly :)
239: *
240: * @param context context to attach to
241: * @return true if successful, false otherwise
242: */
243: public final boolean attachToContext(Context context) {
244: if (context instanceof InternalEventContext) {
245: InternalEventContext iec = (InternalEventContext) context;
246:
247: iec.attachEventCartridge(this );
248:
249: /**
250: * while it's tempting to call setContext on each handler from here,
251: * this needs to be done before each method call. This is
252: * because the specific context will change as inner contexts
253: * are linked in through macros, foreach, or directly by the user.
254: */
255:
256: return true;
257: } else {
258: return false;
259: }
260: }
261:
262: /**
263: * Initialize the handlers. For global handlers this is called when Velocity
264: * is initialized. For local handlers this is called when the first handler
265: * is executed. Handlers will not be initialized more than once.
266: *
267: * @param rs
268: * @throws Exception
269: */
270: public void initialize(RuntimeServices rs) throws Exception {
271:
272: for (Iterator i = referenceHandlers.iterator(); i.hasNext();) {
273: EventHandler eh = (EventHandler) i.next();
274: if ((eh instanceof RuntimeServicesAware)
275: && !initializedHandlers.contains(eh)) {
276: ((RuntimeServicesAware) eh).setRuntimeServices(rs);
277: initializedHandlers.add(eh);
278: }
279: }
280:
281: for (Iterator i = nullSetHandlers.iterator(); i.hasNext();) {
282: EventHandler eh = (EventHandler) i.next();
283: if ((eh instanceof RuntimeServicesAware)
284: && !initializedHandlers.contains(eh)) {
285: ((RuntimeServicesAware) eh).setRuntimeServices(rs);
286: initializedHandlers.add(eh);
287: }
288: }
289:
290: for (Iterator i = methodExceptionHandlers.iterator(); i
291: .hasNext();) {
292: EventHandler eh = (EventHandler) i.next();
293: if ((eh instanceof RuntimeServicesAware)
294: && !initializedHandlers.contains(eh)) {
295: ((RuntimeServicesAware) eh).setRuntimeServices(rs);
296: initializedHandlers.add(eh);
297: }
298: }
299:
300: for (Iterator i = includeHandlers.iterator(); i.hasNext();) {
301: EventHandler eh = (EventHandler) i.next();
302: if ((eh instanceof RuntimeServicesAware)
303: && !initializedHandlers.contains(eh)) {
304: ((RuntimeServicesAware) eh).setRuntimeServices(rs);
305: initializedHandlers.add(eh);
306: }
307: }
308:
309: for (Iterator i = invalidReferenceHandlers.iterator(); i
310: .hasNext();) {
311: EventHandler eh = (EventHandler) i.next();
312: if ((eh instanceof RuntimeServicesAware)
313: && !initializedHandlers.contains(eh)) {
314: ((RuntimeServicesAware) eh).setRuntimeServices(rs);
315: initializedHandlers.add(eh);
316: }
317: }
318:
319: }
320:
321: }
|