1 /* 2 * Copyright (c) 2002-2006 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.ModelDriven; 9 import com.opensymphony.xwork2.util.CompoundRoot; 10 import com.opensymphony.xwork2.util.ValueStack; 11 12 13 /** 14 * <!-- START SNIPPET: description --> 15 * 16 * Watches for {@link ModelDriven} actions and adds the action's model on to the value stack. 17 * 18 * <p/> <b>Note:</b> The ModelDrivenInterceptor must come before the both {@link StaticParametersInterceptor} and 19 * {@link ParametersInterceptor} if you want the parameters to be applied to the model. 20 * 21 * <p/> <b>Note:</b> The ModelDrivenInterceptor will only push the model into the stack when the 22 * model is not null, else it will be ignored. 23 * 24 * <!-- END SNIPPET: description --> 25 * 26 * <p/> <u>Interceptor parameters:</u> 27 * 28 * <!-- START SNIPPET: parameters --> 29 * 30 * <ul> 31 * 32 * <li>refreshModelBeforeResult - set to true if you want the model to be refreshed on the value stack after action 33 * execution and before result execution. The setting is useful if you want to change the model instance during the 34 * action execution phase, like when loading it from the data layer. This will result in getModel() being called at 35 * least twice.</li> 36 * 37 * </ul> 38 * 39 * <!-- END SNIPPET: parameters --> 40 * 41 * <p/> <u>Extending the interceptor:</u> 42 * 43 * <p/> 44 * 45 * <!-- START SNIPPET: extending --> 46 * 47 * There are no known extension points to this interceptor. 48 * 49 * <!-- END SNIPPET: extending --> 50 * 51 * <p/> <u>Example code:</u> 52 * 53 * <pre> 54 * <!-- START SNIPPET: example --> 55 * <action name="someAction" class="com.examples.SomeAction"> 56 * <interceptor-ref name="modelDriven"/> 57 * <interceptor-ref name="basicStack"/> 58 * <result name="success">good_result.ftl</result> 59 * </action> 60 * <!-- END SNIPPET: example --> 61 * </pre> 62 * 63 * @author tm_jee 64 * @version $Date: 2009-07-28 02:25:13 +0200 (Di, 28 Jul 2009) $ $Id: ModelDrivenInterceptor.java 2027 2009-07-28 00:25:13Z musachy $ 65 */ 66 public class ModelDrivenInterceptor extends AbstractInterceptor { 67 68 protected boolean refreshModelBeforeResult = false; 69 70 public void setRefreshModelBeforeResult(boolean val) { 71 this.refreshModelBeforeResult = val; 72 } 73 74 @Override 75 public String intercept(ActionInvocation invocation) throws Exception { 76 Object action = invocation.getAction(); 77 78 if (action instanceof ModelDriven) { 79 ModelDriven modelDriven = (ModelDriven) action; 80 ValueStack stack = invocation.getStack(); 81 Object model = modelDriven.getModel(); 82 if (model != null) { 83 stack.push(model); 84 } 85 if (refreshModelBeforeResult) { 86 invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model)); 87 } 88 } 89 return invocation.invoke(); 90 } 91 92 /** 93 * Refreshes the model instance on the value stack, if it has changed 94 */ 95 protected static class RefreshModelBeforeResult implements PreResultListener { 96 private Object originalModel = null; 97 protected ModelDriven action; 98 99 100 public RefreshModelBeforeResult(ModelDriven action, Object model) { 101 this.originalModel = model; 102 this.action = action; 103 } 104 105 public void beforeResult(ActionInvocation invocation, String resultCode) { 106 ValueStack stack = invocation.getStack(); 107 CompoundRoot root = stack.getRoot(); 108 109 boolean needsRefresh = true; 110 Object newModel = action.getModel(); 111 112 // Check to see if the new model instance is already on the stack 113 for (Object item : root) { 114 if (item.equals(newModel)) { 115 needsRefresh = false; 116 } 117 } 118 119 // Add the new model on the stack 120 if (needsRefresh) { 121 122 // Clear off the old model instance 123 if (originalModel != null) { 124 root.remove(originalModel); 125 } 126 if (newModel != null) { 127 stack.push(newModel); 128 } 129 } 130 } 131 } 132 }