KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > verge > mvc > controller > actionflow > ActionHandlerNodeExecutor


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.verge.mvc.controller.actionflow;
8
9
10 import java.util.Collections JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13
14 import com.inversoft.beans.BeanException;
15 import com.inversoft.verge.mvc.controller.BeanHandle;
16 import com.inversoft.verge.mvc.controller.actionflow.config.Namespace;
17 import com.inversoft.verge.mvc.controller.actionflow.config.Node;
18 import com.inversoft.verge.repository.Repository;
19 import com.inversoft.verge.repository.RepositoryException;
20
21
22 /**
23  * This class is the executor for action handler Nodes. This
24  * executor handles repository lookups, class instantiation
25  * and handle method calling on ActionHandler Nodes.
26  *
27  * @author Brian Pontarelli
28  * @since 2.0
29  * @version 2.0
30  */

31 public class ActionHandlerNodeExecutor implements NodeExecutor {
32
33     /**
34      * The name of the method that handles all the exceptions
35      */

36     public static final String JavaDoc EXCEPTION_HANDLE_METHOD = "exception";
37
38     /**
39      * The parameter list to the handleX methods
40      */

41     public static final Class JavaDoc [] HANDLE_PARAMS = new Class JavaDoc [] {ActionFlowAction.class};
42
43     /**
44      * Global switch for caching. This does not work yet so it is turned off. The
45      * problem is that the class can have two methods that take two different
46      * parameters, but both are valid handle methods.
47      */

48     static final boolean CACHING = true;
49
50     /**
51      * The cache Map for the BeanProperty objects (unsynchronized)
52      */

53     static Map JavaDoc cache = new HashMap JavaDoc();
54
55
56     //--------------------------------------------------------------------------
57
// Cache Methods
58
//--------------------------------------------------------------------------
59

60
61     /**
62      * Returns an instance of the BeanHandle for the given handleName and
63      * bean Class. This object might be cached, depending on the implementation
64      * of this method. Therefore, you must take into account a cached or non-
65      * cached object.
66      *
67      * @param handleName The handle name of the BeanHandle
68      * @param beanClass The bean Class
69      * @return The BeanHandle and never null
70      * @throws BeanException If the creation of the obejct fails
71      */

72     private static BeanHandle getBeanHandle(String JavaDoc handleName, Class JavaDoc beanClass)
73     throws BeanException {
74
75         // If not caching, just create the objects
76
if (!CACHING) {
77             return new BeanHandle(handleName, beanClass, HANDLE_PARAMS);
78         }
79
80         // Otherwise look for the property Map or create and store
81
Map JavaDoc propMap = null;
82         synchronized (cache) {
83             propMap = (Map JavaDoc) cache.get(beanClass);
84             if (propMap == null) {
85                 propMap = Collections.synchronizedMap(new HashMap JavaDoc());
86                 cache.put(beanClass, propMap);
87             }
88         }
89
90         // Look for the property itself, or create and store
91
BeanHandle bh = null;
92         synchronized (propMap) {
93             bh = (BeanHandle) propMap.get(handleName);
94             if (bh == null) {
95                 bh = new BeanHandle(handleName, beanClass, HANDLE_PARAMS);
96                 propMap.put(handleName, bh);
97             }
98         }
99
100         return bh;
101     }
102
103
104     /**
105      * Constructs a new <code>ActionHandlerNodeExecutor</code>.
106      */

107     public ActionHandlerNodeExecutor() {
108     }
109
110
111     /**
112      * Executes the ActionHandler Node described in the Node object given. This
113      * Object will contain the information required to correctly locate or
114      * instantiate an ActionHandler class. The ActionFlowAction given contains
115      * the information about the handle method to execute using the action
116      * String. Namespace and extra params are not used.
117      *
118      * @param namespace The Namespace the Node is located in
119      * @param config The ActionHandlerNode that describes what to execute
120      * @param action The current action of the ActionFlow itself. This is where
121      * the HTTP Objects are stored.
122      * @param extraParams A Map of extra params that have been passed into the
123      * ActionFlow system.
124      * @return An Object containing the resulting action of execution. That
125      * is to say, if executing the Node caused another action to be
126      * generated, it is returned. Usually, this is simply a String
127      * However, if it is any other class, th toString() method is used
128      * to determine the action to take.
129      * @throws Exception If execution of the Node threw any Exception, it is re-
130      * thrown. Otherwise, this throws a NodeExecutorException if there was
131      * a problem during instantiation or invocation
132      */

133     public Object JavaDoc execute(Namespace namespace, Node config, ActionFlowAction action,
134         Map JavaDoc extraParams)
135     throws Exception JavaDoc {
136         assert (config != null) : "config == null";
137         assert (action != null) : "action == null";
138         assert (action.getAction() != null) : "action.getAction() == null";
139
140         Object JavaDoc handler = findActionHandler(config, action);
141
142         return callHandleMethod(handler, action);
143     }
144
145     /**
146      * Using the Node configuration object and the ActionFlowAction, find the instance
147      * of the ActionHandler to execute
148      */

149     Object JavaDoc findActionHandler(Node config, ActionFlowAction action)
150     throws NodeExecutorException
151     {
152         if (config.getClassName() != null) {
153             try {
154                 Class JavaDoc klass = Class.forName(config.getClassName());
155                 return klass.newInstance();
156             } catch (Exception JavaDoc e) {
157                 throw new NodeExecutorException(e);
158             }
159         }
160
161         try {
162             return Repository.getInstance().lookupItem(action.getHttpServletRequest(),
163                 config.getRepositoryId());
164         } catch (RepositoryException re) {
165             throw new NodeExecutorException(re);
166         }
167     }
168
169     /**
170      * Calls the handleX method on the object where X is the name of the action. If the
171      * action is an Exception, this method calls the handleException(Exception exception,
172      * ActionFlowAction action) method.
173      */

174     Object JavaDoc callHandleMethod(Object JavaDoc handler, ActionFlowAction action)
175     throws Exception JavaDoc {
176         Object JavaDoc actionObj = action.getAction();
177         String JavaDoc methodName = null;
178         Object JavaDoc [] params = new Object JavaDoc[] {action};
179
180
181         if (actionObj instanceof Exception JavaDoc) {
182             methodName = EXCEPTION_HANDLE_METHOD;
183         } else if (actionObj instanceof String JavaDoc) {
184             methodName = action.getAction().toString();
185         } else {
186             assert (false) : "action is of type not supported by ActionHandlers";
187         }
188
189         try {
190             BeanHandle bh = ActionHandlerNodeExecutor.getBeanHandle(methodName,
191                 handler.getClass());
192             return bh.invokeHandle(handler, params);
193         } catch (BeanException be) {
194             Throwable JavaDoc t = be.getCause();
195             if (t != null) {
196                 if (t instanceof Exception JavaDoc) {
197                     throw (Exception JavaDoc) t;
198                 } else {
199                     throw new Error JavaDoc("Unhandlable direct sub-class of Throwable", t);
200                 }
201             } else {
202                 throw new NodeExecutorException("Error calling handle method", be);
203             }
204         }
205     }
206 }
Popular Tags