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.ActionContext; 8 import com.opensymphony.xwork2.ActionInvocation; 9 import com.opensymphony.xwork2.ValidationAware; 10 import com.opensymphony.xwork2.conversion.impl.XWorkConverter; 11 import com.opensymphony.xwork2.util.ValueStack; 12 13 import java.util.HashMap; 14 import java.util.Map; 15 16 17 /** 18 * <!-- START SNIPPET: description --> 19 * ConversionErrorInterceptor adds conversion errors from the ActionContext to the Action's field errors. 20 * 21 * <p/> 22 * This interceptor adds any error found in the {@link ActionContext}'s conversionErrors map as a field error (provided 23 * that the action implements {@link ValidationAware}). In addition, any field that contains a validation error has its 24 * original value saved such that any subsequent requests for that value return the original value rather than the value 25 * in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to 26 * display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to 27 * the user). 28 * 29 * 30 * <!-- END SNIPPET: description --> 31 * 32 * <p/> <u>Interceptor parameters:</u> 33 * 34 * <!-- START SNIPPET: parameters --> 35 * 36 * <ul> 37 * 38 * <li>None</li> 39 * 40 * </ul> 41 * 42 * <!-- END SNIPPET: parameters --> 43 * 44 * <p/> <u>Extending the interceptor:</u> 45 * 46 * <p/> 47 * 48 * <!-- START SNIPPET: extending --> 49 * 50 * Because this interceptor is not web-specific, it abstracts the logic for whether an error should be added. This 51 * allows for web-specific interceptors to use more complex logic in the {@link #shouldAddError} method for when a value 52 * has a conversion error but is null or empty or otherwise indicates that the value was never actually entered by the 53 * user. 54 * 55 * <!-- END SNIPPET: extending --> 56 * 57 * <p/> <u>Example code:</u> 58 * 59 * <pre> 60 * <!-- START SNIPPET: example --> 61 * <action name="someAction" class="com.examples.SomeAction"> 62 * <interceptor-ref name="params"/> 63 * <interceptor-ref name="conversionError"/> 64 * <result name="success">good_result.ftl</result> 65 * </action> 66 * <!-- END SNIPPET: example --> 67 * </pre> 68 * 69 * @author Jason Carreira 70 */ 71 public class ConversionErrorInterceptor extends AbstractInterceptor { 72 73 public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override"; 74 75 protected Object getOverrideExpr(ActionInvocation invocation, Object value) { 76 return "'" + value + "'"; 77 } 78 79 @Override 80 public String intercept(ActionInvocation invocation) throws Exception { 81 82 ActionContext invocationContext = invocation.getInvocationContext(); 83 Map<String, Object> conversionErrors = invocationContext.getConversionErrors(); 84 ValueStack stack = invocationContext.getValueStack(); 85 86 HashMap<Object, Object> fakie = null; 87 88 for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) { 89 String propertyName = entry.getKey(); 90 Object value = entry.getValue(); 91 92 if (shouldAddError(propertyName, value)) { 93 String message = XWorkConverter.getConversionErrorMessage(propertyName, stack); 94 95 Object action = invocation.getAction(); 96 if (action instanceof ValidationAware) { 97 ValidationAware va = (ValidationAware) action; 98 va.addFieldError(propertyName, message); 99 } 100 101 if (fakie == null) { 102 fakie = new HashMap<Object, Object>(); 103 } 104 105 fakie.put(propertyName, getOverrideExpr(invocation, value)); 106 } 107 } 108 109 if (fakie != null) { 110 // if there were some errors, put the original (fake) values in place right before the result 111 stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie); 112 invocation.addPreResultListener(new PreResultListener() { 113 public void beforeResult(ActionInvocation invocation, String resultCode) { 114 Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE); 115 116 if (fakie != null) { 117 invocation.getStack().setExprOverrides(fakie); 118 } 119 } 120 }); 121 } 122 return invocation.invoke(); 123 } 124 125 protected boolean shouldAddError(String propertyName, Object value) { 126 return true; 127 } 128 }