Search in sources :

Example 6 with ModelDriven

use of com.opensymphony.xwork2.ModelDriven in project struts by apache.

the class BeanValidationInterceptor method addBeanValidationErrors.

@SuppressWarnings("nls")
protected void addBeanValidationErrors(Set<ConstraintViolation<Object>> constraintViolations, Object action) {
    if (constraintViolations != null) {
        ValidatorContext validatorContext = new DelegatingValidatorContext(action, textProviderFactory);
        for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
            String key = constraintViolation.getMessage();
            String message = key;
            try {
                message = validatorContext.getText(key);
                if (convertToUtf8 && StringUtils.isNotBlank(message)) {
                    message = new String(message.getBytes(convertFromEncoding), "UTF-8");
                }
            } catch (Exception e) {
                LOG.error("Error while trying to fetch message: {}", key, e);
            }
            if (isActionError(constraintViolation)) {
                LOG.debug("Adding action error [{}]", message);
                validatorContext.addActionError(message);
            } else {
                ValidationError validationError = buildBeanValidationError(constraintViolation, message);
                String fieldName = validationError.getFieldName();
                if (action instanceof ModelDriven && fieldName.startsWith(ValidatorConstants.MODELDRIVEN_PREFIX)) {
                    fieldName = fieldName.replace("model.", ValidatorConstants.EMPTY_SPACE);
                }
                LOG.debug("Adding field error [{}] with message [{}]", fieldName, validationError.getMessage());
                validatorContext.addFieldError(fieldName, validationError.getMessage());
            }
        }
    }
}
Also used : DelegatingValidatorContext(com.opensymphony.xwork2.validator.DelegatingValidatorContext) DelegatingValidatorContext(com.opensymphony.xwork2.validator.DelegatingValidatorContext) ValidatorContext(com.opensymphony.xwork2.validator.ValidatorContext) ModelDriven(com.opensymphony.xwork2.ModelDriven)

Example 7 with ModelDriven

use of com.opensymphony.xwork2.ModelDriven in project struts by apache.

the class ScopedModelDrivenInterceptor method intercept.

@Override
public String intercept(ActionInvocation invocation) throws Exception {
    Object action = invocation.getAction();
    if (action instanceof ScopedModelDriven) {
        ScopedModelDriven modelDriven = (ScopedModelDriven) action;
        if (modelDriven.getModel() == null) {
            ActionContext ctx = ActionContext.getContext();
            ActionConfig config = invocation.getProxy().getConfig();
            String cName = className;
            if (cName == null) {
                try {
                    Method method = action.getClass().getMethod(GET_MODEL, EMPTY_CLASS_ARRAY);
                    Class cls = method.getReturnType();
                    cName = cls.getName();
                } catch (NoSuchMethodException e) {
                    throw new StrutsException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config);
                }
            }
            String modelName = name;
            if (modelName == null) {
                modelName = cName;
            }
            Object model = resolveModel(objectFactory, ctx, cName, scope, modelName);
            modelDriven.setModel(model);
            modelDriven.setScopeKey(modelName);
        }
    }
    return invocation.invoke();
}
Also used : ActionConfig(com.opensymphony.xwork2.config.entities.ActionConfig) StrutsException(org.apache.struts2.StrutsException) Method(java.lang.reflect.Method) ActionContext(com.opensymphony.xwork2.ActionContext)

Example 8 with ModelDriven

use of com.opensymphony.xwork2.ModelDriven in project struts by apache.

the class StrutsLocalizedTextProvider method findText.

/**
 * <p>
 * Finds a localized text message for the given key, aTextName. Both the key and the message
 * itself is evaluated as required.  The following algorithm is used to find the requested
 * message:
 * </p>
 *
 * <ol>
 * <li>If {@link #searchDefaultBundlesFirst} is <code>true</code>, look for the message in the default resource bundles first.</li>
 * <li>Look for message in aClass' class hierarchy.
 * <ol>
 * <li>Look for the message in a resource bundle for aClass</li>
 * <li>If not found, look for the message in a resource bundle for any implemented interface</li>
 * <li>If not found, traverse up the Class' hierarchy and repeat from the first sub-step</li>
 * </ol></li>
 * <li>If not found and aClass is a {@link ModelDriven} Action, then look for message in
 * the model's class hierarchy (repeat sub-steps listed above).</li>
 * <li>If not found, look for message in child property.  This is determined by evaluating
 * the message key as an OGNL expression.  For example, if the key is
 * <i>user.address.state</i>, then it will attempt to see if "user" can be resolved into an
 * object.  If so, repeat the entire process from the beginning with the object's class as
 * aClass and "address.state" as the message key.</li>
 * <li>If not found, look for the message in aClass' package hierarchy.</li>
 * <li>If still not found, look for the message in the default resource bundles
 * (Note: the lookup is not repeated again if {@link #searchDefaultBundlesFirst} was <code>true</code>).</li>
 * <li>Return defaultMessage</li>
 * </ol>
 *
 * <p>
 * When looking for the message, if the key indexes a collection (e.g. user.phone[0]) and a
 * message for that specific key cannot be found, the general form will also be looked up
 * (i.e. user.phone[*]).
 * </p>
 *
 * <p>
 * If a message is found, it will also be interpolated.  Anything within <code>${...}</code>
 * will be treated as an OGNL expression and evaluated as such.
 * </p>
 *
 * <p>
 * If a message is <b>not</b> found a DEBUG level log warning will be logged.
 * </p>
 *
 * @param aClass         the class whose name to use as the start point for the search
 * @param aTextName      the key to find the text message for
 * @param locale         the locale the message should be for
 * @param defaultMessage the message to be returned if no text message can be found in any
 *                       resource bundle
 * @param args           arguments
 * @param valueStack     the value stack to use to evaluate expressions instead of the
 *                       one in the ActionContext ThreadLocal
 * @return the localized text, or null if none can be found and no defaultMessage is provided
 */
