001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: MaskTilesRequestProcessor.java,v $
031: * Revision 1.11 2005/10/14 14:09:17 colinmacleod
032: * Added saveForm and getSavedForm methods to the implementation class.
033: *
034: * Revision 1.10 2005/10/11 18:54:06 colinmacleod
035: * Fixed some checkstyle and javadoc issues.
036: *
037: * Revision 1.9 2005/10/03 10:17:25 colinmacleod
038: * Fixed some style and javadoc issues.
039: *
040: * Revision 1.8 2005/10/02 10:52:31 colinmacleod
041: * Improved logging.
042: * Added client session.
043: *
044: * Revision 1.7 2005/04/27 17:23:27 colinmacleod
045: * Fixed bugs resulting from ivata masks changes
046: * for ivata groupware v0.11.
047: *
048: * Revision 1.6 2005/04/11 12:21:15 colinmacleod
049: * Changed MaskRequestProcessorImpl to
050: * MaskRequestProcessorImplementation.
051: * Improved tiles support.
052: *
053: * Revision 1.5 2005/04/09 18:04:19 colinmacleod
054: * Changed copyright text to GPL v2 explicitly.
055: *
056: * Revision 1.4 2005/01/19 13:14:02 colinmacleod
057: * Renamed CausedByException to SystemException.
058: *
059: * Revision 1.3 2005/01/07 08:08:25 colinmacleod
060: * Moved up a version number.
061: * Changed copyright notices to 2005.
062: * Updated the documentation:
063: * - started working on multiproject:site docu.
064: * - changed the logo.
065: * Added checkstyle and fixed LOADS of style issues.
066: * Added separate thirdparty subproject.
067: * Added struts (in web), util and webgui (in webtheme) from ivata op.
068: *
069: * Revision 1.2 2004/12/29 15:34:07 colinmacleod
070: * Improved checking for non-ivata masks forms.
071: *
072: * Revision 1.1 2004/12/23 21:28:32 colinmacleod
073: * Modifications to add ivata op compatibility.
074: *
075: * Revision 1.4 2004/11/12 15:10:42 colinmacleod
076: * Moved persistence classes from ivata op as a replacement for
077: ValueObjectLocator.
078: *
079: * Revision 1.3 2004/11/11 13:49:47 colinmacleod
080: * Added log4j logging.
081: *
082: * Revision 1.2 2004/05/18 22:22:15 colinmacleod
083: * Added check not to populate if cancel was pressed.
084: *
085: * Revision 1.1.1.1 2004/05/16 20:40:33 colinmacleod
086: * Ready for 0.1 release
087: * -----------------------------------------------------------------------------
088: */
089: package com.ivata.mask.web.struts;
090:
091: import java.io.IOException;
092:
093: import javax.servlet.ServletException;
094: import javax.servlet.http.HttpServletRequest;
095: import javax.servlet.http.HttpServletResponse;
096:
097: import org.apache.log4j.Logger;
098: import org.apache.struts.action.Action;
099: import org.apache.struts.action.ActionForm;
100: import org.apache.struts.action.ActionMapping;
101: import org.apache.struts.action.ActionServlet;
102: import org.apache.struts.config.FormBeanConfig;
103: import org.apache.struts.config.ModuleConfig;
104: import org.apache.struts.tiles.TilesRequestProcessor;
105: import org.apache.struts.util.RequestUtils;
106: import org.sourceforge.clientsession.MarshallingException;
107:
108: import com.ivata.mask.MaskFactory;
109: import com.ivata.mask.persistence.PersistenceManager;
110: import com.ivata.mask.util.SystemException;
111:
112: /**
113: * <p>
114: * Extend from this class if you want to use <strong>Struts Tiles </strong>.
115: * </p>
116: *
117: * @since ivata masks 0.3 (2004-05-11)
118: * @author Colin MacLeod
119: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
120: * @version $Revision: 1.11 $
121: */
122: public class MaskTilesRequestProcessor extends TilesRequestProcessor {
123: /**
124: * Logger for this class.
125: */
126: private static final Logger logger = Logger
127: .getLogger(MaskTilesRequestProcessor.class);
128:
129: /**
130: * <p>
131: * This does all the hard work. :-)
132: * </p>
133: */
134: private MaskRequestProcessorImplementation implementation;
135:
136: /**
137: * <p>
138: * Initializes the mask factory, the value object locator and the the
139: * standard field value convertors.
140: * </p>
141: *
142: * @param maskFactory Refer to
143: * {@link MaskRequestProcessorImplementation#MaskRequestProcessorImpl}.
144: * @param persistenceManager Refer to
145: * {@link MaskRequestProcessorImplementation#MaskRequestProcessorImpl}.
146: */
147: public MaskTilesRequestProcessor(final MaskFactory maskFactory,
148: final PersistenceManager persistenceManager) {
149: }
150:
151: /**
152: * <p>
153: * Override this method to define how to create actions in your environment.
154: * This lets you use ivata masks with a standard framework.
155: * </p>
156: *
157: * <p>
158: * The default implementation looks for the action classes it knows about
159: * and initializes them directly. This is a simple starting point; in real
160: * life it is better to use a standard framework such as <a
161: * href="http://picocontainer.org">picocontainer </a>.
162: * </p>
163: *
164: *
165: * @param className {@inheritDoc}
166: * @param request {@inheritDoc}
167: * @param response {@inheritDoc}
168: * @param mapping {@inheritDoc}
169: * @return valid action for the path, or <code>null</code> if the action
170: * can and should be created using the default <strong>Struts</strong>
171: * framework.
172: * @throws IOException if the action cannot be created.
173: */
174: protected Action createAction(final String className,
175: final HttpServletRequest request,
176: final HttpServletResponse response,
177: final ActionMapping mapping) throws IOException {
178: if (logger.isDebugEnabled()) {
179: logger.debug("createAction(String className = " + className
180: + ", HttpServletRequest request = " + request
181: + ", HttpServletResponse response = " + response
182: + ", ActionMapping mapping = " + mapping
183: + ") - start");
184: }
185:
186: assert (implementation != null);
187: try {
188: Action instance = implementation.createAction(className,
189: request, response, mapping, servlet, actions);
190: if (instance != null) {
191: instance.setServlet(servlet);
192: }
193:
194: if (logger.isDebugEnabled()) {
195: logger.debug("createAction() - end - return value = "
196: + instance);
197: }
198: return instance;
199: } catch (SystemException e) {
200: logger
201: .error("createAction - error creating the action.",
202: e);
203: response.sendError(
204: HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
205: getInternal().getMessage("actionCreate",
206: mapping.getPath()));
207: if (logger.isDebugEnabled()) {
208: logger.debug("createAction() - end - return value = "
209: + null);
210: }
211: return null;
212: }
213: }
214:
215: /**
216: * <p>
217: * Override this method to define how to create action forms in your
218: * environment. This lets you use ivata masks with a standard framework.
219: * </p>
220: *
221: * <p>
222: * The default implementation looks for the form classes it knows about and
223: * initializes them directly. This is a simple starting point; in real life
224: * it is better to use a standard framework such as <a
225: * href="http://picocontainer.org">picocontainer </a>.
226: * </p>
227: *
228: * @param formBeanConfig Refer to
229: * {@link MaskRequestProcessorImplementation#createActionForm}.
230: * @param request Refer to
231: * {@link MaskRequestProcessorImplementation#createActionForm}.
232: * @param response Refer to
233: * {@link MaskRequestProcessorImplementation#createActionForm}.
234: * @param mapping Refer to
235: * {@link MaskRequestProcessorImplementation#createActionForm}.
236: * @return Refer to
237: * {@link MaskRequestProcessorImplementation#createActionForm}.
238: * @throws SystemException Refer to
239: * {@link MaskRequestProcessorImplementation#createActionForm}.
240: */
241: protected ActionForm createActionForm(
242: final FormBeanConfig formBeanConfig,
243: final HttpServletRequest request,
244: final HttpServletResponse response,
245: final ActionMapping mapping) throws SystemException {
246: if (logger.isDebugEnabled()) {
247: logger
248: .debug("createActionForm(FormBeanConfig formBeanConfig = "
249: + formBeanConfig
250: + ", HttpServletRequest request = "
251: + request
252: + ", HttpServletResponse response = "
253: + response
254: + ", ActionMapping mapping = "
255: + mapping + ") - start");
256: }
257:
258: assert (implementation != null);
259: // if the form should be dynamic, we need the servlet to create it
260: if (formBeanConfig.getDynamic()) {
261: ActionForm returnActionForm = RequestUtils
262: .createActionForm(formBeanConfig, servlet);
263: if (logger.isDebugEnabled()) {
264: logger
265: .debug("createActionForm() - end - return value = "
266: + returnActionForm);
267: }
268: return returnActionForm;
269: }
270: ActionForm form = implementation.createActionForm(
271: formBeanConfig, request, response, mapping);
272: if (form != null) {
273: form.setServlet(servlet);
274: }
275:
276: if (logger.isDebugEnabled()) {
277: logger.debug("createActionForm() - end - return value = "
278: + form);
279: }
280: return form;
281: }
282:
283: /**
284: * <copyDoc>Refer to {@link MaskRequestProcessor#getImplementation()}.
285: * </copyDoc>
286: * @return
287: * <copyDoc>Refer to {@link MaskRequestProcessor#getImplementation()}.
288: * </copyDoc>
289: */
290: protected MaskRequestProcessorImplementation getImplementation() {
291: if (logger.isDebugEnabled()) {
292: logger.debug("getImplementation() - start");
293: }
294:
295: if (logger.isDebugEnabled()) {
296: logger.debug("getImplementation() - end - return value = "
297: + implementation);
298: }
299: return implementation;
300: }
301:
302: /**
303: * {@inheritDoc}
304: *
305: * @param servletParam {@inheritDoc}
306: * @param moduleConfigParam {@inheritDoc}
307: * @throws javax.servlet.ServletException {@inheritDoc}
308: */
309: public void init(final ActionServlet servletParam,
310: final ModuleConfig moduleConfigParam)
311: throws ServletException {
312: if (logger.isDebugEnabled()) {
313: logger.debug("init(ActionServlet servletParam = "
314: + servletParam
315: + ", ModuleConfig moduleConfigParam = "
316: + moduleConfigParam + ") - start");
317: }
318:
319: super .init(servletParam, moduleConfigParam);
320: assert (implementation != null);
321: implementation.init(servletParam, moduleConfigParam);
322:
323: if (logger.isDebugEnabled()) {
324: logger.debug("init() - end");
325: }
326: }
327:
328: /**
329: * <p>
330: * Overridden to create actions, since our actions have custom constructor
331: * parameters. <b>Don't try to override this method</b>: override
332: * {@link #createAction createAction} instead.
333: * </p>
334: *
335: * @param request
336: * request for which we are creating an action.
337: * @param response
338: * response we are sending.
339: * @param mapping
340: * <strong>Struts </strong> mapping.
341: * @return valid action for the path.
342: * @throws IOException {@inheritDoc}
343: */
344: protected Action processActionCreate(
345: final HttpServletRequest request,
346: final HttpServletResponse response,
347: final ActionMapping mapping) throws IOException {
348: if (logger.isDebugEnabled()) {
349: logger
350: .debug("processActionCreate(HttpServletRequest request = "
351: + request
352: + ", HttpServletResponse response = "
353: + response
354: + ", ActionMapping mapping = "
355: + mapping + ") - start");
356: }
357:
358: // see if there is already an instance of this class to use
359: String className = mapping.getType();
360: Action action = (Action) actions.get(className);
361: if (action != null) {
362: if (logger.isDebugEnabled()) {
363: logger
364: .debug("processActionCreate() - end - return value = "
365: + action);
366: }
367: return action;
368: }
369: action = createAction(className, request, response, mapping);
370: if (action != null) {
371: if (logger.isDebugEnabled()) {
372: logger
373: .debug("processActionCreate() - end - return value = "
374: + action);
375: }
376: return action;
377: }
378: Action returnAction = super .processActionCreate(request,
379: response, mapping);
380: if (logger.isDebugEnabled()) {
381: logger
382: .debug("processActionCreate() - end - return value = "
383: + returnAction);
384: }
385: return returnAction;
386: }
387:
388: /**
389: * <p>
390: * Overridden to create forms, since our forms have custom constructor
391: * parameters. <b>Don't try to override this method</b>: override {@link
392: * #createActionForm createActionForm} instead.
393: * </p>
394: *
395: * @param request
396: * servlet request we are processing.
397: * @param response
398: * servlet response we are creating.
399: * @param mapping
400: * <strong>Struts</strong> mapping we are populating.
401: * @return {@inheritDoc}
402: */
403: protected final ActionForm processActionForm(
404: final HttpServletRequest request,
405: final HttpServletResponse response,
406: final ActionMapping mapping) {
407: if (logger.isDebugEnabled()) {
408: logger
409: .debug("processActionForm(HttpServletRequest request = "
410: + request
411: + ", HttpServletResponse response = "
412: + response
413: + ", ActionMapping mapping = "
414: + mapping + ") - start");
415: }
416:
417: try {
418: implementation.createClientSession(request, servlet
419: .getServletContext());
420: } catch (MarshallingException e) {
421: logger.error("processActionForm - error marshalling.", e);
422: throw new RuntimeException(e);
423: }
424: String name = mapping.getAttribute();
425: FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
426: if (config == null) {
427: if (logger.isDebugEnabled()) {
428: logger
429: .debug("processActionForm() - end - return value = "
430: + null);
431: }
432: return null;
433: }
434: ActionForm form = implementation.getSavedForm(request, mapping);
435: if (form != null) {
436: if (logger.isDebugEnabled()) {
437: logger
438: .debug("processActionForm() - end - return value = "
439: + form);
440: }
441: return form;
442: }
443: try {
444: form = createActionForm(config, request, response, mapping);
445: } catch (SystemException e) {
446: logger.error("processActionForm - error creating form.", e);
447: throw new RuntimeException(e);
448: }
449: if (form == null) {
450: form = super .processActionForm(request, response, mapping);
451: }
452: // if we got a form, set it back to the appropriate scope
453: if (form != null) {
454: implementation.saveForm(request, mapping, form);
455: }
456:
457: if (logger.isDebugEnabled()) {
458: logger.debug("processActionForm() - end - return value = "
459: + form);
460: }
461: return form;
462: }
463:
464: /**
465: * <p>
466: * Overridden to populate forms, and convert the string values of value
467: * object properties into the correct form for their class.
468: * </p>
469: *
470: * @param request {@inheritDoc}
471: * @param response {@inheritDoc}
472: * @param form {@inheritDoc}
473: * @param mapping {@inheritDoc}
474: * @exception ServletException {@inheritDoc}
475: */
476: protected void processPopulate(final HttpServletRequest request,
477: final HttpServletResponse response, final ActionForm form,
478: final ActionMapping mapping) throws ServletException {
479: if (logger.isDebugEnabled()) {
480: logger
481: .debug("processPopulate(HttpServletRequest request = "
482: + request
483: + ", HttpServletResponse response = "
484: + response
485: + ", ActionForm form = "
486: + form
487: + ", ActionMapping mapping = "
488: + mapping
489: + ") - start");
490: }
491:
492: // can't populate if there's nothing there :-)
493: if (form == null) {
494: if (logger.isDebugEnabled()) {
495: logger.debug("processPopulate() - end");
496: }
497: return;
498: }
499: assert (implementation != null);
500: implementation
501: .processPopulate(request, response, form, mapping);
502: if (form != null) {
503: form.setServlet(servlet);
504: }
505:
506: if (logger.isDebugEnabled()) {
507: logger.debug("processPopulate() - end");
508: }
509: }
510:
511: /**
512: * <copyDoc>Refer to {@link #getImplementation}.</copyDoc>
513: * @param implementationParam
514: * <copyDoc>Refer to {@link #getImplementation}.</copyDoc>
515: */
516: protected void setImplementation(
517: final MaskRequestProcessorImplementation implementationParam) {
518: if (logger.isDebugEnabled()) {
519: logger.debug("Setting implementation. Before '"
520: + implementation + "', after '"
521: + implementationParam + "'");
522: }
523: implementation = implementationParam;
524:
525: if (logger.isDebugEnabled()) {
526: logger.debug("setImplementation() - end");
527: }
528: }
529: }
|