KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > servlet > ActionController


1 package jodd.servlet;
2
3 import java.io.IOException;
4 import java.util.HashMap;
5
6 import javax.servlet.ServletException;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 import jodd.util.ReflectUtil;
11 import jodd.util.StringUtil;
12
13 /**
14  * Represents a controller part of mvc2 framework.
15  * <p>
16  *
17  * During initialization, configuration xml file is read and all data are
18  * loaded by controller. When request is received, controller will lookup for
19  * the adequate <code>ActionServlet.doAction()</code> or defined mapped
20  * method to invoke. Depending of the resulting string and the configuration,
21  * controller will perform forwarding or redirection to the destination view.
22  * <p>
23  *
24  * Controller allows intercepting of all invoked actions, by using the ActionFilter.
25  *
26  * @see ActionServlet
27  * @see ActionFilter
28  */

29 public class ActionController extends ActionServlet {
30
31     /**
32      * Holds all actions defined in xml configuration files.
33      */

34     private HashMap actionsMap = new HashMap();
35     /**
36      * Holds all global data.
37      */

38     private ActionData global_forwards = new ActionData();
39     /**
40      * Global controller ActionFilter.
41      */

42     private ActionFilter actionFilter = null;
43
44     // ---------------------------------------------------------------- init
45

46     private String configPath;
47     private String configFile;
48     private String configFilter;
49
50     /**
51      * Initialization of the controler. Reads all actions xml configuration
52      * files and populates actionsMap; and initialize ActionFilter if defined.
53      *
54      * @param config actionsMap
55      *
56      * @exception ServletException
57      * @see #reload
58      */

59     public void init(javax.servlet.ServletConfig config) throws ServletException {
60         super.init(config);
61         
62         // build path for the main config file
63
configPath = config.getServletContext().getRealPath("");
64         configFile = config.getInitParameter("config");
65         configFilter = config.getInitParameter("filter");
66
67         reload();
68     }
69
70     /**
71      * Reloads configuration XML files. This method should be used in
72      * developement, since it is not synchronized with the main dispatcher. It
73      * re-reads configuration files and resets all ActionServlet settings, while
74      * server and controller are active. This makes posible to change
75      * configuration without restarting server.
76      */

77     public void reload() throws ServletException {
78         actionsMap = new HashMap();
79         global_forwards = new ActionData();
80         ActionControllerUtil.parseFile(actionsMap, global_forwards, configPath, configFile);
81
82         if (configFilter != null) {
83             ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
84             if (classLoader == null) {
85                 classLoader = ActionController.class.getClassLoader();
86             }
87             try {
88                 Class c = classLoader.loadClass(configFilter);
89                 actionFilter = (ActionFilter) c.newInstance();
90             } catch (Exception ex) {
91                 actionFilter = null;
92             }
93         } else {
94             actionFilter = null;
95         }
96     }
97
98     // ---------------------------------------------------------------- doRequest
99

100
101     /**
102      * Unique request parameter name that holds ActionData for the current
103      * invoked action, as defined in the configuration xml file. It is used
104      * internally.
105      *
106      * @see jodd.servlet.ActionData
107      */

108     public static String ACTION_DATA = "jodd.servlet.ActionController.actionData";
109
110     /**
111      * Unique request parameter name that holds action path of the the current
112      * invoked action, as defined in the configuration xml file. It is used
113      * internally.
114      */

115     public static String ACTION_PATH = "jodd.servlet.ActionController.actionPath";
116     
117     /**
118      * Unique <b>global</b> forward name that will be used in case when action is
119      * not mapped to a request.
120      */

121     public static String ACTION_NOT_FOUND = "jodd.servlet.ActionController.actionNotFound";
122     
123     /**
124      * Request dispatcher - the controller.<p>
125      *
126      * The request uri will be processed first. Controller will try to find
127      * specific Action type (defined in actions xml configuration file). Very
128      * first time when action is required its class (child of ActionServlet) will
129      * be loaded and instanced. Next time, actions instance will be found in the
130      * buffer, so actions will be instanced just once (when accessed first time).
131      * <p>
132      *
133      * If Action can not be found, controller will forward to ACTION_NOT_FOUND
134      * global forward mapping.
135      * <p>
136      *
137      * Method doAction() will be invoked on founded action. This method returns a
138      * string that represents a forward name (defined in actions xml
139      * configuration file). Alternatively, if defined so, mapped method will be
140      * invoked.
141      * <p>
142      *
143      * On the end, controller will perform forward or redirection to path defined
144      * with returned forward name string (that doAction() returns), as defined in
145      * configuration file. If forward name can not be found, then global forwards
146      * will be examined. If global forward can not be found, that it is assumed
147      * that no forwards are used, and that returned string represents a page.
148      *
149      * @param request
150      * @param response
151      *
152      * @exception IOException
153      * @exception ServletException
154      */

155     public void doRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
156         String uri = request.getRequestURI();
157         String ctxPath = request.getContextPath();
158         int i = uri.indexOf(ctxPath);
159         String actionPath = uri.substring(i + ctxPath.length());
160
161         ActionData actionData = (ActionData) actionsMap.get(actionPath);
162         if (actionData == null) {
163             String actionNotFoundPath = global_forwards.getForwardPath(ACTION_NOT_FOUND);
164             if (actionNotFoundPath == null) {
165                 actionNotFoundPath = ACTION_NOT_FOUND;
166             }
167             forward(request, response, actionNotFoundPath);
168             return;
169         }
170
171         // invoke action and get results
172
String actionResult = invokeAction(request, response, actionData, actionPath);
173
174         // forward/redirect:
175
// split returned forward to uri and parameters.
176
// first examine local forwards and then global forwards.
177
// if none found, assume it is a normal page.
178
if (actionResult != null) {
179             String actionResultUri = actionResult;
180             String actionResultParams = "";
181             i = actionResult.indexOf('?');
182             if (i != -1) {
183                 actionResultUri = actionResult.substring(0, i);
184                 actionResultParams = actionResult.substring(i + 1);
185             }
186
187             String fwdPath = actionData.getForwardPath(actionResultUri);
188             if (fwdPath == null) {
189                 fwdPath = global_forwards.getForwardPath(actionResultUri);
190             }
191             if (fwdPath == null) {
192                 fwdPath = actionResultUri;
193             }
194
195             // add params to fwdPath
196
if (actionResultParams.length() > 0) {
197                 i = fwdPath.indexOf('?');
198                 if (i != -1) {
199                     fwdPath += "&" + actionResultParams;
200                 } else {
201                     fwdPath += "?" + actionResultParams;
202                 }
203             }
204             if (actionData.isForwardRedirect(actionResultUri)) {
205                 redirect(request, response, fwdPath);
206             } else {
207                 forward(request, response, fwdPath);
208             }
209         }
210     }
211
212
213     // ---------------------------------------------------------------- invoke action
214