@Override
public String findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args, ValueStack valueStack) {
    String indexedTextName = null;
    if (aTextName == null) {
        LOG.warn("Trying to find text with null key!");
        aTextName = "";
    }
    // calculate indexedTextName (collection[*]) if applicable
    if (aTextName.contains("[")) {
        int i = -1;
        indexedTextName = aTextName;
        while ((i = indexedTextName.indexOf('[', i + 1)) != -1) {
            int j = indexedTextName.indexOf(']', i);
            String a = indexedTextName.substring(0, i);
            String b = indexedTextName.substring(j);
            indexedTextName = a + "[*" + b;
        }
    }
    // Allow for and track an early lookup for the message in the default resource bundles first, before searching the class hierarchy.
    // The early lookup is only performed when the text provider has been configured to do so, otherwise follow the standard processing order.
    boolean performedInitialDefaultBundlesMessageLookup = false;
    GetDefaultMessageReturnArg result = null;
    // If search default bundles first is set true, call alternative logic first.
    if (searchDefaultBundlesFirst) {
        result = getDefaultMessageWithAlternateKey(aTextName, indexedTextName, locale, valueStack, args, defaultMessage);
        performedInitialDefaultBundlesMessageLookup = true;
        if (!unableToFindTextForKey(result)) {
            // Found a message in the default resource bundles for aTextName or indexedTextName.
            return result.message;
        }
    }
    // search up class hierarchy
    String msg = findMessage(aClass, aTextName, indexedTextName, locale, args, null, valueStack);
    if (msg != null) {
        return msg;
    }
    if (ModelDriven.class.isAssignableFrom(aClass)) {
        ActionContext context = ActionContext.getContext();
        // search up model's class hierarchy
        ActionInvocation actionInvocation = context.getActionInvocation();
        // ActionInvocation may be null if we're being run from a Sitemesh filter, so we won't get model texts if this is null
        if (actionInvocation != null) {
            Object action = actionInvocation.getAction();
            if (action instanceof ModelDriven) {
                Object model = ((ModelDriven) action).getModel();
                if (model != null) {
                    msg = findMessage(model.getClass(), aTextName, indexedTextName, locale, args, null, valueStack);
                    if (msg != null) {
                        return msg;
                    }
                }
            }
        }
    }
    // nothing still? alright, search the package hierarchy now
    for (Class clazz = aClass; (clazz != null) && !clazz.equals(Object.class); clazz = clazz.getSuperclass()) {
        String basePackageName = clazz.getName();
        while (basePackageName.lastIndexOf('.') != -1) {
            basePackageName = basePackageName.substring(0, basePackageName.lastIndexOf('.'));
            String packageName = basePackageName + ".package";
            msg = getMessage(packageName, locale, aTextName, valueStack, args);
            if (msg != null) {
                return msg;
            }
            if (indexedTextName != null) {
                msg = getMessage(packageName, locale, indexedTextName, valueStack, args);
                if (msg != null) {
                    return msg;
                }
            }
        }
    }
    // see if it's a child property
    int idx = aTextName.indexOf('.');
    if (idx != -1) {
        String newKey = null;
        String prop = null;
        if (aTextName.startsWith(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX)) {
            idx = aTextName.indexOf('.', XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length());
            if (idx != -1) {
                prop = aTextName.substring(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length(), idx);
                newKey = XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX + aTextName.substring(idx + 1);
            }
        } else {
            prop = aTextName.substring(0, idx);
            newKey = aTextName.substring(idx + 1);
        }
        if (prop != null) {
            Object obj = valueStack.findValue(prop);
            try {
                Object actionObj = ReflectionProviderFactory.getInstance().getRealTarget(prop, valueStack.getContext(), valueStack.getRoot());
                if (actionObj != null) {
                    PropertyDescriptor propertyDescriptor = ReflectionProviderFactory.getInstance().getPropertyDescriptor(actionObj.getClass(), prop);
                    if (propertyDescriptor != null) {
                        Class clazz = propertyDescriptor.getPropertyType();
                        if (clazz != null) {
                            if (obj != null) {
                                valueStack.push(obj);
                            }
                            msg = findText(clazz, newKey, locale, null, args);
                            if (obj != null) {
                                valueStack.pop();
                            }
                            if (msg != null) {
                                return msg;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                LOG.debug("unable to find property {}", prop, e);
            }
        }
    }
    // so we check first to avoid repeating the same operation twice.
    if (!performedInitialDefaultBundlesMessageLookup) {
        result = getDefaultMessageWithAlternateKey(aTextName, indexedTextName, locale, valueStack, args, defaultMessage);
    }
    // could we find the text, if not log a warn
    if (unableToFindTextForKey(result) && LOG.isDebugEnabled()) {
        String warn = "Unable to find text for key '" + aTextName + "' ";
        if (indexedTextName != null) {
            warn += " or indexed key '" + indexedTextName + "' ";
        }
        warn += "in class '" + aClass.getName() + "' and locale '" + locale + "'";
        LOG.debug(warn);
    }
    return result != null ? result.message : null;
}
Also used : PropertyDescriptor(java.beans.PropertyDescriptor) ActionInvocation(com.opensymphony.xwork2.ActionInvocation) ModelDriven(com.opensymphony.xwork2.ModelDriven) ActionContext(com.opensymphony.xwork2.ActionContext)

Example 9 with ModelDriven

use of com.opensymphony.xwork2.ModelDriven in project struts by apache.

the class StrutsLocalizedTextProviderTest method testFindTextInPackage.

public void testFindTextInPackage() throws Exception {
    ModelDriven action = new ModelDrivenAction2();
    Mock mockActionInvocation = new Mock(ActionInvocation.class);
    mockActionInvocation.expectAndReturn("getAction", action);
    ActionContext.getContext().withActionInvocation((ActionInvocation) mockActionInvocation.proxy());
    String message = localizedTextProvider.findText(ModelDrivenAction2.class, "package.properties", Locale.getDefault());
    assertEquals("It works!", message);
}
Also used : ModelDrivenAction2(com.opensymphony.xwork2.test.ModelDrivenAction2) ModelDriven(com.opensymphony.xwork2.ModelDriven) Mock(com.mockobjects.dynamic.Mock)

Example 10 with ModelDriven

use of com.opensymphony.xwork2.ModelDriven in project struts by apache.

the class RestActionInvocation method selectTarget.

@SuppressWarnings("unchecked")
protected void selectTarget() {
    // Select target (content to return)
    Throwable e = (Throwable) stack.findValue("exception");
    if (e != null) {
        // Exception
        target = e;
        hasErrors = true;
    } else if (action instanceof ValidationAware && ((ValidationAware) action).hasErrors()) {
        // Error messages
        ValidationAware validationAwareAction = ((ValidationAware) action);
        Map errors = new HashMap();
        if (validationAwareAction.getActionErrors().size() > 0) {
            errors.put("actionErrors", validationAwareAction.getActionErrors());
        }
        if (validationAwareAction.getFieldErrors().size() > 0) {
            errors.put("fieldErrors", validationAwareAction.getFieldErrors());
        }
        target = errors;
        hasErrors = true;
    } else if (action instanceof ModelDriven) {
        // Model
        target = ((ModelDriven) action).getModel();
    } else {
        target = action;
    }
    if (shouldRestrictToGET()) {
        target = null;
    }
}
Also used : HashMap(java.util.HashMap) ValidationAware(com.opensymphony.xwork2.interceptor.ValidationAware) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ModelDriven (com.opensymphony.xwork2.ModelDriven)8 Mock (com.mockobjects.dynamic.Mock)2 ActionContext (com.opensymphony.xwork2.ActionContext)2 ModelDrivenAction2 (com.opensymphony.xwork2.test.ModelDrivenAction2)2 ValueStack (com.opensymphony.xwork2.util.ValueStack)2 ActionInvocation (com.opensymphony.xwork2.ActionInvocation)1 ActionConfig (com.opensymphony.xwork2.config.entities.ActionConfig)1 ValidationAware (com.opensymphony.xwork2.interceptor.ValidationAware)1 TestBean2 (com.opensymphony.xwork2.test.TestBean2)1 DelegatingValidatorContext (com.opensymphony.xwork2.validator.DelegatingValidatorContext)1 ValidatorContext (com.opensymphony.xwork2.validator.ValidatorContext)1 ExplicitTypePermission (com.thoughtworks.xstream.security.ExplicitTypePermission)1 PropertyDescriptor (java.beans.PropertyDescriptor)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 Method (java.lang.reflect.Method)1 Date (java.util.Date)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1