From 5c5683907c56ec75f1a0f9f78fe27f8a8f21401c Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 11 Oct 2024 10:49:13 +0200 Subject: [PATCH 1/4] WW-5468 Fixes @StrutsParameter for ModelDriven --- .../com/opensymphony/xwork2/ModelDriven.java | 3 + .../parameter/ParametersInterceptor.java | 61 +++++++++++++------ .../StrutsParameterAnnotationTest.java | 34 +++++++++-- .../struts2/result/StreamResultTest.java | 6 +- .../struts2/junit/StrutsRestTestCase.java | 3 +- 5 files changed, 78 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java b/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java index c07c6bbe7..59641a997 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java +++ b/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java @@ -18,6 +18,8 @@ */ package com.opensymphony.xwork2; +import org.apache.struts2.interceptor.parameter.StrutsParameter; + /** * ModelDriven Actions provide a model object to be pushed onto the ValueStack * in addition to the Action itself, allowing a FormBean type approach like Struts. @@ -31,6 +33,7 @@ public interface ModelDriven { * * @return the model */ + @StrutsParameter T getModel(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java index 353f3cb82..5d1010a0b 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java @@ -20,6 +20,7 @@ package org.apache.struts2.interceptor.parameter; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; import com.opensymphony.xwork2.security.AcceptedPatternsChecker; @@ -348,7 +349,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } long paramDepth = name.codePoints().mapToObj(c -> (char) c).filter(NESTING_CHARS::contains).count(); - if (requireAnnotationsTransitionMode && paramDepth == 0) { + if (!isModelDriven(action) && requireAnnotationsTransitionMode && paramDepth == 0) { return true; } @@ -365,29 +366,36 @@ public class ParametersInterceptor extends MethodFilterInterceptor { * save computation by checking this last. */ protected boolean hasValidAnnotatedMember(String rootProperty, Object action, long paramDepth) { + final String property = isModelDriven(action) ? "model" : rootProperty; + LOG.debug("Using [{}] as a root property of [{}]", property, action.getClass().getSimpleName()); + BeanInfo beanInfo = getBeanInfo(action); if (beanInfo == null) { - return hasValidAnnotatedField(action, rootProperty, paramDepth); + return hasValidAnnotatedField(action, property, paramDepth); } Optional propDescOpt = Arrays.stream(beanInfo.getPropertyDescriptors()) - .filter(desc -> desc.getName().equals(rootProperty)).findFirst(); + .filter(desc -> desc.getName().equals(property)).findFirst(); if (propDescOpt.isEmpty()) { - return hasValidAnnotatedField(action, rootProperty, paramDepth); + return hasValidAnnotatedField(action, property, paramDepth); } if (hasValidAnnotatedPropertyDescriptor(action, propDescOpt.get(), paramDepth)) { return true; } - return hasValidAnnotatedField(action, rootProperty, paramDepth); + return hasValidAnnotatedField(action, property, paramDepth); } protected boolean hasValidAnnotatedPropertyDescriptor(Object action, PropertyDescriptor propDesc, long paramDepth) { - Method relevantMethod = paramDepth == 0 ? propDesc.getWriteMethod() : propDesc.getReadMethod(); + Method relevantMethod = getRelevantMethod(action, propDesc, paramDepth); + if (relevantMethod == null) { + LOG.debug("No such property [{}] in action [{}]", propDesc.getName(), action.getClass().getSimpleName()); return false; } + + LOG.debug("Using [{}] as a property of [{}]", relevantMethod.getName(), action.getClass().getSimpleName()); if (getPermittedInjectionDepth(relevantMethod) < paramDepth) { String logMessage = format( "Parameter injection for method [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", @@ -400,6 +408,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } return false; } + if (isModelDriven(action)) { + allowlistClass(propDesc.getPropertyType()); + } if (paramDepth >= 1) { allowlistClass(relevantMethod.getReturnType()); } @@ -409,6 +420,16 @@ public class ParametersInterceptor extends MethodFilterInterceptor { return true; } + private Method getRelevantMethod(Object action, PropertyDescriptor propDesc, long paramDepth) { + Method useReadOrWriteMethod = isModelDriven(action) ? propDesc.getReadMethod() : propDesc.getWriteMethod(); + return paramDepth == 0 ? useReadOrWriteMethod : propDesc.getReadMethod(); + } + + private boolean isModelDriven(Object action) { + return action instanceof ModelDriven; + } + + protected void allowlistReturnTypeIfParameterized(Method method) { allowlistParameterizedTypeArg(method.getGenericReturnType()); } @@ -439,18 +460,22 @@ public class ParametersInterceptor extends MethodFilterInterceptor { protected boolean hasValidAnnotatedField(Object action, String fieldName, long paramDepth) { Field field; + LOG.debug("Checking if field [{}] of [{}] is annotated with [{}]", + fieldName, action.getClass().getSimpleName(), StrutsParameter.class.getSimpleName()); try { field = action.getClass().getDeclaredField(fieldName); } catch (NoSuchFieldException e) { + LOG.debug("Field [{}] not found", fieldName); return false; } if (!Modifier.isPublic(field.getModifiers())) { + LOG.debug("Field [{}] is not public", fieldName); return false; } if (getPermittedInjectionDepth(field) < paramDepth) { String logMessage = format( "Parameter injection for field [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", - fieldName, + field.getName(), action.getClass().getName()); if (devMode) { notifyDeveloperOfError(LOG, action, logMessage); @@ -591,9 +616,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (!matchLength) { if (devMode) { LOG.warn("Parameter [{}] is too long, allowed length is [{}]. Use Interceptor Parameter Overriding " + - "to override the limit, see more at\n" + - "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding", - name, paramNameMaxLength); + "to override the limit, see more at\n" + + "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding", + name, paramNameMaxLength); } else { LOG.warn("Parameter [{}] is too long, allowed length is [{}]", name, paramNameMaxLength); } @@ -621,8 +646,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (result.isExcluded()) { if (devMode) { LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" + - "https://struts.apache.org/security/#accepted--excluded-patterns", - paramName, result.getExcludedPattern()); + "https://struts.apache.org/security/#accepted--excluded-patterns", + paramName, result.getExcludedPattern()); } else { LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern()); } @@ -640,8 +665,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (excludedValuePattern.matcher(value).matches()) { if (devMode) { LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" + - "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", - value, excludedValuePatterns); + "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", + value, excludedValuePatterns); } else { LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedValuePattern); } @@ -663,8 +688,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } if (devMode) { LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" + - "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", - value, acceptedValuePatterns); + "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", + value, acceptedValuePatterns); } else { LOG.debug("Parameter value [{}] was not accepted!", value); } @@ -734,7 +759,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns); } else { LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this may impact safety of your application!", - acceptedValuePatterns, patterns); + acceptedValuePatterns, patterns); } acceptedValuePatterns = new HashSet<>(patterns.size()); try { @@ -759,7 +784,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { LOG.debug("Setting excluded value patterns to [{}]", patterns); } else { LOG.warn("Replacing excluded value patterns [{}] with [{}], be aware that this may impact safety of your application!", - excludedValuePatterns, patterns); + excludedValuePatterns, patterns); } excludedValuePatterns = new HashSet<>(patterns.size()); try { diff --git a/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java b/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java index 53fa14717..eb44fc6fe 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java @@ -18,6 +18,7 @@ */ package org.apache.struts2.interceptor.parameter; +import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.security.AcceptedPatternsChecker; import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker; import org.apache.commons.lang3.ClassUtils; @@ -80,7 +81,7 @@ public class StrutsParameterAnnotationTest { } } - private Set> getParentClasses(Class ...clazzes) { + private Set> getParentClasses(Class... clazzes) { Set> set = new HashSet<>(); for (Class clazz : clazzes) { set.add(clazz); @@ -258,8 +259,14 @@ public class StrutsParameterAnnotationTest { testParameter(new MethodAction(), "publicStrNotAnnotated", true); } + @Test + public void publicModelPojo() { + parametersInterceptor.setRequireAnnotationsTransitionMode(Boolean.TRUE.toString()); + testParameter(new ModelAction(), "name", true); + assertThat(threadAllowlist.getAllowlist()).containsExactlyInAnyOrderElementsOf(getParentClasses(Object.class, Pojo.class)); + } - class FieldAction { + static class FieldAction { @StrutsParameter private String privateStr; @@ -275,7 +282,7 @@ public class StrutsParameterAnnotationTest { public Pojo publicPojoDepthZero; @StrutsParameter(depth = 1) - public Pojo publicPojoDepthOne ; + public Pojo publicPojoDepthOne; @StrutsParameter(depth = 2) public Pojo publicPojoDepthTwo; @@ -290,7 +297,7 @@ public class StrutsParameterAnnotationTest { public Map publicPojoMapDepthTwo; } - class MethodAction { + static class MethodAction { @StrutsParameter private void setPrivateStr(String str) { @@ -343,6 +350,23 @@ public class StrutsParameterAnnotationTest { } } - class Pojo { + static class ModelAction implements ModelDriven { + + @StrutsParameter + public Pojo getModel() { + return new Pojo(); + } + } + + static class Pojo { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } } diff --git a/core/src/test/java/org/apache/struts2/result/StreamResultTest.java b/core/src/test/java/org/apache/struts2/result/StreamResultTest.java index 5661db5d3..a02781812 100644 --- a/core/src/test/java/org/apache/struts2/result/StreamResultTest.java +++ b/core/src/test/java/org/apache/struts2/result/StreamResultTest.java @@ -37,7 +37,6 @@ import static com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPattern /** * Unit test for {@link StreamResult}. - * */ public class StreamResultTest extends StrutsInternalTestCase { @@ -126,12 +125,12 @@ public class StreamResultTest extends StrutsInternalTestCase { result.doExecute("helloworld", mai); - //check that that headers are not set by default + //check that that headers are not set by default assertNull(response.getHeader("Pragma")); assertNull(response.getHeader("Cache-Control")); } - public void testAllowCacheFalse() throws Exception { + public void testAllowCacheFalse() throws Exception { result.setInputName("streamForImage"); result.setAllowCaching(false); result.doExecute("helloworld", mai); @@ -266,7 +265,6 @@ public class StreamResultTest extends StrutsInternalTestCase { } - protected void tearDown() throws Exception { super.tearDown(); response = null; diff --git a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java index 6f55eefde..50621d847 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/junit/StrutsRestTestCase.java @@ -23,7 +23,6 @@ import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.config.Configuration; import org.apache.struts2.ServletActionContext; -import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.mapper.ActionMapping; import org.springframework.mock.web.MockHttpServletRequest; @@ -75,7 +74,7 @@ public class StrutsRestTestCase extends StrutsJUnit4TestCase { ActionMapping mapping = getActionMapping(request); assertNotNull(mapping); - Dispatcher.getInstance().serviceAction(request, response, mapping); + dispatcher.serviceAction(request, response, mapping); if (response.getStatus() != HttpServletResponse.SC_OK) throw new ServletException("Error code [" + response.getStatus() + "], Error: [" From a57f51cc2bdd3d3501327c1c9b0798e314918152 Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Fri, 11 Oct 2024 20:55:50 +1100 Subject: [PATCH 2/4] WW-5468 Reworked fix, exempt ModelDriven Action parameters --- .../com/opensymphony/xwork2/ModelDriven.java | 5 +- .../parameter/ParametersInterceptor.java | 88 +++++++++---------- .../StrutsParameterAnnotationTest.java | 25 +++--- 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java b/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java index 59641a997..fc7f9a348 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java +++ b/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java @@ -30,10 +30,13 @@ public interface ModelDriven { /** * Gets the model to be pushed onto the ValueStack instead of the Action itself. + *

+ * Please be aware that all setters and getters of every depth on the object returned by this method are available + * for user parameter injection! * * @return the model */ - @StrutsParameter + @StrutsParameter(depth = Integer.MAX_VALUE) T getModel(); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java index 5d1010a0b..67e0d9142 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java @@ -259,19 +259,19 @@ public class ParametersInterceptor extends MethodFilterInterceptor { protected ValueStack toNewStack(ValueStack stack) { ValueStack newStack = valueStackFactory.createValueStack(stack); - if (newStack instanceof ClearableValueStack) { - ((ClearableValueStack) newStack).clearContextValues(); + if (newStack instanceof ClearableValueStack clearable) { + clearable.clearContextValues(); newStack.getActionContext().withLocale(stack.getActionContext().getLocale()).withValueStack(stack); } return newStack; } protected void applyMemberAccessProperties(ValueStack stack) { - if (!(stack instanceof MemberAccessValueStack)) { + if (!(stack instanceof MemberAccessValueStack accessValueStack)) { return; } - ((MemberAccessValueStack) stack).useAcceptProperties(acceptedPatterns.getAcceptedPatterns()); - ((MemberAccessValueStack) stack).useExcludeProperties(excludedPatterns.getExcludedPatterns()); + accessValueStack.useAcceptProperties(acceptedPatterns.getAcceptedPatterns()); + accessValueStack.useExcludeProperties(excludedPatterns.getExcludedPatterns()); } protected Map toAcceptableParameters(HttpParameters parameters, Object action) { @@ -333,7 +333,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } protected boolean isAcceptableParameterNameAware(String name, Object action) { - return !(action instanceof ParameterNameAware) || ((ParameterNameAware) action).acceptableParameterName(name); + return !(action instanceof ParameterNameAware nameAware) || nameAware.acceptableParameterName(name); } /** @@ -349,7 +349,15 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } long paramDepth = name.codePoints().mapToObj(c -> (char) c).filter(NESTING_CHARS::contains).count(); - if (!isModelDriven(action) && requireAnnotationsTransitionMode && paramDepth == 0) { + + if (action instanceof ModelDriven && !ActionContext.getContext().getValueStack().peek().equals(action)) { + LOG.debug("Model driven Action detected, exempting from @StrutsParameter annotation requirement and OGNL allowlisting model type"); + // (Exempted by annotation on com.opensymphony.xwork2.ModelDriven#getModel) + return hasValidAnnotatedMember("model", action, paramDepth + 1); + } + + if (requireAnnotationsTransitionMode && paramDepth == 0) { + LOG.debug("Annotation transition mode enabled, exempting non-nested parameter [{}] from @StrutsParameter annotation requirement", name); return true; } @@ -366,39 +374,34 @@ public class ParametersInterceptor extends MethodFilterInterceptor { * save computation by checking this last. */ protected boolean hasValidAnnotatedMember(String rootProperty, Object action, long paramDepth) { - final String property = isModelDriven(action) ? "model" : rootProperty; - LOG.debug("Using [{}] as a root property of [{}]", property, action.getClass().getSimpleName()); - + LOG.debug("Checking Action [{}] for a matching, correctly annotated member for property [{}]", + action.getClass().getSimpleName(), rootProperty); BeanInfo beanInfo = getBeanInfo(action); if (beanInfo == null) { - return hasValidAnnotatedField(action, property, paramDepth); + return hasValidAnnotatedField(action, rootProperty, paramDepth); } Optional propDescOpt = Arrays.stream(beanInfo.getPropertyDescriptors()) - .filter(desc -> desc.getName().equals(property)).findFirst(); + .filter(desc -> desc.getName().equals(rootProperty)).findFirst(); if (propDescOpt.isEmpty()) { - return hasValidAnnotatedField(action, property, paramDepth); + return hasValidAnnotatedField(action, rootProperty, paramDepth); } if (hasValidAnnotatedPropertyDescriptor(action, propDescOpt.get(), paramDepth)) { return true; } - return hasValidAnnotatedField(action, property, paramDepth); + return hasValidAnnotatedField(action, rootProperty, paramDepth); } protected boolean hasValidAnnotatedPropertyDescriptor(Object action, PropertyDescriptor propDesc, long paramDepth) { - Method relevantMethod = getRelevantMethod(action, propDesc, paramDepth); - + Method relevantMethod = paramDepth == 0 ? propDesc.getWriteMethod() : propDesc.getReadMethod(); if (relevantMethod == null) { - LOG.debug("No such property [{}] in action [{}]", propDesc.getName(), action.getClass().getSimpleName()); return false; } - - LOG.debug("Using [{}] as a property of [{}]", relevantMethod.getName(), action.getClass().getSimpleName()); if (getPermittedInjectionDepth(relevantMethod) < paramDepth) { String logMessage = format( - "Parameter injection for method [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", + "Parameter injection for method [%s] on Action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", relevantMethod.getName(), relevantMethod.getDeclaringClass().getName()); if (devMode) { @@ -408,11 +411,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } return false; } - if (isModelDriven(action)) { - allowlistClass(propDesc.getPropertyType()); - } + LOG.debug("Success: Matching annotated method [{}] found for property [{}] of depth [{}] on Action [{}]", + relevantMethod.getName(), propDesc.getName(), paramDepth, action.getClass().getSimpleName()); if (paramDepth >= 1) { - allowlistClass(relevantMethod.getReturnType()); + allowlistClass(propDesc.getPropertyType()); } if (paramDepth >= 2) { allowlistReturnTypeIfParameterized(relevantMethod); @@ -420,16 +422,6 @@ public class ParametersInterceptor extends MethodFilterInterceptor { return true; } - private Method getRelevantMethod(Object action, PropertyDescriptor propDesc, long paramDepth) { - Method useReadOrWriteMethod = isModelDriven(action) ? propDesc.getReadMethod() : propDesc.getWriteMethod(); - return paramDepth == 0 ? useReadOrWriteMethod : propDesc.getReadMethod(); - } - - private boolean isModelDriven(Object action) { - return action instanceof ModelDriven; - } - - protected void allowlistReturnTypeIfParameterized(Method method) { allowlistParameterizedTypeArg(method.getGenericReturnType()); } @@ -459,22 +451,22 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } protected boolean hasValidAnnotatedField(Object action, String fieldName, long paramDepth) { + LOG.debug("No matching annotated method found for property [{}] of depth [{}] on Action [{}], now also checking for public field", + fieldName, paramDepth, action.getClass().getSimpleName()); Field field; - LOG.debug("Checking if field [{}] of [{}] is annotated with [{}]", - fieldName, action.getClass().getSimpleName(), StrutsParameter.class.getSimpleName()); try { field = action.getClass().getDeclaredField(fieldName); } catch (NoSuchFieldException e) { - LOG.debug("Field [{}] not found", fieldName); + LOG.debug("Matching field for property [{}] not found on Action [{}]", fieldName, action.getClass().getSimpleName()); return false; } if (!Modifier.isPublic(field.getModifiers())) { - LOG.debug("Field [{}] is not public", fieldName); + LOG.debug("Matching field [{}] is not public on Action [{}]", field.getName(), action.getClass().getSimpleName()); return false; } if (getPermittedInjectionDepth(field) < paramDepth) { String logMessage = format( - "Parameter injection for field [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", + "Parameter injection for field [%s] on Action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.", field.getName(), action.getClass().getName()); if (devMode) { @@ -484,6 +476,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } return false; } + LOG.debug("Success: Matching annotated public field [{}] found for property of depth [{}] on Action [{}]", + field.getName(), paramDepth, action.getClass().getSimpleName()); if (paramDepth >= 1) { allowlistClass(field.getType()); } @@ -537,7 +531,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } protected boolean isAcceptableParameterValueAware(Parameter param, Object action) { - return !(action instanceof ParameterValueAware) || ((ParameterValueAware) action).acceptableParameterValue(param.getValue()); + return !(action instanceof ParameterValueAware valueAware) || valueAware.acceptableParameterValue(param.getValue()); } /** @@ -616,9 +610,9 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (!matchLength) { if (devMode) { LOG.warn("Parameter [{}] is too long, allowed length is [{}]. Use Interceptor Parameter Overriding " + - "to override the limit, see more at\n" + - "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding", - name, paramNameMaxLength); + "to override the limit, see more at\n" + + "https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding", + name, paramNameMaxLength); } else { LOG.warn("Parameter [{}] is too long, allowed length is [{}]", name, paramNameMaxLength); } @@ -631,7 +625,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (!result.isAccepted()) { if (devMode) { LOG.warn("Parameter [{}] didn't match accepted pattern [{}]! See Accepted / Excluded patterns at\n" + - "https://struts.apache.org/security/#accepted--excluded-patterns", + "https://struts.apache.org/security/#accepted--excluded-patterns", paramName, result.getAcceptedPattern()); } else { LOG.debug("Parameter [{}] didn't match accepted pattern [{}]!", paramName, result.getAcceptedPattern()); @@ -646,7 +640,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (result.isExcluded()) { if (devMode) { LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" + - "https://struts.apache.org/security/#accepted--excluded-patterns", + "https://struts.apache.org/security/#accepted--excluded-patterns", paramName, result.getExcludedPattern()); } else { LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern()); @@ -665,7 +659,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { if (excludedValuePattern.matcher(value).matches()) { if (devMode) { LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" + - "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", + "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", value, excludedValuePatterns); } else { LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedValuePattern); @@ -688,7 +682,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } if (devMode) { LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" + - "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", + "https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values", value, acceptedValuePatterns); } else { LOG.debug("Parameter value [{}] was not accepted!", value); diff --git a/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java b/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java index eb44fc6fe..8116952b6 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java @@ -18,7 +18,9 @@ */ package org.apache.struts2.interceptor.parameter; +import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ModelDriven; +import com.opensymphony.xwork2.StubValueStack; import com.opensymphony.xwork2.security.AcceptedPatternsChecker; import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker; import org.apache.commons.lang3.ClassUtils; @@ -64,6 +66,7 @@ public class StrutsParameterAnnotationTest { @After public void tearDown() throws Exception { threadAllowlist.clearAllowlist(); + ActionContext.clear(); } private void testParameter(Object action, String paramName, boolean shouldContain) { @@ -261,8 +264,15 @@ public class StrutsParameterAnnotationTest { @Test public void publicModelPojo() { - parametersInterceptor.setRequireAnnotationsTransitionMode(Boolean.TRUE.toString()); - testParameter(new ModelAction(), "name", true); + var action = new ModelAction(); + + // Emulate ModelDrivenInterceptor running previously + var valueStack = new StubValueStack(); + valueStack.push(action.getModel()); + ActionContext.of().withValueStack(valueStack).bind(); + + testParameter(action, "name", true); + testParameter(action, "name.nested", true); assertThat(threadAllowlist.getAllowlist()).containsExactlyInAnyOrderElementsOf(getParentClasses(Object.class, Pojo.class)); } @@ -352,21 +362,12 @@ public class StrutsParameterAnnotationTest { static class ModelAction implements ModelDriven { - @StrutsParameter + @Override public Pojo getModel() { return new Pojo(); } } static class Pojo { - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } } } From 58e19dde30c79dc2cb2a36abea50d07024916933 Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Sat, 12 Oct 2024 22:52:53 +1100 Subject: [PATCH 3/4] WW-5468 Remove unneeded annotations --- .../struts2/showcase/modelDriven/ModelDrivenAction.java | 2 +- .../test/java/com/opensymphony/xwork2/ModelDrivenAction.java | 3 +-- .../com/opensymphony/xwork2/ModelDrivenAnnotationAction.java | 3 +-- .../xwork2/interceptor/ModelDrivenInterceptorTest.java | 2 +- .../com/opensymphony/xwork2/test/ModelDrivenAction2.java | 4 +--- .../xwork2/test/ModelDrivenAnnotationAction2.java | 4 +--- .../xwork2/test/subtest/NullModelDrivenAction.java | 3 ++- .../xwork2/validator/VisitorValidatorModelAction.java | 5 ++--- .../struts/beanvalidation/actions/ModelDrivenAction.java | 5 +---- .../struts/beanvalidation/actions/ValidateGroupAction.java | 5 +---- .../org/apache/struts2/rest/RestActionInvocationTest.java | 2 -- .../test/java/com/opensymphony/xwork2/ModelDrivenAction.java | 3 +-- 12 files changed, 13 insertions(+), 28 deletions(-) diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java index 60692b0e6..0fae6c481 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java @@ -42,7 +42,7 @@ public class ModelDrivenAction extends ActionSupport implements ModelDriven { } @Override - public Object getModel() { + public Gangster getModel() { return new Gangster(); } } diff --git a/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java b/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java index 6ffcad2ff..e300d036b 100644 --- a/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java @@ -44,9 +44,8 @@ public class ModelDrivenAction extends ActionSupport implements ModelDriven { /** * @return the model to be pushed onto the ValueStack after the Action itself */ - @StrutsParameter(depth = 2) @Override - public Object getModel() { + public TestBean getModel() { return model; } } diff --git a/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAnnotationAction.java b/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAnnotationAction.java index 5549b60b1..f05641732 100644 --- a/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAnnotationAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/ModelDrivenAnnotationAction.java @@ -44,9 +44,8 @@ public class ModelDrivenAnnotationAction extends ActionSupport implements ModelD /** * @return the model to be pushed onto the ValueStack after the Action itself */ - @StrutsParameter(depth = 2) @Override - public Object getModel() { + public AnnotatedTestBean getModel() { return model; } } diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptorTest.java index 65b21c86d..f6513f5f2 100644 --- a/core/src/test/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptorTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptorTest.java @@ -178,7 +178,7 @@ public class ModelDrivenInterceptorTest extends XWorkTestCase { } - public class ModelDrivenAction extends ActionSupport implements ModelDriven { + public class ModelDrivenAction extends ActionSupport implements ModelDriven { @Override public Object getModel() { diff --git a/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAction2.java b/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAction2.java index 0c445860b..5e29e6899 100644 --- a/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAction2.java +++ b/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAction2.java @@ -19,7 +19,6 @@ package com.opensymphony.xwork2.test; import com.opensymphony.xwork2.ModelDrivenAction; -import org.apache.struts2.interceptor.parameter.StrutsParameter; /** @@ -35,9 +34,8 @@ public class ModelDrivenAction2 extends ModelDrivenAction { /** * @return the model to be pushed onto the ValueStack after the Action itself */ - @StrutsParameter(depth = 3) @Override - public Object getModel() { + public TestBean2 getModel() { return model; } } diff --git a/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAnnotationAction2.java b/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAnnotationAction2.java index 7c26dcfab..b2fcdf542 100644 --- a/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAnnotationAction2.java +++ b/core/src/test/java/com/opensymphony/xwork2/test/ModelDrivenAnnotationAction2.java @@ -19,7 +19,6 @@ package com.opensymphony.xwork2.test; import com.opensymphony.xwork2.ModelDrivenAnnotationAction; -import org.apache.struts2.interceptor.parameter.StrutsParameter; /** @@ -36,9 +35,8 @@ public class ModelDrivenAnnotationAction2 extends ModelDrivenAnnotationAction { /** * @return the model to be pushed onto the ValueStack after the Action itself */ - @StrutsParameter(depth = 3) @Override - public Object getModel() { + public AnnotationTestBean2 getModel() { return model; } } diff --git a/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java b/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java index be0916d9d..3551a4643 100644 --- a/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java @@ -19,6 +19,7 @@ package com.opensymphony.xwork2.test.subtest; import com.opensymphony.xwork2.ModelDrivenAction; +import com.opensymphony.xwork2.TestBean; /** * Extends ModelDrivenAction to return a null model. @@ -31,7 +32,7 @@ public class NullModelDrivenAction extends ModelDrivenAction { * @return the model to be pushed onto the ValueStack instead of the Action itself */ @Override - public Object getModel() { + public TestBean getModel() { return null; } } diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java index 9f5baeee0..9ec226f98 100644 --- a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorValidatorModelAction.java @@ -19,7 +19,7 @@ package com.opensymphony.xwork2.validator; import com.opensymphony.xwork2.ModelDriven; -import org.apache.struts2.interceptor.parameter.StrutsParameter; +import com.opensymphony.xwork2.TestBean; /** @@ -33,9 +33,8 @@ public class VisitorValidatorModelAction extends VisitorValidatorTestAction impl /** * @return the model to be pushed onto the ValueStack instead of the Action itself */ - @StrutsParameter(depth = 2) @Override - public Object getModel() { + public TestBean getModel() { return getBean(); } } diff --git a/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ModelDrivenAction.java b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ModelDrivenAction.java index 296f42c62..48ee558f6 100644 --- a/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ModelDrivenAction.java +++ b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ModelDrivenAction.java @@ -20,17 +20,14 @@ package org.apache.struts.beanvalidation.actions; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; -import org.apache.struts.beanvalidation.models.Person; -import org.apache.struts2.interceptor.parameter.StrutsParameter; - import jakarta.validation.Valid; +import org.apache.struts.beanvalidation.models.Person; public class ModelDrivenAction extends ActionSupport implements ModelDriven, ModelDrivenActionInterface { @Valid private final Person model = new Person(); - @StrutsParameter(depth = 2) @Override public Person getModel() { return model; diff --git a/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ValidateGroupAction.java b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ValidateGroupAction.java index 20aabf15b..9acc31df6 100644 --- a/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ValidateGroupAction.java +++ b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/actions/ValidateGroupAction.java @@ -20,18 +20,15 @@ package org.apache.struts.beanvalidation.actions; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; +import jakarta.validation.Valid; import org.apache.struts.beanvalidation.constraints.ValidationGroup; import org.apache.struts.beanvalidation.models.Person; -import org.apache.struts2.interceptor.parameter.StrutsParameter; - -import jakarta.validation.Valid; public class ValidateGroupAction extends ActionSupport implements ModelDriven { @Valid private final Person model = new Person(); - @StrutsParameter(depth = 2) @Override public Person getModel() { return model; diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java index 0e64f2ef8..6536fd187 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java @@ -35,7 +35,6 @@ import com.opensymphony.xwork2.util.XWorkTestCaseHelper; import jakarta.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.apache.struts2.ServletActionContext; -import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.ognl.StrutsOgnlGuard; import org.apache.struts2.result.HttpHeaderResult; import org.springframework.mock.web.MockHttpServletRequest; @@ -298,7 +297,6 @@ public class RestActionInvocationTest extends TestCase { List model; - @StrutsParameter(depth = 1) @Override public List getModel() { return model; diff --git a/plugins/spring/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java b/plugins/spring/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java index 6ffcad2ff..e300d036b 100644 --- a/plugins/spring/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java +++ b/plugins/spring/src/test/java/com/opensymphony/xwork2/ModelDrivenAction.java @@ -44,9 +44,8 @@ public class ModelDrivenAction extends ActionSupport implements ModelDriven { /** * @return the model to be pushed onto the ValueStack after the Action itself */ - @StrutsParameter(depth = 2) @Override - public Object getModel() { + public TestBean getModel() { return model; } } From f6c17e9c6d8a99a0c2b15289f6f1a1d74649c2ca Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Sat, 12 Oct 2024 22:58:00 +1100 Subject: [PATCH 4/4] WW-5468 Replace tabs with spaces --- .../rest/RestActionInvocationTest.java | 344 +++++++++--------- 1 file changed, 172 insertions(+), 172 deletions(-) diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java index 6536fd187..c6019c0e0 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java @@ -50,97 +50,97 @@ import static jakarta.servlet.http.HttpServletResponse.SC_NOT_MODIFIED; public class RestActionInvocationTest extends TestCase { - RestActionInvocation restActionInvocation; - MockHttpServletRequest request; - MockHttpServletResponse response; + RestActionInvocation restActionInvocation; + MockHttpServletRequest request; + MockHttpServletResponse response; - @Override - protected void setUp() throws Exception { - super.setUp(); + @Override + protected void setUp() throws Exception { + super.setUp(); - restActionInvocation = new RestActionInvocationTester(); - request = new MockHttpServletRequest(); - response = new MockHttpServletResponse(); - ServletActionContext.setRequest(request); - ServletActionContext.setResponse(response); + restActionInvocation = new RestActionInvocationTester(); + request = new MockHttpServletRequest(); + response = new MockHttpServletResponse(); + ServletActionContext.setRequest(request); + ServletActionContext.setResponse(response); - } + } - /** - * Test the correct action results: null, String, HttpHeaders, Result - * @throws Exception - */ - public void testSaveResult() throws Exception { + /** + * Test the correct action results: null, String, HttpHeaders, Result + * @throws Exception + */ + public void testSaveResult() throws Exception { - Object methodResult = "index"; - ActionConfig actionConfig = restActionInvocation.getProxy().getConfig(); - assertEquals("index", restActionInvocation.saveResult(actionConfig, methodResult)); + Object methodResult = "index"; + ActionConfig actionConfig = restActionInvocation.getProxy().getConfig(); + assertEquals("index", restActionInvocation.saveResult(actionConfig, methodResult)); - setUp(); - methodResult = new DefaultHttpHeaders("show"); - assertEquals("show", restActionInvocation.saveResult(actionConfig, methodResult)); - assertEquals(methodResult, restActionInvocation.httpHeaders); + setUp(); + methodResult = new DefaultHttpHeaders("show"); + assertEquals("show", restActionInvocation.saveResult(actionConfig, methodResult)); + assertEquals(methodResult, restActionInvocation.httpHeaders); - setUp(); - methodResult = new HttpHeaderResult(HttpServletResponse.SC_ACCEPTED); - assertEquals(null, restActionInvocation.saveResult(actionConfig, methodResult)); - assertEquals(methodResult, restActionInvocation.createResult()); + setUp(); + methodResult = new HttpHeaderResult(HttpServletResponse.SC_ACCEPTED); + assertEquals(null, restActionInvocation.saveResult(actionConfig, methodResult)); + assertEquals(methodResult, restActionInvocation.createResult()); - setUp(); - try { - methodResult = new Object(); - restActionInvocation.saveResult(actionConfig, methodResult); + setUp(); + try { + methodResult = new Object(); + restActionInvocation.saveResult(actionConfig, methodResult); - // ko - assertFalse(true); + // ko + assertFalse(true); - } catch (ConfigurationException c) { - // ok, object not allowed - } - } + } catch (ConfigurationException c) { + // ok, object not allowed + } + } - /** - * Test the target selection: exception, error messages, model and null - * @throws Exception - */ - public void testSelectTarget() throws Exception { + /** + * Test the target selection: exception, error messages, model and null + * @throws Exception + */ + public void testSelectTarget() throws Exception { - // Exception - Exception e = new Exception(); - restActionInvocation.getStack().set("exception", e); - restActionInvocation.selectTarget(); - assertEquals(e, restActionInvocation.target); + // Exception + Exception e = new Exception(); + restActionInvocation.getStack().set("exception", e); + restActionInvocation.selectTarget(); + assertEquals(e, restActionInvocation.target); - // Error messages - setUp(); - String actionMessage = "Error!"; - RestActionSupport action = (RestActionSupport)restActionInvocation.getAction(); - action.addActionError(actionMessage); - Map errors = new HashMap(); - List list = new ArrayList(); - list.add(actionMessage); - errors.put("actionErrors", list); - restActionInvocation.selectTarget(); - assertEquals(errors, restActionInvocation.target); + // Error messages + setUp(); + String actionMessage = "Error!"; + RestActionSupport action = (RestActionSupport)restActionInvocation.getAction(); + action.addActionError(actionMessage); + Map errors = new HashMap(); + List list = new ArrayList(); + list.add(actionMessage); + errors.put("actionErrors", list); + restActionInvocation.selectTarget(); + assertEquals(errors, restActionInvocation.target); - // Model with get and no content in post, put, delete - setUp(); - RestAction restAction = (RestAction)restActionInvocation.getAction(); - List model = new ArrayList(); - model.add("Item"); - restAction.model = model; - request.setMethod("GET"); - restActionInvocation.selectTarget(); - assertEquals(model, restActionInvocation.target); - request.setMethod("POST"); - restActionInvocation.selectTarget(); - assertEquals(null, restActionInvocation.target); - request.setMethod("PUT"); - restActionInvocation.selectTarget(); - assertEquals(null, restActionInvocation.target); - request.setMethod("DELETE"); - restActionInvocation.selectTarget(); - assertEquals(null, restActionInvocation.target); + // Model with get and no content in post, put, delete + setUp(); + RestAction restAction = (RestAction)restActionInvocation.getAction(); + List model = new ArrayList(); + model.add("Item"); + restAction.model = model; + request.setMethod("GET"); + restActionInvocation.selectTarget(); + assertEquals(model, restActionInvocation.target); + request.setMethod("POST"); + restActionInvocation.selectTarget(); + assertEquals(null, restActionInvocation.target); + request.setMethod("PUT"); + restActionInvocation.selectTarget(); + assertEquals(null, restActionInvocation.target); + request.setMethod("DELETE"); + restActionInvocation.selectTarget(); + assertEquals(null, restActionInvocation.target); // disable content restriction to GET only model = new ArrayList(); @@ -154,108 +154,108 @@ public class RestActionInvocationTest extends TestCase { assertEquals(model.get(0), "Item1"); } - /** - * Test the not modified status code. - * @throws Exception - */ - public void testResultNotModified() throws Exception { + /** + * Test the not modified status code. + * @throws Exception + */ + public void testResultNotModified() throws Exception { - request.addHeader("If-None-Match", "123"); - request.setMethod("GET"); + request.addHeader("If-None-Match", "123"); + request.setMethod("GET"); - RestAction restAction = (RestAction)restActionInvocation.getAction(); - List model = new ArrayList() { - @Override - public int hashCode() { - return 123; - } - }; - model.add("Item"); - restAction.model = model; + RestAction restAction = (RestAction)restActionInvocation.getAction(); + List model = new ArrayList() { + @Override + public int hashCode() { + return 123; + } + }; + model.add("Item"); + restAction.model = model; - restActionInvocation.processResult(); - assertEquals(SC_NOT_MODIFIED, response.getStatus()); + restActionInvocation.processResult(); + assertEquals(SC_NOT_MODIFIED, response.getStatus()); } - /** - * Test the default error result. - * @throws Exception - */ - public void testDefaultErrorResult() throws Exception { + /** + * Test the default error result. + * @throws Exception + */ + public void testDefaultErrorResult() throws Exception { - // Exception - Exception e = new Exception(); - restActionInvocation.getStack().set("exception", e); - request.setMethod("GET"); + // Exception + Exception e = new Exception(); + restActionInvocation.getStack().set("exception", e); + request.setMethod("GET"); - RestAction restAction = (RestAction)restActionInvocation.getAction(); - List model = new ArrayList(); - model.add("Item"); - restAction.model = model; + RestAction restAction = (RestAction)restActionInvocation.getAction(); + List model = new ArrayList(); + model.add("Item"); + restAction.model = model; - restActionInvocation.setDefaultErrorResultName("default-error"); - ResultConfig resultConfig = new ResultConfig.Builder("default-error", - "org.apache.struts2.result.HttpHeaderResult") - .addParam("status", "123").build(); - ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", - "RestAction", "org.apache.rest.RestAction") - .addResultConfig(resultConfig) - .build(); - ((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig); + restActionInvocation.setDefaultErrorResultName("default-error"); + ResultConfig resultConfig = new ResultConfig.Builder("default-error", + "org.apache.struts2.result.HttpHeaderResult") + .addParam("status", "123").build(); + ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", + "RestAction", "org.apache.rest.RestAction") + .addResultConfig(resultConfig) + .build(); + ((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig); - restActionInvocation.processResult(); - assertEquals(123, response.getStatus()); + restActionInvocation.processResult(); + assertEquals(123, response.getStatus()); - } + } - public void testNoResult() throws Exception { + public void testNoResult() throws Exception { - RestAction restAction = (RestAction)restActionInvocation.getAction(); - List model = new ArrayList(); - model.add("Item"); - restAction.model = model; - request.setMethod("GET"); - restActionInvocation.setResultCode("index"); + RestAction restAction = (RestAction)restActionInvocation.getAction(); + List model = new ArrayList(); + model.add("Item"); + restAction.model = model; + request.setMethod("GET"); + restActionInvocation.setResultCode("index"); - try { - restActionInvocation.processResult(); + try { + restActionInvocation.processResult(); - // ko - assertFalse(true); + // ko + assertFalse(true); - } catch (ConfigurationException c) { - // ok, no result - } + } catch (ConfigurationException c) { + // ok, no result + } - } + } - /** - * Test the global execution - * @throws Exception - */ - public void testInvoke() throws Exception { + /** + * Test the global execution + * @throws Exception + */ + public void testInvoke() throws Exception { - // Default index method return 'success' - ((MockActionProxy)restActionInvocation.getProxy()).setMethod("index"); + // Default index method return 'success' + ((MockActionProxy)restActionInvocation.getProxy()).setMethod("index"); - // Define result 'success' - ResultConfig resultConfig = new ResultConfig.Builder("success", - "org.apache.struts2.result.HttpHeaderResult") - .addParam("status", "123").build(); - ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", - "RestAction", "org.apache.rest.RestAction") - .addResultConfig(resultConfig) - .build(); - ((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig); + // Define result 'success' + ResultConfig resultConfig = new ResultConfig.Builder("success", + "org.apache.struts2.result.HttpHeaderResult") + .addParam("status", "123").build(); + ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", + "RestAction", "org.apache.rest.RestAction") + .addResultConfig(resultConfig) + .build(); + ((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig); - request.setMethod("GET"); + request.setMethod("GET"); restActionInvocation.setOgnlUtil(new OgnlUtil( - new DefaultOgnlExpressionCacheFactory<>(String.valueOf(10_000), BASIC.toString()), - new DefaultOgnlBeanInfoCacheFactory<>(String.valueOf(10_000), BASIC.toString()), - new StrutsOgnlGuard() - )); + new DefaultOgnlExpressionCacheFactory<>(String.valueOf(10_000), BASIC.toString()), + new DefaultOgnlBeanInfoCacheFactory<>(String.valueOf(10_000), BASIC.toString()), + new StrutsOgnlGuard() + )); restActionInvocation.invoke(); assertEquals(123, response.getStatus()); @@ -263,7 +263,7 @@ public class RestActionInvocationTest extends TestCase { class RestActionInvocationTester extends RestActionInvocation { - RestActionInvocationTester() { + RestActionInvocationTester() { super(new HashMap(), true); List interceptorMappings = new ArrayList(); MockInterceptor mockInterceptor = new MockInterceptor(); @@ -273,21 +273,21 @@ public class RestActionInvocationTest extends TestCase { interceptors = interceptorMappings.iterator(); MockActionProxy actionProxy = new MockActionProxy(); ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", - "RestAction", "org.apache.rest.RestAction").build(); + "RestAction", "org.apache.rest.RestAction").build(); actionProxy.setConfig(actionConfig); proxy = actionProxy; action = new RestAction(); setMimeTypeHandlerSelector(new DefaultContentTypeHandlerManager()); unknownHandlerManager = new DefaultUnknownHandlerManager(); - try { - XWorkTestCaseHelper.setUp(); - } catch (Exception e) { - throw new RuntimeException(e); - } - invocationContext = ActionContext.getContext(); - container = ActionContext.getContext().getContainer(); - stack = ActionContext.getContext().getValueStack(); - objectFactory = container.getInstance(ObjectFactory.class); + try { + XWorkTestCaseHelper.setUp(); + } catch (Exception e) { + throw new RuntimeException(e); + } + invocationContext = ActionContext.getContext(); + container = ActionContext.getContext().getContainer(); + stack = ActionContext.getContext().getValueStack(); + objectFactory = container.getInstance(ObjectFactory.class); } @@ -295,12 +295,12 @@ public class RestActionInvocationTest extends TestCase { static class RestAction extends RestActionSupport implements ModelDriven> { - List model; + List model; - @Override - public List getModel() { - return model; - } + @Override + public List getModel() { + return model; + } } }