215
216     /**
217      * Unique <b>global</b> forward name that will be used in case when action is
218      * not mapped to a request.
219      */

220     public static String INVOKE_ACTION_PARAMS = "jodd.servlet.ActionController.invokeActionParams";
221
222     /**
223      * Invoke specified action as it would be invoked by ActionController.
224      *
225      * <p>
226      * NOTE: request parameters are passed from the current request!!!
227      * Instead, they are passed as a HashMap in request attribute under the key:
228      * INVOKE_ACTION_PARAMS.
229      *
230      * @param request http request
231      * @param response http response
232      * @param actionPath action path, as defined in configuration xml file
233      *
234      * @return resulting forward String, or ACTION_NOT_FOUND if not founded
235      * @exception IOException
236      * @exception ServletException
237      * @see #doRequest
238      */

239     public String invokeAction(HttpServletRequest request, HttpServletResponse response, String actionPath) throws IOException, ServletException {
240         String actionPathUri = actionPath;
241         int i = actionPath.indexOf('?');
242         if (i != -1) {
243             actionPathUri = actionPath.substring(0, i);
244             HashMap map = ServletUtil.getUrlParams(actionPath);
245             request.setAttribute(INVOKE_ACTION_PARAMS, map);
246         }
247
248         ActionData actionData = (ActionData) actionsMap.get(actionPathUri);
249         if (actionData == null) {
250             return ACTION_NOT_FOUND;
251         }
252         return invokeAction(request, response, actionData, actionPathUri);
253     }
254
255     /**
256      * Invokes an request once ActionData has been found.
257      *
258      * @param request http request
259      * @param response http responce
260      * @param actionData valida action data
261      * @param actionPath valid action path
262      *
263      * @return action forward string
264      * @exception IOException
265      * @exception ServletException
266      */

267     private String invokeAction(HttpServletRequest request, HttpServletResponse response, ActionData actionData, String actionPath) throws IOException, ServletException {
268
269         ActionServlet action = actionData.getAction();
270
271         // is action already loaded ?
272
if (action == null) {
273             ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
274             if (classLoader == null) {
275                 classLoader = ActionController.class.getClassLoader();
276             }
277             try {
278                 Class c = classLoader.loadClass((String) actionData.getType());
279                 action = (ActionServlet) c.newInstance();
280             } catch (Exception ex) {
281                 action = null;
282                 throw new ServletException("can't load ActionServlet " + (String)actionData.getType(), ex);
283             }
284             action.controller = this; // store controller reference in each action servlet
285
actionData.setAction(action);
286             actionsMap.put(actionPath, actionData);
287         }
288
289         // invoke founded action
290
String actionResult = null;
291         if (action != null) {
292             request.setAttribute(ACTION_DATA, actionData);
293             request.setAttribute(ACTION_PATH, actionPath);
294             String method = actionData.getMethod();
295             
296             // invoke filter
297
String actionFilterResult = null;
298             if (actionFilter != null) {
299                 actionFilterResult = actionFilter.onAction(request, response, action);
300             }
301             if (actionFilterResult == null) {
302                 if (method == null) {
303                     // invoke default method
304
actionResult = action.doAction(request, response);
305                 } else {
306                     // invoke mapped metod
307
try {
308                         // faster:
309
actionResult = StringUtil.toString(ReflectUtil.invoke(action, method, new Object[] {request, response}, new Class[] {HttpServletRequest.class, HttpServletResponse.class}));
310                         // slower:
311
//actionResult = StringUtil.toString(ReflectUtil.invoke(action, method, new Object[] {request, response}));
312
} catch (Exception ex) {
313                     }
314                 }
315                 if (actionFilter != null) {
316                     actionFilterResult = actionFilter.onAfterAction(request, response, action, actionResult);
317                     if (actionFilterResult != null) {
318                         actionResult = actionFilterResult;
319                     }
320                 }
321             } else {
322                 actionResult = actionFilterResult;
323             }
324         }
325         return actionResult;
326     }
327
328 }
329
Popular Tags