1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 package com.ivata.mask.web.struts;
144 import java.lang.reflect.InvocationTargetException;
145
146 import javax.naming.OperationNotSupportedException;
147 import javax.servlet.http.HttpServletRequest;
148 import javax.servlet.http.HttpServletResponse;
149 import javax.servlet.http.HttpSession;
150 import org.apache.commons.beanutils.PropertyUtils;
151 import org.apache.log4j.Logger;
152 import org.apache.struts.action.Action;
153 import org.apache.struts.action.ActionErrors;
154 import org.apache.struts.action.ActionForm;
155 import org.apache.struts.action.ActionForward;
156 import org.apache.struts.action.ActionMapping;
157 import org.apache.struts.action.ActionMessages;
158 import org.apache.struts.taglib.html.Constants;
159 import com.ivata.mask.MaskFactory;
160 import com.ivata.mask.util.SystemException;
161 import com.ivata.mask.util.StringHandling;
162 /***
163 * <p>
164 * Every <code>Action</code> in the system derives from this class, making it
165 * possible to centralize logging instantiation, and check we have a valid
166 * intranet session.
167 * </p>
168 *
169 * @since ivata masks 0.4 (2002-11-10)
170 * @author Colin MacLeod
171 * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
172 * @version $Revision: 1.12 $
173 */
174 public abstract class MaskAction extends Action {
175 /***
176 * Request attribute flag which indicates we have performed the
177 * cancellation.
178 */
179 private static final String CANCEL_COMPLETE = "MASK_CANEL_COMPLETE";
180 /***
181 * <p>
182 * This log provides tracing and debugging information.
183 * </p>
184 */
185 private static Logger logger = Logger.getLogger(MaskAction.class);
186 /***
187 * <p>
188 * This mask authenticator will be used to confirm whether or not the user
189 * should be allowed to continue.
190 * </p>
191 */
192 private MaskAuthenticator authenticator;
193 /***
194 * <p>
195 * Set to <code>true</code> by <code>LoginAction</code> to indicate the
196 * user name should not be checked.
197 * </p>
198 */
199 private boolean login = false;
200 /***
201 * <p>
202 * This factory is needed to access the masks and groups of masks.
203 * </p>
204 */
205 private MaskFactory maskFactory;
206 /***
207 * <p>
208 * Construct a mask action, with the given authenticator.
209 * </p>
210 *
211 * @param maskFactoryParam
212 * This factory is needed to access the masks and groups of
213 * masks.
214 * @param authenticatorParam
215 * used to confirm whether or not the user should be allowed to
216 * continue, in the <code>execute</code> method.
217 */
218 public MaskAction(final MaskFactory maskFactoryParam,
219 final MaskAuthenticator authenticatorParam) {
220 this.maskFactory = maskFactoryParam;
221 this.authenticator = authenticatorParam;
222 }
223 /***
224 * <p>
225 * Called when the clear button is pressed, or after an ok or delete button,
226 * where the session should be restored to its default state.
227 * </p>
228 *
229 * @param mapping
230 * The ActionMapping used to select this instance.
231 * @param errors
232 * valid errors object to append errors to. If there are any
233 * errors, the action will return to the input.
234 * @param form
235 * optional ActionForm bean for this request (if any)
236 * @param request
237 * non-HTTP request we are processing
238 * @param response
239 * The non-HTTP response we are creating
240 * @param session
241 * returned from the <code>request</code> parameter.
242 * @throws SystemException
243 * if there is any problem which prevents processing. It will
244 * result in the webapp being forwarded to the standard error
245 * page.
246 */
247 public void clear(final ActionMapping mapping, final ActionErrors errors,
248 final ActionForm form, final HttpServletRequest request,
249 final HttpServletResponse response, final HttpSession session)
250 throws SystemException {
251 if (form instanceof MaskForm) {
252 MaskForm maskForm = (MaskForm) form;
253 try {
254 maskForm.clear();
255 } catch (OperationNotSupportedException e) {
256 throw new SystemException(e);
257 }
258 }
259 }
260 /***
261 * <p>
262 * Called from the other <code>execute</code> method, this can be
263 * overridden by each subclass to provide the <i>ivata </i>-specific
264 * processing required.
265 * </p>
266 *
267 * @param mapping
268 * The ActionMapping used to select this instance.
269 * @param errors
270 * valid errors object to append errors to. If there are any
271 * errors, the action will return to the input.
272 * @param form
273 * optional ActionForm bean for this request (if any)
274 * @param request
275 * non-HTTP request we are processing
276 * @param response
277 * The non-HTTP response we are creating
278 * @param session
279 * returned from the <code>request</code> parameter.
280 * @throws SystemException
281 * if there is any problem which prevents processing. It will
282 * result in the webapp being forwarded to the standard error
283 * page.
284 * @return this method returns the string used to identify the correct
285 * <strong>Struts </strong> <code>ActionForward</code> which
286 * should follow this page, or <code>null</code> if it should
287 * return to the input.
288 */
289 public String execute(final ActionMapping mapping,
290 final ActionErrors errors, final ActionForm form,
291 final HttpServletRequest request,
292 final HttpServletResponse response, final HttpSession session)
293 throws SystemException {
294
295 return null;
296 }
297 /***
298 * <p>
299 * Generic method called by the <strong>Struts </strong> interface.
300 * </p>
301 *
302 * <p>
303 * Process the specified HTTP request, and create the corresponding HTTP
304 * response. Return an {@link ActionForward}instance describing where and
305 * how control should be forwarded, or <code>null</code> if the response
306 * has already been completed.
307 * </p>
308 *
309 * @param mapping
310 * The ActionMapping used to select this instance
311 * @param form
312 * The optional ActionForm bean for this request (if any)
313 * @param request
314 * The non-HTTP request we are processing
315 * @param response
316 * The non-HTTP response we are creating
317 * @exception Exception
318 * if the application business logic throws an exception
319 * @return this method returns a <code>"success"</code>
320 * <code>ActionForward</code>
321 * if the compose session is cancelled or successfully sent,
322 * otherwise a <code>"failure"</code>
323 * <code>ActionForward</code>.
324 */
325 public ActionForward execute(final ActionMapping mapping,
326 final ActionForm form, final HttpServletRequest request,
327 final HttpServletResponse response) throws Exception {
328
329 HttpSession session = request.getSession();
330
331
332 String authenticateForward = authenticator.authenticate(session, login);
333 if (authenticateForward != null) {
334 logger.info("Authenticator for class " + getClass().getName()
335 + " -> forwarding to '" + authenticateForward + "'.");
336 return mapping.findForward(authenticateForward);
337 }
338 try {
339 String forward = null;
340 ActionErrors errors = new ActionErrors();
341
342
343 String apply = getFromRequestOrForm("apply", request, form);
344 String clear = getFromRequestOrForm("clear", request, form);
345 String deleteConfirm = getFromRequestOrForm("deleteConfirm",
346 request, form);
347 String deleteWarn = getFromRequestOrForm("deleteWarn", request,
348 form);
349 String ok = getFromRequestOrForm("ok", request, form);
350 String defaultForwardApply = getFromRequestOrForm(
351 "defaultForwardApply",
352 request, form, "apply");
353 String defaultForwardDelete =
354 getFromRequestOrForm("defaultForwardDelete",
355 request, form, "delete");
356 String defaultForwardOk = getFromRequestOrForm("defaultForwardOk",
357 request, form, "ok");
358
359
360 if (isCancelled(request)) {
361 if (logger.isInfoEnabled()) {
362 logger.info("MaskAction [" + this.getClass().getName()
363 + "] amendment was cancelled.");
364 }
365 clear(mapping, errors, form, request, response, session);
366 request.setAttribute(CANCEL_COMPLETE, "true");
367 return mapping.findForward("cancel");
368 }
369
370 if (!StringHandling.isNullOrEmpty(deleteWarn)) {
371 try {
372 PropertyUtils.setProperty(form, "deleteWarn", "");
373 } catch (Exception e) {
374 if (logger.isDebugEnabled()) {
375 logger.debug("Exception re-setting deleteWarn.", e);
376 }
377 }
378 return mapping.getInputForward();
379 }
380
381 boolean isOk;
382 if (!StringHandling.isNullOrEmpty(clear)) {
383 clear(mapping, errors, form, request, response, session);
384 if (form instanceof MaskForm) {
385 DialogForm dialogForm = (DialogForm) form;
386 dialogForm.clear();
387 }
388 forward = execute(mapping, errors, form, request, response,
389 session);
390
391 } else if (!StringHandling.isNullOrEmpty(deleteConfirm)) {
392 forward = onDelete(mapping, errors, form, request, response,
393 session, defaultForwardDelete);
394 if (forward == null) {
395
396 PropertyUtils.setProperty(form, "delete", "");
397 } else {
398 clear(mapping, errors, form, request, response, session);
399 }
400
401 } else if ((isOk = !StringHandling.isNullOrEmpty(ok))
402 || !StringHandling.isNullOrEmpty(apply)) {
403 String defaultForward;
404 if (isOk) {
405 defaultForward = defaultForwardOk;
406 } else {
407 defaultForward = defaultForwardApply;
408 }
409 forward = onConfirm(mapping, errors, form, request, response,
410 session, defaultForward);
411 if (forward == null) {
412
413 PropertyUtils.setProperty(form, "ok", "");
414 PropertyUtils.setProperty(form, "apply", "");
415 } else {
416
417 if (isOk) {
418 clear(mapping, errors, form, request, response, session);
419 }
420
421
422 }
423 } else {
424 forward = execute(mapping, errors, form, request, response,
425 session);
426 }
427
428 if (errors.size() != 0) {
429 saveErrors(request, (ActionMessages) errors);
430 saveToken(request);
431 }
432
433 if (forward == null) {
434 return mapping.getInputForward();
435 }
436
437 ActionForward actionForward = mapping.findForward(forward);
438 if (actionForward == null) {
439 return mapping.getInputForward();
440 }
441 return actionForward;
442 } catch (Exception e) {
443
444 request.setAttribute("exception", e);
445 return mapping.findForward("error");
446 }
447 }
448 /***
449 * <p>
450 * This mask authenticator will be used to confirm whether or not the user
451 * should be allowed to continue.
452 * </p>
453 *
454 * @return Returns the authenticator.
455 */
456 protected MaskAuthenticator getAuthenticator() {
457 return authenticator;
458 }
459 /***
460 * <p>
461 * Helper method to see if the parameter with the given name is set in the
462 * request and, if not, if it is set in the form provided.
463 * </p>
464 *
465 * @param name
466 * the name of the parameter to look for.
467 * @param request
468 * servlet request to look for the parameter in.
469 * @param form
470 * the form to search for the parameter, if it is not found in
471 * the request.
472 * @return value from the request parameter with the name given. If that is
473 * null, then the value of the form attribute is returned, or
474 * <code>null</code> if there is no parameter or form attribute
475 * with the given name.
476 * @throws SystemException
477 * if there is an <code>InvocationTargetException</code> or an
478 * <code>IllegalAccessException</code> accessing the
479 * parameter.
480 */
481 protected final String getFromRequestOrForm(final String name,
482 final HttpServletRequest request, final ActionForm form)
483 throws SystemException {
484 return getFromRequestOrForm(name, request, form, null);
485 }
486 /***
487 * <p>
488 * Helper method to see if the parameter with the given name is set in the
489 * request and, if not, if it is set in the form provided.
490 * </p>
491 *
492 * @param name
493 * the name of the parameter to look for.
494 * @param request
495 * servlet request to look for the parameter in.
496 * @param form
497 * the form to search for the parameter, if it is not found in
498 * the request.
499 * @return value from the request parameter with the name given. If that is
500 * null, then the value of the form attribute is returned, or
501 * <code>defaultValue</code> if there is no parameter or form
502 * attribute with the given name.
503 * @throws SystemException
504 * if there is an <code>InvocationTargetException</code> or an
505 * <code>IllegalAccessException</code> accessing the
506 * parameter.
507 */
508 protected final String getFromRequestOrForm(final String name,
509 final HttpServletRequest request, final ActionForm form,
510 String defaultValue)
511 throws SystemException {
512 String value = request.getParameter(name);
513
514 if (value != null) {
515 return value;
516 }
517
518 if (form == null) {
519 return defaultValue;
520 }
521
522 try {
523 value = (String) PropertyUtils.getSimpleProperty(form, name);
524 } catch (NoSuchMethodException e) {
525
526
527 value = defaultValue;
528 } catch (InvocationTargetException e) {
529 throw new SystemException(e);
530 } catch (IllegalAccessException e) {
531 throw new SystemException(e);
532 }
533 return value;
534 }
535 /***
536 * <p>
537 * This method ascertains the correct input mask to use. First it looks for
538 * an override in the request, then it looks for a parameter in the current
539 * form before finally using the default.
540 * </p>
541 *
542 * @param request
543 * servlet request we are processing. A request parameter will be
544 * first checked here.
545 * @param form
546 * the form currently being processed. If there is no request
547 * parameter, the property "inputMask" is read from the
548 * form.
549 * @return string representing the action to perform for the current input
550 * mask.
551 * @throws SystemException
552 * if the input mask cannot be retrieved.
553 */
554 protected final String getInputMask(final HttpServletRequest request,
555 final Object form) throws SystemException {
556 String inputMask = request.getParameter("inputMask");
557 if ((inputMask == null) && (form != null)) {
558 try {
559 inputMask = (String) PropertyUtils.getProperty(form,
560 "inputMask");
561 } catch (IllegalAccessException e) {
562 e.printStackTrace();
563 throw new SystemException(e);
564 } catch (InvocationTargetException e) {
565 e.printStackTrace();
566 throw new SystemException(e);
567 } catch (NoSuchMethodException e) {
568
569 if (logger.isDebugEnabled()) {
570 logger.debug(
571 "NoSuchMethodException found looking for property '"
572 + "inputMask'", e);
573 }
574 }
575 }
576 if (inputMask == null) {
577 inputMask = maskFactory.getDefaultInputMask();
578 }
579 return inputMask;
580 }
581 /***
582 * <p>
583 * This method ascertains the correct list mask to use. First it looks for
584 * an override in the request, then it looks for a parameter in the current
585 * form before finally using the default.
586 * </p>
587 *
588 * @param request
589 * servlet request we are processing. A request parameter will be
590 * first checked here.
591 * @param form
592 * the form currently being processed. If there is no request
593 * parameter, the property "listMask" is read from the
594 * form.
595 * @return string representing the action to perform for the current list
596 * mask.
597 * @throws SystemException
598 * if the list mask cannot be retrieved.
599 */
600 protected final String getListMask(final HttpServletRequest request,
601 final Object form) throws SystemException {
602 String listMask = request.getParameter("listMask");
603 if ((listMask == null) && (form != null)) {
604 try {
605 listMask = (String) PropertyUtils.getProperty(form, "listMask");
606 } catch (IllegalAccessException e) {
607 e.printStackTrace();
608 throw new SystemException(e);
609 } catch (InvocationTargetException e) {
610 e.printStackTrace();
611 throw new SystemException(e);
612 } catch (NoSuchMethodException e) {
613
614 logger.debug("NoSuchMethodException found looking for property '"
615 + "listMask' in form '"
616 + form.toString()
617 + "'; (this is normally ok)", e);
618 }
619 }
620 if (listMask == null) {
621 listMask = maskFactory.getDefaultListMask();
622 }
623 return listMask;
624 }
625 /***
626 * <p>
627 * This factory is needed to access the masks and groups of masks.
628 * </p>
629 *
630 * @return Returns the maskFactory, used to access masks and groups of
631 * masks.
632 */
633 protected MaskFactory getMaskFactory() {
634 return maskFactory;
635 }
636 /***
637 * Not sure why I needed to override this!
638 *
639 * Refer to {@link org.apache.struts.action.Action#isCancelled}.
640 *
641 * @param request
642 * Refer to {@link org.apache.struts.action.Action#isCancelled}.
643 * @return Refer to {@link org.apache.struts.action.Action#isCancelled}.
644 * @see org.apache.struts.action.Action#isCancelled
645 */
646 protected final boolean isCancelled(final HttpServletRequest request) {
647 return (!"true".equals(request.getAttribute(CANCEL_COMPLETE)))
648 &&
649 ((request.getParameter("cancel") != null)
650 || (request.getParameter(Constants.CANCEL_PROPERTY)
651 != null)
652 || (request
653 .getParameter(Constants.CANCEL_PROPERTY_X)
654 != null));
655 }
656 /***
657 * <p>
658 * This method is called if the ok or apply buttons are pressed.
659 * </p>
660 *
661 * @param mapping
662 * The ActionMapping used to select this instance.
663 * @param errors
664 * valid errors object to append errors to. If there are any
665 * errors, the action will return to the input.
666 * @param form
667 * optional ActionForm bean for this request (if any)
668 * @param request
669 * non-HTTP request we are processing
670 * @param response
671 * The non-HTTP response we are creating
672 * @param session
673 * returned from the <code>request</code> parameter.
674 * @param defaultForward "ok" if the <code>Ok</code> button
675 * was pressed, otherwise "apply" if the <code>Apply</code> button
676 * was pressed.
677 * @throws SystemException
678 * if there is any problem which prevents processing. It will
679 * result in the webapp being forwarded to the standard error
680 * page.
681 * @return this method returns the string used to identify the correct
682 * <strong>Struts </strong> <code>ActionForward</code> which
683 * should follow this page, or <code>null</code> if it should
684 * return to the input.
685 */
686 public String onConfirm(final ActionMapping mapping,
687 final ActionErrors errors, final ActionForm form,
688 final HttpServletRequest request,
689 final HttpServletResponse response, final HttpSession session,
690 final String defaultForward) throws SystemException {
691
692 execute(mapping, errors, form, request, response, session);
693 return defaultForward;
694 }
695 /***
696 * <p>
697 * This method is called if the delete (confirm, not warn) button is
698 * pressed.
699 * </p>
700 * @param mapping
701 * The ActionMapping used to select this instance.
702 * @param errors
703 * valid errors object to append errors to. If there are any
704 * errors, the action will return to the input.
705 * @param form
706 * optional ActionForm bean for this request (if any)
707 * @param request
708 * non-HTTP request we are processing
709 * @param response
710 * The non-HTTP response we are creating
711 * @param session
712 * returned from the <code>request</code> parameter.
713 * @param defaultForward usually "delete". This is the forward
714 * it is suggested you use, if everything is ok.
715 * @exception SystemException
716 * if there is any problem which prevents processing. It will
717 * result in the webapp being forwarded to the standard error
718 * page.
719 * @return this method returns the string used to identify the correct
720 * <strong>Struts </strong> <code>ActionForward</code> which
721 * should follow this page, or <code>null</code> if it should
722 * return to the input.
723 */
724 public String onDelete(final ActionMapping mapping,
725 final ActionErrors errors, final ActionForm form,
726 final HttpServletRequest request,
727 final HttpServletResponse response,
728 final HttpSession session,
729 final String defaultForward)
730 throws SystemException {
731
732 execute(mapping, errors, form, request, response, session);
733 return defaultForward;
734 }
735 /***
736 * <p>
737 * Set to <code>true</code> by <code>LoginAction</code> to indicate the
738 * user name should not be checked.
739 * </p>
740 *
741 * @param loginParam
742 * the new value of login.
743 */
744 public final void setLogin(final boolean loginParam) {
745 this.login = loginParam;
746 }
747 }
748