View Javadoc

1   /*
2    * Copyright (c) 2001 - 2005 ivata limited.
3    * All rights reserved.
4    * -----------------------------------------------------------------------------
5    * ivata masks may be redistributed under the GNU General Public
6    * License as published by the Free Software Foundation;
7    * version 2 of the License.
8    *
9    * These programs are free software; you can redistribute them and/or
10   * modify them under the terms of the GNU General Public License
11   * as published by the Free Software Foundation; version 2 of the License.
12   *
13   * These programs are distributed in the hope that they will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16   *
17   * See the GNU General Public License in the file LICENSE.txt for more
18   * details.
19   *
20   * If you would like a copy of the GNU General Public License write to
21   *
22   * Free Software Foundation, Inc.
23   * 59 Temple Place - Suite 330
24   * Boston, MA 02111-1307, USA.
25   *
26   *
27   * To arrange commercial support and licensing, contact ivata at
28   *                  http://www.ivata.com/contact.jsp
29   * -----------------------------------------------------------------------------
30   * $Log: MaskRequestProcessor.java,v $
31   * Revision 1.12  2005/04/27 17:23:27  colinmacleod
32   * Fixed bugs resulting from ivata masks changes
33   * for ivata groupware v0.11.
34   *
35   * Revision 1.11  2005/04/22 09:46:36  colinmacleod
36   * processActionCreate no longer final.
37   *
38   * Revision 1.10  2005/04/11 12:21:15  colinmacleod
39   * Changed MaskRequestProcessorImpl to
40   * MaskRequestProcessorImplementation.
41   * Improved tiles support.
42   *
43   * Revision 1.9  2005/04/09 18:04:19  colinmacleod
44   * Changed copyright text to GPL v2 explicitly.
45   *
46   * Revision 1.8  2005/01/19 13:14:02  colinmacleod
47   * Renamed CausedByException to SystemException.
48   *
49   * Revision 1.7  2005/01/07 08:08:24  colinmacleod
50   * Moved up a version number.
51   * Changed copyright notices to 2005.
52   * Updated the documentation:
53   *   - started working on multiproject:site docu.
54   *   - changed the logo.
55   * Added checkstyle and fixed LOADS of style issues.
56   * Added separate thirdparty subproject.
57   * Added struts (in web), util and webgui (in webtheme) from ivata op.
58   *
59   * Revision 1.6  2004/12/29 15:34:07  colinmacleod
60   * Improved checking for non-ivata masks forms.
61   *
62   * Revision 1.5  2004/12/23 21:28:32  colinmacleod
63   * Modifications to add ivata op compatibility.
64   *
65   * Revision 1.4  2004/11/12 15:10:42  colinmacleod
66   * Moved persistence classes from ivata op as a replacement for
67   * ValueObjectLocator.
68   *
69   * Revision 1.3  2004/11/11 13:49:47  colinmacleod
70   * Added log4j logging.
71   *
72   * Revision 1.2  2004/05/18 22:22:15  colinmacleod
73   * Added check not to populate if cancel was pressed.
74   *
75   * Revision 1.1.1.1  2004/05/16 20:40:33  colinmacleod
76   * Ready for 0.1 release
77   * -----------------------------------------------------------------------------
78   */
79  package com.ivata.mask.web.struts;
80  
81  import java.io.IOException;
82  
83  import javax.servlet.ServletException;
84  import javax.servlet.http.HttpServletRequest;
85  import javax.servlet.http.HttpServletResponse;
86  import javax.servlet.http.HttpSession;
87  
88  import org.apache.log4j.Logger;
89  import org.apache.struts.action.Action;
90  import org.apache.struts.action.ActionForm;
91  import org.apache.struts.action.ActionMapping;
92  import org.apache.struts.action.ActionServlet;
93  import org.apache.struts.action.RequestProcessor;
94  import org.apache.struts.config.FormBeanConfig;
95  import org.apache.struts.config.ModuleConfig;
96  import org.apache.struts.util.RequestUtils;
97  
98  import com.ivata.mask.MaskFactory;
99  import com.ivata.mask.persistence.PersistenceManager;
100 import com.ivata.mask.util.SystemException;
101 /***
102  * <p>
103  * Extend from this class if you _don't_ want to use <strong>Struts Tiles
104  * </strong>.
105  * </p>
106  *
107  * @since ivata masks 0.3 (2004-05-11)
108  * @author Colin MacLeod
109  * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
110  * @version $Revision: 1.12 $
111  */
112 public class MaskRequestProcessor extends RequestProcessor {
113     /***
114      * Logger for this class.
115      */
116     private static final Logger logger = Logger
117             .getLogger(MaskRequestProcessor.class);
118 
119     /***
120      * <p>
121      * This does all the hard work. :-)
122      * </p>
123      */
124     private MaskRequestProcessorImplementation implementation;
125     /***
126      * <p>
127      * Initializes the mask factory, the value object locator and the the
128      * standard field value converters.
129      * </p>
130      *
131      * @param maskFactory
132      *            needed to access the masks and groups of masks.
133      * @param persistenceManager
134      *            used to locate the value objects by their shared base class.
135      */
136     public MaskRequestProcessor(final MaskFactory maskFactory,
137             final PersistenceManager persistenceManager) {
138     }
139 
140     /***
141      * <p>
142      * Override this method to define how to create actions in your environment.
143      * This lets you use ivata masks with a standard framework.
144      * </p>
145      *
146      * <p>
147      * The default implementation looks for the action classes it knows about
148      * and initializes them directly. This is a simple starting point; in real
149      * life it is better to use a standard framework such as <a
150      * href="http://picocontainer.org">picocontainer </a>.
151      * </p>
152      *
153      *
154      * @param className
155      *            full path and name of the action class to be created.
156      * @param request
157      *            request for which we are creating an action.
158      * @param response
159      *            response we are sending.
160      * @param mapping
161      *            <strong>Struts </strong> mapping.
162      * @return valid action for the path, or <code>null</code> if the action
163      *         can and should be created using the default <strong>Struts
164      *         </strong> framework.
165      * @throws IOException
166      *             if the action cannot be created.
167      */
168     protected Action createAction(final String className,
169             final HttpServletRequest request,
170             final HttpServletResponse response, final ActionMapping mapping)
171             throws IOException {
172         assert (implementation != null);
173         try {
174             Action instance = implementation.createAction(className, request,
175                     response, mapping, actions, servlet);
176             if (instance != null) {
177                 instance.setServlet(servlet);
178             }
179             return instance;
180         } catch (SystemException e) {
181             response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
182                     getInternal().getMessage("actionCreate", mapping.getPath()));
183             return null;
184         }
185 
186     }
187     /***
188      * <p>
189      * Override this method to define how to create action forms in your
190      * environment. This lets you use ivata masks with a standard framework.
191      * </p>
192      *
193      * <p>
194      * The default implementation looks for the form classes it knows about and
195      * initializes them directly. This is a simple starting point; in real life
196      * it is better to use a standard framework such as <a
197      * href="http://picocontainer.org">picocontainer </a>.
198      * </p>
199      *
200      * @param formBeanConfig
201      *            instance of <code>FormBeanConfig</code> defining the form to
202      *            be created.
203      * @param request
204      *            request for which we are creating an action.
205      * @param response
206      *            response we are sending.
207      * @param mapping
208      *            <strong>Struts </strong> mapping.
209      * @return valid action for the path, or <code>null</code> if the form can
210      *         and should be created using the default <strong>Struts </strong>
211      *         framework.
212      * @throws SystemException
213      *             if the form cannot be created for any reason.
214      */
215     protected ActionForm createActionForm(final FormBeanConfig formBeanConfig,
216             final HttpServletRequest request,
217             final HttpServletResponse response, final ActionMapping mapping)
218             throws SystemException {
219         assert (implementation != null);
220         // if the form should be dynamic, we need the servlet to create it
221         if (formBeanConfig.getDynamic()) {
222             return RequestUtils.createActionForm(formBeanConfig, servlet);
223         }
224         ActionForm form = implementation
225                 .createActionForm(formBeanConfig, request, response, mapping);
226         if (form != null) {
227             form.setServlet(servlet);
228         }
229         return form;
230     }
231     /***
232      * @return Returns the implementation.
233      */
234     protected MaskRequestProcessorImplementation getImplementation() {
235         assert (implementation != null);
236         return implementation;
237     }
238     /***
239      * Refer to {@link RequestProcessor#init}.
240      *
241      * @param servletParam
242      * Refer to {@link RequestProcessor#init}.
243      * @param moduleConfigParam
244      * Refer to {@link RequestProcessor#init}.
245      * @throws javax.servlet.ServletException
246      * Refer to {@link RequestProcessor#init}.
247      */
248     public void init(ActionServlet servletParam, ModuleConfig moduleConfigParam)
249             throws ServletException {
250         super.init(servletParam, moduleConfigParam);
251         assert (implementation != null);
252         implementation.init(servletParam, moduleConfigParam);
253     }
254     /***
255      * <p>
256      * Overridden to create actions, since our actions have custom constructor
257      * parameters. <b>Don't try to override this method: </b> override {@link
258      * #createAction createAction} instead.
259      * </p>
260      *
261      * @param request
262      *            request for which we are creating an action.
263      * @param response
264      *            response we are sending.
265      * @param mapping
266      *            <strong>Struts </strong> mapping.
267      * @return valid action for the path.
268      * @throws IOException
269      * Refer to
270      * {@link org.apache.struts.action.RequestProcessor#processActionCreate}.
271      * @see org.apache.struts.action.RequestProcessor#processActionCreate
272      */
273     protected Action processActionCreate(
274             final HttpServletRequest request,
275             final HttpServletResponse response, final ActionMapping mapping)
276             throws IOException {
277         // see if there is already an instance of this class to use
278         String className = mapping.getType();
279         Action action = (Action) actions.get(className);
280         if (action != null) {
281             return action;
282         }
283         action = createAction(className, request, response, mapping);
284         if (action != null) {
285             return action;
286         }
287         return super.processActionCreate(request, response, mapping);
288     }
289     /***
290      * <p>
291      * Overridden to create forms, since our forms have custom constructor
292      * parameters. <b>Don't try to override this method: </b> override {@link
293      * #createActionForm createActionForm} instead.
294      * </p>
295      *
296      * @param request
297      *            servlet request we are processing.
298      * @param response
299      *            servlet response we are creating.
300      * @param mapping
301      *            current <strong>Struts </strong> action mapping we are
302      *            processing.
303      * @return valid action form.
304      * @see org.apache.struts.action.RequestProcessor#processActionForm
305      */
306     protected final ActionForm processActionForm(
307             final HttpServletRequest request,
308             final HttpServletResponse response, final ActionMapping mapping) {
309         HttpSession session = request.getSession();
310         String name = mapping.getName();
311         FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
312         if (config == null) {
313             return null;
314         }
315         ActionForm form;
316         String scope = mapping.getScope();
317         if ("request".equals(scope)) {
318             form = (ActionForm) request.getAttribute(mapping.getAttribute());
319         } else {
320             form = (ActionForm) session.getAttribute(mapping.getAttribute());
321         }
322         if (form == null) {
323             try {
324                 form = createActionForm(config, request, response, mapping);
325             } catch (SystemException e) {
326                 e.printStackTrace();
327                 throw new RuntimeException(e);
328             }
329         }
330         if (form == null) {
331             form = super.processActionForm(request, response, mapping);
332         }
333         // if we got a form, set it back to the appropriate scope
334         if (form != null) {
335             if ("request".equals(scope)) {
336                 request.setAttribute(mapping.getAttribute(), form);
337             } else {
338                 session.setAttribute(mapping.getAttribute(), form);
339             }
340         }
341         return form;
342     }
343     /***
344      * <p>
345      * Overridden to populate forms, and convert the string values of value
346      * object properties into the correct form for their class.
347      * </p>
348      *
349      * @param request
350      *            servlet request we are processing.
351      * @param response
352      *            servlet response we are creating.
353      * @param form
354      *            form instance we are populating.
355      * @param mapping
356      *            <strong>Struts </strong> mapping we are using.
357      *
358      * @exception ServletException
359      *                if an exception is thrown while setting property values
360      * @see org.apache.struts.action.RequestProcessor#processPopulate
361      */
362     protected void processPopulate(final HttpServletRequest request,
363             final HttpServletResponse response, final ActionForm form,
364             final ActionMapping mapping) throws ServletException {
365         // can't populate if there's nothing there :-)
366         if (form == null) {
367             return;
368         }
369         assert (implementation != null);
370         implementation.processPopulate(request, response, form, mapping);
371         //super.processPopulate(request, response, form, mapping);
372         if (form != null) {
373             form.setServlet(servlet);
374         }
375     }
376     /***
377      * Refer to {@link #getimplementation}.
378      * @param implementationParam Refer to {@link #getimplementation}.
379      */
380     protected void setImplementation(
381             MaskRequestProcessorImplementation implementationParam) {
382         if (logger.isDebugEnabled()) {
383             logger.debug("Setting implementation. Before '" + implementation
384                     + "', after '" + implementationParam + "'");
385         }
386         implementation = implementationParam;
387     }
388 }
389