001: /*
002: * Danet GmbH
003: *
004: * $Id: WebActionDispatcher.java,v 1.2 2005/09/10 21:44:18 mlipp Exp $
005: *
006: * $Log: WebActionDispatcher.java,v $
007: * Revision 1.2 2005/09/10 21:44:18 mlipp
008: * Fixed JDK 5.0 warnings.
009: *
010: * Revision 1.1.1.1 2003/06/30 20:05:12 drmlipp
011: * Initial import
012: *
013: * Revision 1.9 2003/04/25 14:50:59 lipp
014: * Fixed javadoc errors and warnings.
015: *
016: * Revision 1.8 2003/04/24 20:50:13 lipp
017: * Fixed some warnings.
018: *
019: * Revision 1.7 2001/12/07 09:45:34 schlue
020: * doccheck
021: *
022: * Revision 1.6 2001/11/23 16:11:50 schlue
023: * Verification of duplicate action handlers added.
024: *
025: * Revision 1.5 2001/11/22 16:49:55 schlue
026: * Modifications for web actions completed
027: *
028: * Revision 1.4 2001/11/20 14:19:28 schlue
029: * First version of web action handler framework implemented.
030: * Sample action handler for staff management supplied.
031: *
032: * Revision 1.3 2001/11/15 16:27:05 schlue
033: * Implementation completed. Everything tested except adding of a handler suite.
034: *
035: * Revision 1.2 2001/10/25 10:53:24 lipp
036: * Javadoc problems fixed.
037: *
038: * Revision 1.1 2001/10/25 07:24:16 lipp
039: * Moved to webaction util/web/action.
040: *
041: */
042: package de.danet.an.util.web.action;
043:
044: import java.util.ArrayList;
045: import java.util.Collection;
046: import java.util.HashMap;
047: import java.util.Iterator;
048: import java.util.List;
049: import java.util.Map;
050:
051: import java.lang.reflect.InvocationTargetException;
052: import java.lang.reflect.Method;
053:
054: import javax.servlet.http.HttpServletRequest;
055:
056: /**
057: * A <code>WebActionDispatcher</code> is a collection of
058: * {@link de.danet.an.util.web.action.WebActionHandler
059: * <code>WebActionHandler</code>s} and
060: * <code>WebActionDispatcher</code>s.
061: * <code>WebActionDispatcher</code>s are usually created by
062: * {@link de.danet.an.util.web.action.WebActionHandler
063: * <code>WebActionHandler</code>s} that want to register on or more of
064: * their methods. A "top level" <code>WebActionDispatcher</code> is
065: * used to collect all handlers. This dispatcher is used to handle
066: * requests by calling its
067: * {@link de.danet.an.util.web.action.WebActionDispatcher#dispatchRequest
068: * <code>dispatchRequest</code>} methods.
069: */
070: public class WebActionDispatcher {
071:
072: // Identifier for Web Action Action in requests
073: private static final String ACTION_PARAM = "WAA";
074: /* List of registered classes, derived from WebActionHandler
075: * and providing a "suite" method that returns a WebActionDispatcher */
076: private List registeredDispatchers = new ArrayList();
077: // List of registered WebActionHandler objects
078: private List registeredHandlers = new ArrayList();
079: // Cache for storing supported actions
080: private Map actionMap = null;
081: // Flag for verifying duplicate action names
082: private boolean verifyDuplicateActions = true;
083:
084: /**
085: * Constructs a dispatcher that doesn't handle any requests yet.
086: */
087: public WebActionDispatcher() {
088: }
089:
090: /**
091: * Adds a single {@link de.danet.an.util.web.action.WebActionHandler
092: * <code>WebActionHandler</code>}.
093: * @param handler the handler to be added.
094: */
095: public void addHandler(WebActionHandler handler) {
096: registeredHandlers.add(handler);
097: }
098:
099: /**
100: * Adds a {@link de.danet.an.util.web.action.WebActionHandler
101: * <code>WebActionHandler</code>} class, i.e. all handlers
102: * returned by its static <code>suite()</code> method (as another
103: * <code>WebActionDispatcher</code>).
104: * @param dispatcher the suite of handlers to be added. The
105: * <code>dispatcher</code> class must be derived from
106: * {@link de.danet.an.util.web.action.WebActionHandler
107: * <code>WebActionHandler</code>} and provide a
108: * <code>WebActionDispatcher suite()</code> method.
109: * The <code>suite()</code> method will be invoked at the first time
110: * a request is dipatched.
111: */
112: public void addHandlerSuite(java.lang.Class dispatcher) {
113: registeredDispatchers.add(dispatcher);
114: }
115:
116: /**
117: * Handles an HTTP request by finding the appropriate request
118: * handler (if any) and invoking it. The first call to this function will
119: * build a cache that maps action names to instances of
120: * {@link de.danet.an.util.web.action.WebActionHandler
121: * <code>WebActionHandler</code>}s. Thus subsequent calls of the
122: * <code>add...</code> methods will have no effect. Although
123: * tracking of container relationship and invalidating of the
124: * cache could be added with little to small effort, such a
125: * feature is currently considered unnecessary and thus omitted.
126: * @param request the request to be handled.
127: * @throws IllegalAccessException if an action method cannot be accessed
128: * @throws InvocationTargetException if an action method cannot be invoked
129: */
130: public void dispatchRequest(HttpServletRequest request)
131: throws IllegalAccessException, InvocationTargetException {
132: // first make sure we have an action map
133: if (actionMap == null) {
134: actionMap = new HashMap();
135: for (Iterator i = getHandlers().iterator(); i.hasNext();) {
136: WebActionHandler h = (WebActionHandler) i.next();
137: h.addToMap(actionMap, verifyDuplicateActions);
138: }
139: }
140: // now find and handle request
141: String action = request.getParameter(ACTION_PARAM);
142: // maybe there is nothing do be done here
143: if (action != null) {
144: WebActionHandler handler = (WebActionHandler) actionMap
145: .get(action);
146: if (handler != null) {
147: handler.handleRequest(request);
148: }
149: }
150: }
151:
152: /**
153: * Returns the handlers contained in this dispatchers, i.e. those
154: * added directly with <code>addHandler</code> as well as those
155: * added indirectly with <code>addHandlerSuite</code>.
156: * @return all handlers contained in this dispatcher.
157: */
158: protected Collection getHandlers() {
159: // Add registered handlers to result set
160: Collection res = new ArrayList(registeredHandlers);
161:
162: // loop over registered suites (WebActionDispatchers), call
163: // getHandlers and addAll to result set
164: Iterator dispatchers = registeredDispatchers.iterator();
165: while (dispatchers.hasNext()) {
166: WebActionDispatcher dispatcher = null;
167: Class handlerClass = (Class) dispatchers.next();
168: // class must be derived from WebActionHandler
169: if (WebActionHandler.class.isAssignableFrom(handlerClass)) {
170: try {
171: // and it must define a "suite" method without parameters
172: Method method = handlerClass.getDeclaredMethod(
173: "suite", new Class[0]);
174: // that returns a WebActionDispatcher
175: if (method.getReturnType() == WebActionDispatcher.class) {
176: try {
177: dispatcher = (WebActionDispatcher) method
178: .invoke(null, (Object[]) null);
179: } catch (IllegalAccessException exc) {
180: throw new IllegalStateException(
181: handlerClass.getName());
182: } catch (InvocationTargetException exc) {
183: throw new IllegalStateException(
184: handlerClass.getName());
185: }
186: } else {
187: throw new IllegalStateException(handlerClass
188: .getName());
189: }
190: } catch (NoSuchMethodException exc) {
191: throw new IllegalStateException(handlerClass
192: .getName());
193: }
194: } else {
195: throw new IllegalStateException(handlerClass.getName());
196: }
197: res.addAll(dispatcher.getHandlers());
198: }
199: return res;
200: }
201:
202: /**
203: * Returns the current value of the flag for verifying duplicate action
204: * names.
205: * @see #setVerifyDuplicateActionsFlag
206: * @return flag
207: */
208: public boolean getVerifyDuplicateActionsFlag() {
209: return verifyDuplicateActions;
210: }
211:
212: /**
213: * Sets the current value of the flag for verifying duplicate action
214: * names.
215: * @param flag new flag value
216: * @see #getVerifyDuplicateActionsFlag
217: */
218: public void setVerifyDuplicateActionsFlag(boolean flag) {
219: verifyDuplicateActions = flag;
220: }
221: }
|