001: /*
002: * Danet GmbH
003: *
004: * $Id: WebActionHandler.java,v 1.2 2007/03/27 21:59:44 mlipp Exp $
005: *
006: * $Log: WebActionHandler.java,v $
007: * Revision 1.2 2007/03/27 21:59:44 mlipp
008: * Fixed lots of checkstyle warnings.
009: *
010: * Revision 1.1.1.1 2003/06/30 20:05:12 drmlipp
011: * Initial import
012: *
013: * Revision 1.6 2003/04/25 14:50:59 lipp
014: * Fixed javadoc errors and warnings.
015: *
016: * Revision 1.5 2002/09/11 14:55:03 schlue
017: * Dispatcher enhanced for extended AMN specification (IE bug).
018: *
019: * Revision 1.4 2001/11/23 16:11:50 schlue
020: * Verification of duplicate action handlers added.
021: *
022: * Revision 1.3 2001/11/22 16:49:55 schlue
023: * Modifications for web actions completed
024: *
025: * Revision 1.2 2001/11/15 16:27:05 schlue
026: * Implementation completed. Everything tested except adding of a handler suite.
027: *
028: * Revision 1.1 2001/10/25 07:24:16 lipp
029: * Moved to webaction util/web/action.
030: *
031: */
032: package de.danet.an.util.web.action;
033:
034: import java.lang.reflect.InvocationTargetException;
035: import java.util.List;
036: import java.util.Map;
037: import java.util.ArrayList;
038: import java.lang.reflect.Method;
039: import javax.servlet.http.HttpServletRequest;
040:
041: /**
042: * <code>WebActionHandler</code> is the base class for web action
043: * request handlers. A derived class creates one or more instances of
044: * itself (and thus <code>WebActionHandler</code>) by calling the
045: * constructor with the name of its method that is to be made
046: * invokable as an argument.
047: */
048: public class WebActionHandler {
049:
050: // Prefix for Web Action Parameter identifier in requests
051: private static final String PARAM_PARAM = "WAP";
052: // Name of action handled by this object
053: private String myActionName = null;
054: // Method object that has to be invoked for action handling
055: private Method myActionMethod = null;
056: // Number of parameters, declared for handling the action
057: private int paramCnt = 0;
058: // Flag, indicating that first parameter is of type HttpServletRequest
059: private boolean firstParameterIsServletRequest = false;
060:
061: /**
062: * Used by derived classes to construct web action handlers. Web
063: * action handlers thus constructed are assembled into collections
064: * by a static method <code>WebActionDispatcher suite()</code> that
065: * must be supplied by every class derived from
066: * <code>WebActionHandler</code>. A derived class thus looks like:
067: * <pre>
068: * public class MyActs extends WebActionHandler {
069: * public MyActs(String method) {
070: * super(method);
071: * }
072: *
073: * public static WebActionDispatcher suite() {
074: * WebActionDispatcher suite = new WebActionDispatcher();
075: * suite.addHandler(new MyActs("addSomething"));
076: * }
077: *
078: * public void addSomething(String arg1, String arg2) {
079: * // This function may be invoked with a request
080: * // ...?WAA=addSomething&WAP1=arg1&WAP2=arg2
081: * }
082: * }
083: * </pre>
084: * The method that handles the action may have parameters
085: * of type {@link java.lang.String <code>String</code>} only - with
086: * one exception. The first parameter may optionally be a
087: * <code>javax.servlet.http.HttpServletRequest</code>. If the first
088: * paramter is of that type, the request object is passed to the method
089: * in addition to the specific <code>WAP<i>n</i></code> parameter values.
090: * @param methodName the name of the class' method to be invoked.
091: * The method name has to be unique, the return value of the method has
092: * to be of type void and the parameters have to fulfill the requirements
093: * stated above. Otherwise an IllegalArgumentException is thrown.
094: */
095: protected WebActionHandler(String methodName) {
096: this (methodName, methodName);
097: }
098:
099: /**
100: * An alternative constructor that may be used to assign an action
101: * name (used in the HTTP request) that differs from the method
102: * name.
103: * @param methodName the name of the class' method to be invoked.
104: * @param actionName the name to be used as parameter <code>WAA</code>
105: * in the HTTP request.
106: */
107: protected WebActionHandler(String methodName, String actionName) {
108: myActionName = actionName;
109: myActionMethod = findMethod(methodName);
110: // No method found -> no action can be performed
111: if (myActionMethod == null) {
112: throw new IllegalArgumentException(methodName);
113: }
114: // check return type, has to be void
115: if (myActionMethod.getReturnType() != void.class) {
116: throw new IllegalArgumentException(methodName);
117: }
118: // determine method parameters
119: Class[] params = myActionMethod.getParameterTypes();
120: int i = 0;
121: // (only) first parameter may be of type HttpServletRequest
122: if (params[0].equals(HttpServletRequest.class)) {
123: firstParameterIsServletRequest = true;
124: i++;
125: }
126: while (i < params.length) {
127: if (!params[i].equals(String.class)) {
128: throw new IllegalArgumentException(params[i].getName());
129: }
130: i++;
131: // only parameters of type String are counted
132: paramCnt++;
133: }
134: }
135:
136: /**
137: * Adds this <code>WebActionHandler</code> to a map that
138: * associates action names with <code>WebActionHandler</code>s.
139: * @param map the map this handler is to be inserted to.
140: * @param verifyDuplicates flag, indicating if it should be verified that
141: * currently no other action handler is registered with this action name.
142: * In case of an duplicate entry, an IllegalStateException is thrown.
143: */
144: void addToMap(Map map, boolean verifyDuplicates) {
145: // this method has package visibility as it is only used by
146: // WebActionDispatcher.
147: Object oldActionHandler = map.put(myActionName, this );
148: if (verifyDuplicates && (oldActionHandler != null)) {
149: throw new IllegalStateException(oldActionHandler.toString());
150: }
151: }
152:
153: /**
154: * Handles the given request. This method is called only if the request's
155: * <code>WAA</code> parameter matches this handlers's action name, i.e.
156: * this method need not evaluate the <code>WAA</code> parameter.
157: * @param request the request to be handled.
158: * @throws IllegalAccessException if an action method cannot be accessed
159: * @throws InvocationTargetException if an action method cannot be invoked
160: */
161: void handleRequest(HttpServletRequest request)
162: throws IllegalAccessException, InvocationTargetException {
163: // this method has package visibility as it is only used by
164: // WebActionDispatcher.
165: List parameters = new ArrayList();
166: if (firstParameterIsServletRequest) {
167: parameters.add(request);
168: }
169:
170: // extract parameters WAPnn
171: for (int i = 1; i <= paramCnt; i++) {
172: final String paramname = new String(PARAM_PARAM + i);
173: // Missing WAPnn entries will be delivered as "null" strings
174: parameters.add(request.getParameter(paramname));
175: }
176: myActionMethod.invoke(this , parameters.toArray());
177: }
178:
179: /**
180: * Search method with given name in current (derived) class.
181: * The method name has to be unique within the class or otherwise an
182: * IllegalArgumentException is thrown.
183: * @param methodName the name of the class' method to be found.
184: * in the HTTP request.
185: * @return method object
186: */
187: private Method findMethod(String methodName) {
188: Method actionMethod = null;
189: Method[] myMethods = this .getClass().getMethods();
190: for (int i = 0; i < myMethods.length; i++) {
191: if (myMethods[i].getName().equals(methodName)) {
192: if (actionMethod == null) {
193: actionMethod = myMethods[i];
194: } else {
195: // Oops, two methods with this name.
196: // Don't know which one to take
197: throw new IllegalArgumentException(methodName);
198: }
199: }
200: }
201: return actionMethod;
202: }
203: }
|