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