1 /* 2 * Copyright (c) 2002-2007 by OpenSymphony 3 * All rights reserved. 4 */ 5 package com.opensymphony.xwork2.interceptor; 6 7 import com.opensymphony.xwork2.ActionInvocation; 8 import com.opensymphony.xwork2.Preparable; 9 import com.opensymphony.xwork2.util.logging.Logger; 10 import com.opensymphony.xwork2.util.logging.LoggerFactory; 11 12 import java.lang.reflect.InvocationTargetException; 13 14 15 /** 16 * <!-- START SNIPPET: description --> 17 * 18 * This interceptor calls <code>prepare()</code> on actions which implement 19 * {@link Preparable}. This interceptor is very useful for any situation where 20 * you need to ensure some logic runs before the actual execute method runs. 21 * 22 * <p/> A typical use of this is to run some logic to load an object from the 23 * database so that when parameters are set they can be set on this object. For 24 * example, suppose you have a User object with two properties: <i>id</i> and 25 * <i>name</i>. Provided that the params interceptor is called twice (once 26 * before and once after this interceptor), you can load the User object using 27 * the id property, and then when the second params interceptor is called the 28 * parameter <i>user.name</i> will be set, as desired, on the actual object 29 * loaded from the database. See the example for more info. 30 * 31 * <p/> 32 * <b>Note:</b> Since XWork 2.0.2, this interceptor extends {@link MethodFilterInterceptor}, therefore being 33 * able to deal with excludeMethods / includeMethods parameters. See [Workflow Interceptor] 34 * (class {@link DefaultWorkflowInterceptor}) for documentation and examples on how to use this feature. 35 * 36 * <p/><b>Update</b>: Added logic to execute a prepare{MethodName} and conditionally 37 * the a general prepare() Method, depending on the 'alwaysInvokePrepare' parameter/property 38 * which is by default true. This allows us to run some logic based on the method 39 * name we specify in the {@link com.opensymphony.xwork2.ActionProxy}. For example, you can specify a 40 * prepareInput() method that will be run before the invocation of the input method. 41 * 42 * <!-- END SNIPPET: description --> 43 * 44 * <p/> <u>Interceptor parameters:</u> 45 * 46 * <!-- START SNIPPET: parameters --> 47 * 48 * <ul> 49 * 50 * <li>alwaysInvokePrepare - Default to true. If true, prepare will always be invoked, 51 * otherwise it will not.</li> 52 * 53 * </ul> 54 * 55 * <!-- END SNIPPET: parameters --> 56 * 57 * <p/> <u>Extending the interceptor:</u> 58 * 59 * <p/> 60 * 61 * <!-- START SNIPPET: extending --> 62 * 63 * There are no known extension points to this interceptor. 64 * 65 * <!-- END SNIPPET: extending --> 66 * 67 * <p/> <u>Example code:</u> 68 * 69 * <pre> 70 * <!-- START SNIPPET: example --> 71 * <!-- Calls the params interceptor twice, allowing you to 72 * pre-load data for the second time parameters are set --> 73 * <action name="someAction" class="com.examples.SomeAction"> 74 * <interceptor-ref name="params"/> 75 * <interceptor-ref name="prepare"/> 76 * <interceptor-ref name="basicStack"/> 77 * <result name="success">good_result.ftl</result> 78 * </action> 79 * <!-- END SNIPPET: example --> 80 * </pre> 81 * 82 * @author Jason Carreira 83 * @author Philip Luppens 84 * @author tm_jee 85 * @see com.opensymphony.xwork2.Preparable 86 */ 87 public class PrepareInterceptor extends MethodFilterInterceptor { 88 89 private static final long serialVersionUID = -5216969014510719786L; 90 91 private static final Logger LOG = LoggerFactory.getLogger(PrepareInterceptor.class); 92 93 private final static String PREPARE_PREFIX = "prepare"; 94 private final static String ALT_PREPARE_PREFIX = "prepareDo"; 95 96 private boolean alwaysInvokePrepare = true; 97 98 /** 99 * Sets if the <code>preapare</code> method should always be executed. 100 * <p/> 101 * Default is <tt>true</tt>. 102 * 103 * @param alwaysInvokePrepare if <code>prepare</code> should always be executed or not. 104 */ 105 public void setAlwaysInvokePrepare(String alwaysInvokePrepare) { 106 this.alwaysInvokePrepare = Boolean.parseBoolean(alwaysInvokePrepare); 107 } 108 109 @Override 110 public String doIntercept(ActionInvocation invocation) throws Exception { 111 Object action = invocation.getAction(); 112 113 if (action instanceof Preparable) { 114 try { 115 PrefixMethodInvocationUtil.invokePrefixMethod(invocation, 116 new String[]{PREPARE_PREFIX, ALT_PREPARE_PREFIX}); 117 } 118 catch (InvocationTargetException e) { 119 // just in case there's an exception while doing reflection, 120 // we still want prepare() to be able to get called. 121 LOG.warn("an exception occured while trying to execute prefixed method", e); 122 } 123 catch (IllegalAccessException e) { 124 // just in case there's an exception while doing reflection, 125 // we still want prepare() to be able to get called. 126 LOG.warn("an exception occured while trying to execute prefixed method", e); 127 } catch (Exception e) { 128 // just in case there's an exception while doing reflection, 129 // we still want prepare() to be able to get called. 130 LOG.warn("an exception occured while trying to execute prefixed method", e); 131 } 132 133 if (alwaysInvokePrepare) { 134 ((Preparable) action).prepare(); 135 } 136 } 137 138 return invocation.invoke(); 139 } 140 141 }