diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 01d5374d9..21bc0fc69 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -54,7 +54,7 @@ public class OgnlUtil { private static final Logger LOG = LogManager.getLogger(OgnlUtil.class); private final ConcurrentMap expressions = new ConcurrentHashMap<>(); - private final ConcurrentMap beanInfoCache = new ConcurrentHashMap<>(); + private final ConcurrentMap, BeanInfo> beanInfoCache = new ConcurrentHashMap<>(); private TypeConverter defaultConverter; private boolean devMode; @@ -65,18 +65,23 @@ public class OgnlUtil { private Set excludedPackageNamePatterns; private Set excludedPackageNames; + private Set> devModeExcludedClasses; + private Set devModeExcludedPackageNamePatterns; + private Set devModeExcludedPackageNames; + private Container container; private boolean allowStaticFieldAccess = true; private boolean allowStaticMethodAccess; private boolean disallowProxyMemberAccess; public OgnlUtil() { - excludedClasses = new HashSet<>(); - excludedPackageNamePatterns = new HashSet<>(); - excludedPackageNames = new HashSet<>(); - excludedClasses = Collections.unmodifiableSet(excludedClasses); - excludedPackageNamePatterns = Collections.unmodifiableSet(excludedPackageNamePatterns); - excludedPackageNames = Collections.unmodifiableSet(excludedPackageNames); + excludedClasses = Collections.unmodifiableSet(new HashSet<>()); + excludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>()); + excludedPackageNames = Collections.unmodifiableSet(new HashSet<>()); + + devModeExcludedClasses = Collections.unmodifiableSet(new HashSet<>()); + devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>()); + devModeExcludedPackageNames = Collections.unmodifiableSet(new HashSet<>()); } @Inject @@ -111,6 +116,14 @@ public class OgnlUtil { this.excludedClasses = Collections.unmodifiableSet(excludedClasses); } + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required = false) + protected void setDevModeExcludedClasses(String commaDelimitedClasses) { + Set> excludedClasses = new HashSet<>(); + excludedClasses.addAll(this.devModeExcludedClasses); + excludedClasses.addAll(parseExcludedClasses(commaDelimitedClasses)); + this.devModeExcludedClasses = Collections.unmodifiableSet(excludedClasses); + } + private Set> parseExcludedClasses(String commaDelimitedClasses) { Set classNames = TextParseUtil.commaDelimitedStringToSet(commaDelimitedClasses); Set> classes = new HashSet<>(); @@ -134,6 +147,14 @@ public class OgnlUtil { this.excludedPackageNamePatterns = Collections.unmodifiableSet(excludedPackageNamePatterns); } + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false) + protected void setDevModeExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) { + Set excludedPackageNamePatterns = new HashSet<>(); + excludedPackageNamePatterns.addAll(this.devModeExcludedPackageNamePatterns); + excludedPackageNamePatterns.addAll(parseExcludedPackageNamePatterns(commaDelimitedPackagePatterns)); + this.devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(excludedPackageNamePatterns); + } + private Set parseExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) { Set packagePatterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackagePatterns); Set packageNamePatterns = new HashSet<>(); @@ -153,6 +174,14 @@ public class OgnlUtil { this.excludedPackageNames = Collections.unmodifiableSet(excludedPackageNames); } + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, required = false) + protected void setDevModeExcludedPackageNames(String commaDelimitedPackageNames) { + Set excludedPackageNames = new HashSet<>(); + excludedPackageNames.addAll(this.devModeExcludedPackageNames); + excludedPackageNames.addAll(parseExcludedPackageNames(commaDelimitedPackageNames)); + this.devModeExcludedPackageNames = Collections.unmodifiableSet(excludedPackageNames); + } + private Set parseExcludedPackageNames(String commaDelimitedPackageNames) { return TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames); } @@ -339,7 +368,7 @@ public class OgnlUtil { * problems setting the properties */ public void setProperties(Map properties, Object o, boolean throwPropertyExceptions) { - Map context = createDefaultContext(o, null); + Map context = createDefaultContext(o); setProperties(properties, o, context, throwPropertyExceptions); } @@ -428,17 +457,15 @@ public class OgnlUtil { * @throws OgnlException in case of ognl errors */ public void setValue(final String name, final Map context, final Object root, final Object value) throws OgnlException { - compileAndExecute(name, context, new OgnlTask() { - public Void execute(Object tree) throws OgnlException { - if (isEvalExpression(tree, context)) { - throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name"); - } - if (isArithmeticExpression(tree, context)) { - throw new OgnlException("Arithmetic expressions cannot be used as parameter name"); - } - Ognl.setValue(tree, context, root, value); - return null; + compileAndExecute(name, context, (OgnlTask) tree -> { + if (isEvalExpression(tree, context)) { + throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name"); } + if (isArithmeticExpression(tree, context)) { + throw new OgnlException("Arithmetic expressions cannot be used as parameter name"); + } + Ognl.setValue(tree, context, root, value); + return null; }); } @@ -447,7 +474,7 @@ public class OgnlUtil { SimpleNode node = (SimpleNode) tree; OgnlContext ognlContext = null; - if (context!=null && context instanceof OgnlContext) { + if (context instanceof OgnlContext) { ognlContext = (OgnlContext) context; } return node.isEvalChain(ognlContext) || node.isSequence(ognlContext); @@ -460,7 +487,7 @@ public class OgnlUtil { SimpleNode node = (SimpleNode) tree; OgnlContext ognlContext = null; - if (context!=null && context instanceof OgnlContext) { + if (context instanceof OgnlContext) { ognlContext = (OgnlContext) context; } return node.isOperation(ognlContext); @@ -473,7 +500,7 @@ public class OgnlUtil { SimpleNode node = (SimpleNode) tree; OgnlContext ognlContext = null; - if (context!=null && context instanceof OgnlContext) { + if (context instanceof OgnlContext) { ognlContext = (OgnlContext) context; } return node.isSimpleMethod(ognlContext) && !node.isChain(ognlContext); @@ -482,27 +509,15 @@ public class OgnlUtil { } public Object getValue(final String name, final Map context, final Object root) throws OgnlException { - return compileAndExecute(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root); - } - }); + return compileAndExecute(name, context, tree -> Ognl.getValue(tree, context, root)); } public Object callMethod(final String name, final Map context, final Object root) throws OgnlException { - return compileAndExecuteMethod(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root); - } - }); + return compileAndExecuteMethod(name, context, tree -> Ognl.getValue(tree, context, root)); } - public Object getValue(final String name, final Map context, final Object root, final Class resultType) throws OgnlException { - return compileAndExecute(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root, resultType); - } - }); + public Object getValue(final String name, final Map context, final Object root, final Class resultType) throws OgnlException { + return compileAndExecute(name, context, tree -> Ognl.getValue(tree, context, root, resultType)); } @@ -553,11 +568,7 @@ public class OgnlUtil { } public Object compile(String expression, Map context) throws OgnlException { - return compileAndExecute(expression,context,new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return tree; - } - }); + return compileAndExecute(expression, context, tree -> tree); } private void checkEnableEvalExpression(Object tree, Map context) throws OgnlException { @@ -608,8 +619,8 @@ public class OgnlUtil { return; } - final Map contextFrom = createDefaultContext(from, null); - final Map contextTo = createDefaultContext(to, null); + final Map contextFrom = createDefaultContext(from); + final Map contextTo = createDefaultContext(to); PropertyDescriptor[] fromPds; PropertyDescriptor[] toPds; @@ -646,12 +657,10 @@ public class OgnlUtil { PropertyDescriptor toPd = toPdHash.get(fromPd.getName()); if ((toPd != null) && (toPd.getWriteMethod() != null)) { try { - compileAndExecute(fromPd.getName(), context, new OgnlTask() { - public Void execute(Object expr) throws OgnlException { - Object value = Ognl.getValue(expr, contextFrom, from); - Ognl.setValue(expr, contextTo, to, value); - return null; - } + compileAndExecute(fromPd.getName(), context, expr -> { + Object value = Ognl.getValue(expr, contextFrom, from); + Ognl.setValue(expr, contextTo, to, value); + return null; }); } catch (OgnlException e) { @@ -700,7 +709,7 @@ public class OgnlUtil { * @return property descriptors. * @throws IntrospectionException is thrown if an exception occurs during introspection. */ - public PropertyDescriptor[] getPropertyDescriptors(Class clazz) throws IntrospectionException { + public PropertyDescriptor[] getPropertyDescriptors(Class clazz) throws IntrospectionException { BeanInfo beanInfo = getBeanInfo(clazz); return beanInfo.getPropertyDescriptors(); } @@ -719,17 +728,13 @@ public class OgnlUtil { */ public Map getBeanMap(final Object source) throws IntrospectionException, OgnlException { Map beanMap = new HashMap<>(); - final Map sourceMap = createDefaultContext(source, null); + final Map sourceMap = createDefaultContext(source); PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(source); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { final String propertyName = propertyDescriptor.getDisplayName(); Method readMethod = propertyDescriptor.getReadMethod(); if (readMethod != null) { - final Object value = compileAndExecute(propertyName, null, new OgnlTask() { - public Object execute(Object expr) throws OgnlException { - return Ognl.getValue(expr, sourceMap, source); - } - }); + final Object value = compileAndExecute(propertyName, null, expr -> Ognl.getValue(expr, sourceMap, source)); beanMap.put(propertyName, value); } else { beanMap.put(propertyName, "There is no read method for " + propertyName); @@ -757,7 +762,7 @@ public class OgnlUtil { * @return java bean info. * @throws IntrospectionException is thrown if an exception occurs during introspection. */ - public BeanInfo getBeanInfo(Class clazz) throws IntrospectionException { + public BeanInfo getBeanInfo(Class clazz) throws IntrospectionException { synchronized (beanInfoCache) { BeanInfo beanInfo = beanInfoCache.get(clazz); if (beanInfo == null) { @@ -787,22 +792,30 @@ public class OgnlUtil { } } - protected Map createDefaultContext(Object root) { + protected Map createDefaultContext(Object root) { return createDefaultContext(root, null); } - protected Map createDefaultContext(Object root, ClassResolver classResolver) { + protected Map createDefaultContext(Object root, ClassResolver classResolver) { ClassResolver resolver = classResolver; if (resolver == null) { resolver = container.getInstance(CompoundRootAccessor.class); } SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess); - memberAccess.setExcludedClasses(excludedClasses); - memberAccess.setExcludedPackageNamePatterns(excludedPackageNamePatterns); - memberAccess.setExcludedPackageNames(excludedPackageNames); memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess); + if (devMode) { + LOG.warn("Working in devMode, using devMode excluded classes and packages!"); + memberAccess.setExcludedClasses(devModeExcludedClasses); + memberAccess.setExcludedPackageNamePatterns(devModeExcludedPackageNamePatterns); + memberAccess.setExcludedPackageNames(devModeExcludedPackageNames); + } else { + memberAccess.setExcludedClasses(excludedClasses); + memberAccess.setExcludedPackageNamePatterns(excludedPackageNamePatterns); + memberAccess.setExcludedPackageNames(excludedPackageNames); + } + return Ognl.createDefaultContext(root, memberAccess, resolver, defaultConverter); } diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index 2d1209548..a55ed6282 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -319,6 +319,11 @@ public final class StrutsConstants { public static final String STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS = "struts.excludedPackageNamePatterns"; public static final String STRUTS_EXCLUDED_PACKAGE_NAMES = "struts.excludedPackageNames"; + /** Comma delimited set of excluded classes and package names which cannot be accessed via expressions in devMode */ + public static final String STRUTS_DEV_MODE_EXCLUDED_CLASSES = "struts.devMode.excludedClasses"; + public static final String STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS = "struts.devMode.excludedPackageNamePatterns"; + public static final String STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES = "struts.devMode.excludedPackageNames"; + /** Dedicated services to check if passed string is excluded/accepted */ public static final String STRUTS_EXCLUDED_PATTERNS_CHECKER = "struts.excludedPatterns.checker"; public static final String STRUTS_ACCEPTED_PATTERNS_CHECKER = "struts.acceptedPatterns.checker"; diff --git a/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java b/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java index 904296ff9..bb648ec92 100644 --- a/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java +++ b/core/src/main/java/org/apache/struts2/config/entities/ConstantConfig.java @@ -129,6 +129,9 @@ public class ConstantConfig { private Set> excludedClasses; private List excludedPackageNamePatterns; private Set excludedPackageNames; + private Set> devModeExcludedClasses; + private List devModeExcludedPackageNamePatterns; + private Set devModeExcludedPackageNames; private BeanConfig excludedPatternsChecker; private BeanConfig acceptedPatternsChecker; private Set overrideExcludedPatterns; @@ -149,7 +152,7 @@ public class ConstantConfig { private String classesToString(Set> classes) { List list = null; if (classes != null && !classes.isEmpty()) { - list = new ArrayList(); + list = new ArrayList<>(); for (Class c : classes) { list.add(c.getName()); } @@ -257,6 +260,9 @@ public class ConstantConfig { map.put(StrutsConstants.STRUTS_EXCLUDED_CLASSES, classesToString(excludedClasses)); map.put(StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS, StringUtils.join(excludedPackageNamePatterns, ',')); map.put(StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAMES, StringUtils.join(excludedPackageNames, ',')); + map.put(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, classesToString(devModeExcludedClasses)); + map.put(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, StringUtils.join(devModeExcludedPackageNamePatterns, ',')); + map.put(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, StringUtils.join(devModeExcludedPackageNames, ',')); map.put(StrutsConstants.STRUTS_EXCLUDED_PATTERNS_CHECKER, beanConfToString(excludedPatternsChecker)); map.put(StrutsConstants.STRUTS_ACCEPTED_PATTERNS_CHECKER, beanConfToString(acceptedPatternsChecker)); map.put(StrutsConstants.STRUTS_OVERRIDE_EXCLUDED_PATTERNS, StringUtils.join(overrideExcludedPatterns, ',')); @@ -1209,6 +1215,30 @@ public class ConstantConfig { this.excludedPackageNames = excludedPackageNames; } + public Set> getDevModeExcludedClasses() { + return devModeExcludedClasses; + } + + public void setDevModeExcludedClasses(Set> devModeExcludedClasses) { + this.devModeExcludedClasses = devModeExcludedClasses; + } + + public List getDevModeExcludedPackageNamePatterns() { + return devModeExcludedPackageNamePatterns; + } + + public void setDevModeExcludedPackageNamePatterns(List devModeExcludedPackageNamePatterns) { + this.devModeExcludedPackageNamePatterns = devModeExcludedPackageNamePatterns; + } + + public Set getDevModeExcludedPackageNames() { + return devModeExcludedPackageNames; + } + + public void setDevModeExcludedPackageNames(Set devModeExcludedPackageNames) { + this.devModeExcludedPackageNames = devModeExcludedPackageNames; + } + public BeanConfig getExcludedPatternsChecker() { return excludedPatternsChecker; } diff --git a/core/src/main/java/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.java index 7e995f8fe..10fdcf4df 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.java @@ -43,7 +43,12 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Array; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; /** * @@ -65,8 +70,8 @@ import java.util.*; * the 'xml' mode is inserted at the top of the page. *
  • command - Tests an OGNL expression and returns the * string result. Only used by the OGNL console.
  • - *
  • browser Shows field values of an object specified in the - * object parameter (#context by default). When the object + *
  • browser Shows field values of an object specified in the + * object parameter (action by default). When the object * parameters is set, the '#' character needs to be escaped to '%23'. Like * debug=browser&object=%23parameters
  • * @@ -93,9 +98,9 @@ public class DebuggingInterceptor extends AbstractInterceptor { private final static Logger LOG = LogManager.getLogger(DebuggingInterceptor.class); private String[] ignorePrefixes = new String[]{"org.apache.struts.", - "com.opensymphony.xwork2.", "xwork."}; + "com.opensymphony.xwork2.", "xwork."}; private String[] _ignoreKeys = new String[]{"application", "session", - "parameters", "request"}; + "parameters", "request"}; private HashSet ignoreKeys = new HashSet<>(Arrays.asList(_ignoreKeys)); private final static String XML_MODE = "xml"; @@ -111,10 +116,10 @@ public class DebuggingInterceptor extends AbstractInterceptor { private final static String DECORATE_PARAM = "decorate"; private boolean enableXmlWithConsole = false; - + private boolean devMode; private FreemarkerManager freemarkerManager; - + private boolean consoleEnabled = false; private ReflectionProvider reflectionProvider; @@ -122,12 +127,12 @@ public class DebuggingInterceptor extends AbstractInterceptor { public void setDevMode(String mode) { this.devMode = "true".equals(mode); } - + @Inject public void setFreemarkerManager(FreemarkerManager mgr) { this.freemarkerManager = mgr; } - + @Inject public void setReflectionProvider(ReflectionProvider reflectionProvider) { this.reflectionProvider = reflectionProvider; @@ -149,40 +154,40 @@ public class DebuggingInterceptor extends AbstractInterceptor { ctx.getParameters().remove(DEBUG_PARAM); if (XML_MODE.equals(type)) { inv.addPreResultListener( - new PreResultListener() { - public void beforeResult(ActionInvocation inv, String result) { - printContext(); - } - }); + new PreResultListener() { + public void beforeResult(ActionInvocation inv, String result) { + printContext(); + } + }); } else if (CONSOLE_MODE.equals(type)) { consoleEnabled = true; inv.addPreResultListener( - new PreResultListener() { - public void beforeResult(ActionInvocation inv, String actionResult) { - String xml = ""; - if (enableXmlWithConsole) { - StringWriter writer = new StringWriter(); - printContext(new PrettyPrintWriter(writer)); - xml = writer.toString(); - xml = xml.replaceAll("&", "&"); - xml = xml.replaceAll(">", ">"); - xml = xml.replaceAll("<", "<"); - } - ActionContext.getContext().put("debugXML", xml); - - FreemarkerResult result = new FreemarkerResult(); - result.setFreemarkerManager(freemarkerManager); - result.setContentType("text/html"); - result.setLocation("/org/apache/struts2/interceptor/debugging/console.ftl"); - result.setParse(false); - try { - result.execute(inv); - } catch (Exception ex) { - LOG.error("Unable to create debugging console", ex); - } - + new PreResultListener() { + public void beforeResult(ActionInvocation inv, String actionResult) { + String xml = ""; + if (enableXmlWithConsole) { + StringWriter writer = new StringWriter(); + printContext(new PrettyPrintWriter(writer)); + xml = writer.toString(); + xml = xml.replaceAll("&", "&"); + xml = xml.replaceAll(">", ">"); + xml = xml.replaceAll("<", "<"); } - }); + ActionContext.getContext().put("debugXML", xml); + + FreemarkerResult result = new FreemarkerResult(); + result.setFreemarkerManager(freemarkerManager); + result.setContentType("text/html"); + result.setLocation("/org/apache/struts2/interceptor/debugging/console.ftl"); + result.setParse(false); + try { + result.execute(inv); + } catch (Exception ex) { + LOG.error("Unable to create debugging console", ex); + } + + } + }); } else if (COMMAND_MODE.equals(type)) { ValueStack stack = (ValueStack) ctx.getSession().get(SESSION_KEY); if (stack == null) { @@ -197,7 +202,7 @@ public class DebuggingInterceptor extends AbstractInterceptor { res.setContentType("text/plain"); try (PrintWriter writer = - ServletActionContext.getResponse().getWriter()) { + ServletActionContext.getResponse().getWriter()) { writer.print(stack.findValue(cmd)); } catch (IOException ex) { ex.printStackTrace(); @@ -209,25 +214,26 @@ public class DebuggingInterceptor extends AbstractInterceptor { new PreResultListener() { public void beforeResult(ActionInvocation inv, String actionResult) { String rootObjectExpression = getParameter(OBJECT_PARAM); - if (rootObjectExpression == null) - rootObjectExpression = "#context"; + if (rootObjectExpression == null) { + rootObjectExpression = "action"; + } String decorate = getParameter(DECORATE_PARAM); ValueStack stack = (ValueStack) ctx.get(ActionContext.VALUE_STACK); Object rootObject = stack.findValue(rootObjectExpression); - + try (StringWriter writer = new StringWriter()) { ObjectToHTMLWriter htmlWriter = new ObjectToHTMLWriter(writer); htmlWriter.write(reflectionProvider, rootObject, rootObjectExpression); String html = writer.toString(); writer.close(); - + stack.set("debugHtml", html); - + //on the first request, response can be decorated //but we need plain text on the other ones if ("false".equals(decorate)) ServletActionContext.getRequest().setAttribute("decorator", "none"); - + FreemarkerResult result = new FreemarkerResult(); result.setFreemarkerManager(freemarkerManager); result.setContentType("text/html"); @@ -240,7 +246,7 @@ public class DebuggingInterceptor extends AbstractInterceptor { } }); } - } + } if (cont) { try { if (actionOnly) { @@ -280,7 +286,7 @@ public class DebuggingInterceptor extends AbstractInterceptor { try { PrettyPrintWriter writer = new PrettyPrintWriter( - ServletActionContext.getResponse().getWriter()); + ServletActionContext.getResponse().getWriter()); printContext(writer); writer.close(); } catch (IOException ex) { @@ -421,10 +427,10 @@ public class DebuggingInterceptor extends AbstractInterceptor { private List filterValueStack(Map requestMap) { List filter = new ArrayList<>(); Object valueStack = requestMap.get("struts.valueStack"); - if(valueStack != null) { - filter.add(valueStack); - } - return filter; + if (valueStack != null) { + filter.add(valueStack); + } + return filter; } } diff --git a/core/src/main/java/org/apache/struts2/interceptor/debugging/ObjectToHTMLWriter.java b/core/src/main/java/org/apache/struts2/interceptor/debugging/ObjectToHTMLWriter.java index bad10b1e3..3374f737d 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/debugging/ObjectToHTMLWriter.java +++ b/core/src/main/java/org/apache/struts2/interceptor/debugging/ObjectToHTMLWriter.java @@ -20,6 +20,8 @@ package org.apache.struts2.interceptor.debugging; import com.opensymphony.xwork2.util.reflection.ReflectionException; import com.opensymphony.xwork2.util.reflection.ReflectionProvider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.beans.IntrospectionException; import java.io.Writer; @@ -33,6 +35,9 @@ import java.util.Set; * */ class ObjectToHTMLWriter { + + private static final Logger LOG = LogManager.getLogger(ObjectToHTMLWriter.class); + private PrettyPrintWriter prettyWriter; ObjectToHTMLWriter(Writer writer) { @@ -40,36 +45,43 @@ class ObjectToHTMLWriter { this.prettyWriter.setEscape(false); } - @SuppressWarnings("unchecked") public void write(ReflectionProvider reflectionProvider, Object root, String expr) throws IntrospectionException, ReflectionException { prettyWriter.startNode("table"); prettyWriter.addAttribute("class", "debugTable"); - if (root instanceof Map) { - for (Object next : ((Map) root).entrySet()) { - Map.Entry property = (Map.Entry) next; + if (root == null) { + LOG.info("Root is null"); + writeProperty("root", null, expr); + } else if (root instanceof Map) { + LOG.info("Root is a Map"); + for (Object next : ((Map) root).entrySet()) { + Map.Entry property = (Map.Entry) next; String key = property.getKey().toString(); Object value = property.getValue(); writeProperty(key, value, expr); } } else if (root instanceof List) { - List list = (List) root; + LOG.info("Root is a List"); + List list = (List) root; for (int i = 0; i < list.size(); i++) { Object element = list.get(i); writeProperty(String.valueOf(i), element, expr); } } else if (root instanceof Set) { - Set set = (Set) root; + LOG.info("Root is a Set"); + Set set = (Set) root; for (Object next : set) { writeProperty("", next, expr); } } else if (root.getClass().isArray()) { + LOG.info("Root is an Array"); Object[] objects = (Object[]) root; for (int i = 0; i < objects.length; i++) { writeProperty(String.valueOf(i), objects[i], expr); } } else { + LOG.info("Root is {}", root.getClass()); //print properties Map properties = reflectionProvider.getBeanMap(root); for (Map.Entry property : properties.entrySet()) { @@ -99,9 +111,9 @@ class ObjectToHTMLWriter { //value cell prettyWriter.startNode("td"); if (value != null) { + LOG.info("Writing property [{}] as [{}]", name, value); //if is is an empty collection or array, don't write a link - if (isEmptyCollection(value) || isEmptyMap(value) || (value.getClass() - .isArray() && ((Object[]) value).length == 0)) { + if (isEmptyCollection(value) || isEmptyMap(value) || (value.getClass().isArray() && ((Object[]) value).length == 0)) { prettyWriter.addAttribute("class", "emptyCollection"); prettyWriter.setValue("empty"); } else { @@ -118,7 +130,7 @@ class ObjectToHTMLWriter { prettyWriter.startNode("td"); if (value != null) { prettyWriter.addAttribute("class", "typeColumn"); - Class clazz = value.getClass(); + Class clazz = value.getClass(); prettyWriter.setValue(clazz.getName()); } else { prettyWriter.addAttribute("class", "nullValue"); @@ -135,7 +147,7 @@ class ObjectToHTMLWriter { */ private boolean isEmptyMap(Object value) { try { - return value instanceof Map && ((Map) value).isEmpty(); + return value instanceof Map && ((Map) value).isEmpty(); } catch (Exception e) { return true; } @@ -146,14 +158,14 @@ class ObjectToHTMLWriter { */ private boolean isEmptyCollection(Object value) { try { - return value instanceof Collection && ((Collection) value).isEmpty(); + return value instanceof Collection && ((Collection) value).isEmpty(); } catch (Exception e) { return true; } } private void writeValue(String name, Object value, String expr) { - Class clazz = value.getClass(); + Class clazz = value.getClass(); if (clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) || clazz.equals(String.class) || Boolean.class.equals(clazz)) { prettyWriter.setValue(String.valueOf(value)); diff --git a/core/src/main/resources/org/apache/struts2/interceptor/debugging/browser.ftl b/core/src/main/resources/org/apache/struts2/interceptor/debugging/browser.ftl index 6558608d8..f1dcbbf6b 100644 --- a/core/src/main/resources/org/apache/struts2/interceptor/debugging/browser.ftl +++ b/core/src/main/resources/org/apache/struts2/interceptor/debugging/browser.ftl @@ -86,6 +86,6 @@ - ${debugHtml} + ${debugHtml?no_esc} diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index 9da9daf76..0988d8794 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -48,9 +48,21 @@ sun.misc.Unsafe, com.opensymphony.xwork2.ActionContext" /> + + + + + diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java index ed6896a2c..707b0e566 100644 --- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java @@ -26,20 +26,42 @@ import com.opensymphony.xwork2.inject.ContainerBuilder; import com.opensymphony.xwork2.interceptor.ChainingInterceptor; import com.opensymphony.xwork2.test.StubConfigurationProvider; import com.opensymphony.xwork2.test.User; -import com.opensymphony.xwork2.util.*; +import com.opensymphony.xwork2.util.Bar; +import com.opensymphony.xwork2.util.CompoundRoot; +import com.opensymphony.xwork2.util.Foo; +import com.opensymphony.xwork2.util.Owner; +import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.location.LocatableProperties; import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import java.beans.IntrospectionException; -import ognl.*; +import ognl.InappropriateExpressionException; +import ognl.MethodFailedException; +import ognl.NoSuchPropertyException; +import ognl.NullHandler; +import ognl.Ognl; +import ognl.OgnlException; +import ognl.OgnlRuntime; +import ognl.SimpleNode; import org.apache.struts2.StrutsConstants; import org.apache.struts2.StrutsException; +import java.beans.IntrospectionException; import java.lang.reflect.Method; import java.text.DateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; public class OgnlUtilTest extends XWorkTestCase { + // Fields for static field access test public static final String STATIC_FINAL_PUBLIC_ATTRIBUTE = "Static_Final_Public_Attribute"; static final String STATIC_FINAL_PACKAGE_ATTRIBUTE = "Static_Final_Package_Attribute"; @@ -51,13 +73,13 @@ public class OgnlUtilTest extends XWorkTestCase { private static String STATIC_PRIVATE_ATTRIBUTE = "Static_Private_Attribute"; private OgnlUtil ognlUtil; - + @Override public void setUp() throws Exception { super.setUp(); ognlUtil = container.getInstance(OgnlUtil.class); } - + public void testCanSetADependentObject() { String dogName = "fido"; @@ -78,11 +100,11 @@ public class OgnlUtilTest extends XWorkTestCase { if (!getter.equals(name) || (method.getParameterTypes().length != 1)) { continue; } else { - Class clazz = method.getParameterTypes()[0]; + Class clazz = method.getParameterTypes()[0]; try { Object param = clazz.newInstance(); - method.invoke(o, new Object[]{param}); + method.invoke(o, param); return param; } catch (Exception e) { @@ -96,8 +118,8 @@ public class OgnlUtilTest extends XWorkTestCase { }); Owner owner = new Owner(); - Map context = ognlUtil.createDefaultContext(owner); - Map props = new HashMap(); + Map context = ognlUtil.createDefaultContext(owner); + Map props = new HashMap<>(); props.put("dog.name", dogName); ognlUtil.setProperties(props, owner, context); @@ -124,7 +146,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertTrue("Expression cache empty before clear ?", ognlUtil.expressionCacheSize() > 0); // Clear the Epxression cache and confirm subsequent requests are new. ognlUtil.clearExpressionCache(); - assertTrue("Expression cache not empty after clear ?", ognlUtil.expressionCacheSize() == 0); + assertEquals("Expression cache not empty after clear ?", 0, ognlUtil.expressionCacheSize()); Object expr3 = ognlUtil.compile("test"); Object expr4 = ognlUtil.compile("test"); Object expr5 = ognlUtil.compile("test"); @@ -157,7 +179,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertTrue("BeanInfo cache empty before clear ?", ognlUtil.beanInfoCacheSize() > 0); // Clear the BeanInfo cache and confirm subsequent requests are new. ognlUtil.clearBeanInfoCache(); - assertTrue("BeanInfo cache not empty after clear ?", ognlUtil.beanInfoCacheSize() == 0); + assertEquals("BeanInfo cache not empty after clear ?", 0, ognlUtil.beanInfoCacheSize()); Object beanInfo1_4 = ognlUtil.getBeanInfo(testBean1); Object beanInfo1_5 = ognlUtil.getBeanInfo(testBean1); Object beanInfo1_6 = ognlUtil.getBeanInfo(testBean1); @@ -190,7 +212,7 @@ public class OgnlUtilTest extends XWorkTestCase { OgnlUtil.clearRuntimeCache(); } - public void testCacheDisabled() throws OgnlException { + public void testCacheDisabled() throws OgnlException { ognlUtil.setEnableExpressionCache("false"); Object expr0 = ognlUtil.compile("test"); Object expr2 = ognlUtil.compile("test"); @@ -201,7 +223,7 @@ public class OgnlUtilTest extends XWorkTestCase { EmailAction action = new EmailAction(); Map context = ognlUtil.createDefaultContext(action); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("email[0].address", "addr1"); props.put("email[1].address", "addr2"); props.put("email[2].address", "addr3"); @@ -217,7 +239,7 @@ public class OgnlUtilTest extends XWorkTestCase { Foo foo1 = new Foo(); Foo foo2 = new Foo(); - Map context = ognlUtil.createDefaultContext(foo1); + Map context = ognlUtil.createDefaultContext(foo1); Calendar cal = Calendar.getInstance(); cal.clear(); @@ -265,7 +287,7 @@ public class OgnlUtilTest extends XWorkTestCase { Map context = ognlUtil.createDefaultContext(foo1); - List excludes = new ArrayList(); + List excludes = new ArrayList<>(); excludes.add("title"); excludes.add("number"); @@ -287,13 +309,13 @@ public class OgnlUtilTest extends XWorkTestCase { b1.setSomethingElse(10); - b1.setId(new Long(1)); + b1.setId(1L); b2.setTitle(""); - b2.setId(new Long(2)); + b2.setId(2L); context = ognlUtil.createDefaultContext(b1); - List includes = new ArrayList(); + List includes = new ArrayList<>(); includes.add("title"); includes.add("somethingElse"); @@ -364,7 +386,7 @@ public class OgnlUtilTest extends XWorkTestCase { Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("bar.title", "i am barbaz"); ognlUtil.setProperties(props, foo, context); @@ -372,8 +394,8 @@ public class OgnlUtilTest extends XWorkTestCase { } public void testNoExceptionForUnmatchedGetterAndSetterWithThrowPropertyException() { - Map props = new HashMap(); - props.put("myIntegerProperty", new Integer(1234)); + Map props = new HashMap<>(); + props.put("myIntegerProperty", 1234); TestObject testObject = new TestObject(); @@ -383,7 +405,7 @@ public class OgnlUtilTest extends XWorkTestCase { } public void testExceptionForWrongPropertyNameWithThrowPropertyException() { - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("myStringProperty", "testString"); TestObject testObject = new TestObject(); @@ -400,7 +422,7 @@ public class OgnlUtilTest extends XWorkTestCase { Foo foo = new Foo(); Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("aLong", "123a"); ognlUtil.setProperties(props, foo, context); @@ -421,7 +443,7 @@ public class OgnlUtilTest extends XWorkTestCase { stack.push(user); // indexed string w/ existing array - user.setList(new ArrayList()); + user.setList(new ArrayList<>()); user.getList().add(""); String[] foo = new String[]{"asdf"}; @@ -435,27 +457,27 @@ public class OgnlUtilTest extends XWorkTestCase { public void testSetPropertiesBoolean() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("useful", "true"); ognlUtil.setProperties(props, foo, context); - assertEquals(true, foo.isUseful()); + assertTrue(foo.isUseful()); - props = new HashMap(); + props = new HashMap<>(); props.put("useful", "false"); ognlUtil.setProperties(props, foo, context); - assertEquals(false, foo.isUseful()); + assertFalse(foo.isUseful()); } public void testSetPropertiesDate() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("birthday", "02/12/1982"); // US style test context.put(ActionContext.LOCALE, Locale.US); @@ -481,7 +503,7 @@ public class OgnlUtilTest extends XWorkTestCase { Date eventTime = cal.getTime(); String formatted = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, Locale.UK) - .format(eventTime); + .format(eventTime); props.put("event", formatted); cal = Calendar.getInstance(Locale.UK); @@ -494,7 +516,7 @@ public class OgnlUtilTest extends XWorkTestCase { Date meetingTime = cal.getTime(); formatted = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, Locale.UK) - .format(meetingTime); + .format(meetingTime); props.put("meeting", formatted); context.put(ActionContext.LOCALE, Locale.UK); @@ -504,12 +526,12 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(eventTime, foo.getEvent()); assertEquals(meetingTime, foo.getMeeting()); - + //test RFC 3339 date format for JSON props.put("event", "1996-12-19T16:39:57Z"); context.put(ActionContext.LOCALE, Locale.US); ognlUtil.setProperties(props, foo, context); - + cal = Calendar.getInstance(Locale.US); cal.clear(); cal.set(Calendar.MONTH, Calendar.DECEMBER); @@ -518,9 +540,9 @@ public class OgnlUtilTest extends XWorkTestCase { cal.set(Calendar.HOUR_OF_DAY, 16); cal.set(Calendar.MINUTE, 39); cal.set(Calendar.SECOND, 57); - + assertEquals(cal.getTime(), foo.getEvent()); - + //test setting a calendar property props.put("calendar", "1996-12-19T16:39:57Z"); context.put(ActionContext.LOCALE, Locale.US); @@ -531,9 +553,9 @@ public class OgnlUtilTest extends XWorkTestCase { public void testSetPropertiesInt() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("number", "2"); ognlUtil.setProperties(props, foo, context); @@ -543,9 +565,9 @@ public class OgnlUtilTest extends XWorkTestCase { public void testSetPropertiesLongArray() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("points", new String[]{"1", "2"}); ognlUtil.setProperties(props, foo, context); @@ -558,9 +580,9 @@ public class OgnlUtilTest extends XWorkTestCase { public void testSetPropertiesString() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("title", "this is a title"); ognlUtil.setProperties(props, foo, context); @@ -569,7 +591,7 @@ public class OgnlUtilTest extends XWorkTestCase { public void testSetProperty() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); assertFalse(123456 == foo.getNumber()); ognlUtil.setProperty("number", "123456", foo, context); assertEquals(123456, foo.getNumber()); @@ -580,14 +602,11 @@ public class OgnlUtilTest extends XWorkTestCase { ChainingInterceptor foo = new ChainingInterceptor(); ChainingInterceptor foo2 = new ChainingInterceptor(); - OgnlContext context = (OgnlContext) ognlUtil.createDefaultContext(null); + Map context = ognlUtil.createDefaultContext(null); SimpleNode expression = (SimpleNode) Ognl.parseExpression("{'a','ruby','b','tom'}"); - Ognl.getValue(expression, context, "aksdj"); - final ValueStack stack = ActionContext.getContext().getValueStack(); - Object result = Ognl.getValue(ognlUtil.compile("{\"foo\",'ruby','b','tom'}"), context, foo); foo.setIncludesCollection((Collection) result); @@ -622,9 +641,9 @@ public class OgnlUtilTest extends XWorkTestCase { public void testStringToLong() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("ALong", "123"); ognlUtil.setProperties(props, foo, context); @@ -641,52 +660,52 @@ public class OgnlUtilTest extends XWorkTestCase { Foo foo = new Foo(); foo.setALong(88); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); ognlUtil.setProperties(null, foo, context); assertEquals(88, foo.getALong()); - Map props = new HashMap(); + Map props = new HashMap<>(); props.put("ALong", "99"); ognlUtil.setProperties(props, foo, context); assertEquals(99, foo.getALong()); } - + public void testCopyNull() { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); - ognlUtil.copy(null, null, context); + Map context = ognlUtil.createDefaultContext(foo); + ognlUtil.copy(null, null, context); - ognlUtil.copy(foo, null, context); - ognlUtil.copy(null, foo, context); + ognlUtil.copy(foo, null, context); + ognlUtil.copy(null, foo, context); } - + public void testGetTopTarget() throws Exception { Foo foo = new Foo(); - Map context = ognlUtil.createDefaultContext(foo); + Map context = ognlUtil.createDefaultContext(foo); CompoundRoot root = new CompoundRoot(); Object top = ognlUtil.getRealTarget("top", context, root); assertEquals(root, top); // top should be root - + root.push(foo); Object val = ognlUtil.getRealTarget("unknown", context, root); assertNull(val); // not found } - + public void testGetBeanMap() throws Exception { - Bar bar = new Bar(); - bar.setTitle("I have beer"); - - Foo foo = new Foo(); + Bar bar = new Bar(); + bar.setTitle("I have beer"); + + Foo foo = new Foo(); foo.setALong(123); foo.setNumber(44); foo.setBar(bar); foo.setTitle("Hello Santa"); foo.setUseful(true); - + // just do some of the 15 tests - Map beans = ognlUtil.getBeanMap(foo); + Map beans = ognlUtil.getBeanMap(foo); assertNotNull(beans); assertEquals(22, beans.size()); assertEquals("Hello Santa", beans.get("title")); @@ -697,21 +716,21 @@ public class OgnlUtilTest extends XWorkTestCase { } public void testGetBeanMapNoReadMethod() throws Exception { - MyWriteBar bar = new MyWriteBar(); - bar.setBar("Sams"); - - Map beans = ognlUtil.getBeanMap(bar); - assertEquals(2, beans.size()); - assertEquals(new Integer("1"), beans.get("id")); - assertEquals("There is no read method for bar", beans.get("bar")); + MyWriteBar bar = new MyWriteBar(); + bar.setBar("Sams"); + + Map beans = ognlUtil.getBeanMap(bar); + assertEquals(2, beans.size()); + assertEquals(new Integer("1"), beans.get("id")); + assertEquals("There is no read method for bar", beans.get("bar")); } /** - * XW-281 - */ + * XW-281 + */ public void testSetBigIndexedValue() { ValueStack stack = ActionContext.getContext().getValueStack(); - Map stackContext = stack.getContext(); + Map stackContext = stack.getContext(); stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.FALSE); stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE); stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE); @@ -720,39 +739,33 @@ public class OgnlUtilTest extends XWorkTestCase { stack.push(user); // indexed string w/ existing array - user.setList(new ArrayList()); + user.setList(new ArrayList<>()); String[] foo = new String[]{"asdf"}; - ((OgnlValueStack)stack).setDevMode("true"); + ((OgnlValueStack) stack).setDevMode("true"); try { stack.setValue("list.1114778947765", foo); - fail("non-valid expression: list.1114778947765"); + fail("non-valid expression: list.1114778947765"); + } catch (RuntimeException ex) { + // it's oke } - catch(RuntimeException ex) { - ; // it's oke - } - + try { stack.setValue("1114778947765", foo); - fail("non-valid expression: 1114778947765"); + fail("non-valid expression: 1114778947765"); + } catch (RuntimeException ignore) { } - catch(RuntimeException ex) { - ; - } - + try { stack.setValue("1234", foo); fail("non-valid expression: 1234"); + } catch (RuntimeException ignore) { } - catch(RuntimeException ex) { - ; - } - - ((OgnlValueStack)stack).setDevMode("false"); + + ((OgnlValueStack) stack).setDevMode("false"); try { reloadTestContainerConfiguration(false, false); // Set dev mode false (above set now refused) - } - catch (Exception ex) { + } catch (Exception ex) { fail("Unable to reload container configuration - exception: " + ex); } @@ -768,17 +781,16 @@ public class OgnlUtilTest extends XWorkTestCase { stack.setValue("1234", foo); } - public void testStackValueDevModeChange() throws Exception { + public void testStackValueDevModeChange() { try { reloadTestContainerConfiguration(false, false); // Set dev mode false - } - catch (Exception ex) { + } catch (Exception ex) { fail("Unable to reload container configuration - exception: " + ex); } ValueStack stack = ActionContext.getContext().getValueStack(); - Map stackContext = stack.getContext(); + Map stackContext = stack.getContext(); stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.FALSE); stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE); stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE); @@ -792,8 +804,7 @@ public class OgnlUtilTest extends XWorkTestCase { try { reloadTestContainerConfiguration(true, false); // Set dev mode true - } - catch (Exception ex) { + } catch (Exception ex) { fail("Unable to reload container configuration - exception: " + ex); } @@ -807,38 +818,34 @@ public class OgnlUtilTest extends XWorkTestCase { try { stack.setValue("list.1114778947765", foo); fail("non-valid expression: list.1114778947765"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } try { stack.setValue("1114778947765", foo); fail("non-valid expression: 1114778947765"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } try { stack.setValue("1234", foo); fail("non-valid expression: 1234"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } } - public void testDevModeChange() throws Exception { + public void testDevModeChange() { try { reloadTestContainerConfiguration(false, false); // Set dev mode false - } - catch (Exception ex) { + } catch (Exception ex) { fail("Unable to reload container configuration - exception: " + ex); } ValueStack stack = ActionContext.getContext().getValueStack(); - Map stackContext = stack.getContext(); + Map stackContext = stack.getContext(); stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.FALSE); stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE); stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE); @@ -852,8 +859,7 @@ public class OgnlUtilTest extends XWorkTestCase { try { reloadTestContainerConfiguration(true, false); // Set dev mode true - } - catch (Exception ex) { + } catch (Exception ex) { fail("Unable to reload container configuration - exception: " + ex); } @@ -867,28 +873,25 @@ public class OgnlUtilTest extends XWorkTestCase { try { stack.setValue("list.1114778947765", foo); fail("non-valid expression: list.1114778947765"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } try { stack.setValue("1114778947765", foo); fail("non-valid expression: 1114778947765"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } try { stack.setValue("1234", foo); fail("non-valid expression: 1234"); - } - catch(RuntimeException ex) { + } catch (RuntimeException ex) { // Expected with dev mode true } } - public void testAvoidCallingMethodsOnObjectClass() throws Exception { + public void testAvoidCallingMethodsOnObjectClass() { Foo foo = new Foo(); Exception expected = null; @@ -904,7 +907,41 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("com.opensymphony.xwork2.util.Foo.class", expected.getMessage()); } - public void testAvoidCallingMethodsOnObjectClassUpperCased() throws Exception { + public void testAllowCallingMethodsOnObjectClassInDevModeTrue() { + Exception expected = null; + try { + ognlUtil.setExcludedClasses(Foo.class.getName()); + ognlUtil.setDevModeExcludedClasses(""); + ognlUtil.setDevMode(Boolean.TRUE.toString()); + + Foo foo = new Foo(); + String result = (String) ognlUtil.getValue("toString", ognlUtil.createDefaultContext(foo), foo, String.class); + assertEquals("Foo", result); + } catch (OgnlException e) { + expected = e; + } + assertNull(expected); + } + + public void testAllowCallingMethodsOnObjectClassInDevModeFalse() { + Exception expected = null; + try { + ognlUtil.setExcludedClasses(Foo.class.getName()); + ognlUtil.setDevModeExcludedClasses(""); + ognlUtil.setDevMode(Boolean.FALSE.toString()); + + Foo foo = new Foo(); + String result = (String) ognlUtil.getValue("toString", ognlUtil.createDefaultContext(foo), foo, String.class); + assertEquals("Foo", result); + } catch (OgnlException e) { + expected = e; + } + assertNotNull(expected); + assertSame(NoSuchPropertyException.class, expected.getClass()); + assertEquals("com.opensymphony.xwork2.util.Foo.toString", expected.getMessage()); + } + + public void testAvoidCallingMethodsOnObjectClassUpperCased() { Foo foo = new Foo(); Exception expected = null; @@ -920,7 +957,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("com.opensymphony.xwork2.util.Foo.Class", expected.getMessage()); } - public void testAvoidCallingMethodsOnObjectClassAsMap() throws Exception { + public void testAvoidCallingMethodsOnObjectClassAsMap() { Foo foo = new Foo(); Exception expected = null; @@ -936,7 +973,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("com.opensymphony.xwork2.util.Foo.class", expected.getMessage()); } - public void testAvoidCallingMethodsOnObjectClassAsMap2() throws Exception { + public void testAvoidCallingMethodsOnObjectClassAsMap2() { Foo foo = new Foo(); Exception expected = null; @@ -951,7 +988,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("com.opensymphony.xwork2.util.Foo.foo", expected.getMessage()); } - public void testAvoidCallingMethodsOnObjectClassAsMapWithQuotes() throws Exception { + public void testAvoidCallingMethodsOnObjectClassAsMapWithQuotes() { Foo foo = new Foo(); Exception expected = null; @@ -967,7 +1004,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("com.opensymphony.xwork2.util.Foo.class", expected.getMessage()); } - public void testAvoidCallingToString() throws Exception { + public void testAvoidCallingToString() { Foo foo = new Foo(); Exception expected = null; @@ -982,7 +1019,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals("toString", expected.getMessage()); } - public void testAvoidCallingMethodsWithBraces() throws Exception { + public void testAvoidCallingMethodsWithBraces() { Foo foo = new Foo(); Exception expected = null; @@ -997,7 +1034,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(expected.getMessage(), "Inappropriate OGNL expression: toString()"); } - public void testAvoidCallingSomeClasses() throws Exception { + public void testAvoidCallingSomeClasses() { Foo foo = new Foo(); Exception expected = null; @@ -1013,7 +1050,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(expected.getMessage(), "Method \"getRuntime\" failed for object class java.lang.Runtime"); } - public void testBlockSequenceOfExpressions() throws Exception { + public void testBlockSequenceOfExpressions() { Foo foo = new Foo(); Exception expected = null; @@ -1028,7 +1065,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(expected.getMessage(), "Eval expressions/chained expressions have been disabled!"); } - public void testCallMethod() throws Exception { + public void testCallMethod() { Foo foo = new Foo(); Exception expected = null; @@ -1043,37 +1080,36 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(expected.getMessage(), "It isn't a simple method which can be called!"); } - public void testXworkTestCaseOgnlUtilExclusions() throws Exception { + public void testXworkTestCaseOgnlUtilExclusions() { internalTestInitialEmptyOgnlUtilExclusions(ognlUtil); internalTestOgnlUtilExclusionsImmutable(ognlUtil); } - public void testDefaultOgnlUtilExclusions() throws Exception { + public void testDefaultOgnlUtilExclusions() { OgnlUtil basicOgnlUtil = new OgnlUtil(); internalTestInitialEmptyOgnlUtilExclusions(basicOgnlUtil); internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil); } - public void testOgnlUtilExcludedAdditivity() throws Exception { + public void testOgnlUtilExcludedAdditivity() { Set> excludedClasses; Set excludedPackageNamePatterns; Iterator excludedPackageNamePatternsIterator; Set excludedPackageNames; - Set patternStrings = new HashSet<>(); ognlUtil.setExcludedClasses("java.lang.String,java.lang.Integer"); internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedClasses = ognlUtil.getExcludedClasses(); - assertNotNull("initial exluded classes null?", excludedClasses); - assertTrue("initial exluded classes size not 2 after adds?", excludedClasses.size() == 2); + assertNotNull("initial excluded classes null?", excludedClasses); + assertEquals("initial excluded classes size not 2 after adds?", 2, excludedClasses.size()); assertTrue("String not in exclusions?", excludedClasses.contains(String.class)); assertTrue("Integer not in exclusions?", excludedClasses.contains(Integer.class)); ognlUtil.setExcludedClasses("java.lang.Boolean,java.lang.Double"); internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedClasses = ognlUtil.getExcludedClasses(); - assertNotNull("updated exluded classes null?", excludedClasses); - assertTrue("updated exluded classes size not 4 after adds?", excludedClasses.size() == 4); + assertNotNull("updated excluded classes null?", excludedClasses); + assertEquals("updated excluded classes size not 4 after adds?", 4, excludedClasses.size()); assertTrue("String not in exclusions?", excludedClasses.contains(String.class)); assertTrue("Integer not in exclusions?", excludedClasses.contains(Integer.class)); assertTrue("String not in exclusions?", excludedClasses.contains(Boolean.class)); @@ -1082,10 +1118,10 @@ public class OgnlUtilTest extends XWorkTestCase { ognlUtil.setExcludedPackageNamePatterns("fakepackage1.*,fakepackage2.*"); internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedPackageNamePatterns = ognlUtil.getExcludedPackageNamePatterns(); - assertNotNull("initial exluded package name patterns null?", excludedPackageNamePatterns); - assertTrue("initial exluded package name patterns size not 2 after adds?", excludedPackageNamePatterns.size() == 2); + assertNotNull("initial excluded package name patterns null?", excludedPackageNamePatterns); + assertEquals("initial excluded package name patterns size not 2 after adds?", 2, excludedPackageNamePatterns.size()); excludedPackageNamePatternsIterator = excludedPackageNamePatterns.iterator(); - patternStrings.clear(); + Set patternStrings = new HashSet<>(); while (excludedPackageNamePatternsIterator.hasNext()) { Pattern pattern = excludedPackageNamePatternsIterator.next(); patternStrings.add(pattern.pattern()); @@ -1095,10 +1131,10 @@ public class OgnlUtilTest extends XWorkTestCase { ognlUtil.setExcludedPackageNamePatterns("fakepackage3.*,fakepackage4.*"); internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedPackageNamePatterns = ognlUtil.getExcludedPackageNamePatterns(); - assertNotNull("updated exluded package name patterns null?", excludedPackageNamePatterns); - assertTrue("updated exluded package name patterns size not 4 after adds?", excludedPackageNamePatterns.size() == 4); + assertNotNull("updated excluded package name patterns null?", excludedPackageNamePatterns); + assertEquals("updated excluded package name patterns size not 4 after adds?", 4, excludedPackageNamePatterns.size()); excludedPackageNamePatternsIterator = excludedPackageNamePatterns.iterator(); - patternStrings.clear(); + patternStrings = new HashSet<>(); while (excludedPackageNamePatternsIterator.hasNext()) { Pattern pattern = excludedPackageNamePatternsIterator.next(); patternStrings.add(pattern.pattern()); @@ -1112,14 +1148,14 @@ public class OgnlUtilTest extends XWorkTestCase { internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedPackageNames = ognlUtil.getExcludedPackageNames(); assertNotNull("initial exluded package names null?", excludedPackageNames); - assertTrue("initial exluded package names not 2 after adds?", excludedPackageNames.size() == 2); + assertEquals("initial exluded package names not 2 after adds?", 2, excludedPackageNames.size()); assertTrue("fakepackage1.package not in exclusions?", excludedPackageNames.contains("fakepackage1.package")); assertTrue("fakepackage2.package not in exclusions?", excludedPackageNames.contains("fakepackage2.package")); ognlUtil.setExcludedPackageNames("fakepackage3.package,fakepackage4.package"); internalTestOgnlUtilExclusionsImmutable(ognlUtil); excludedPackageNames = ognlUtil.getExcludedPackageNames(); assertNotNull("updated exluded package names null?", excludedPackageNames); - assertTrue("updated exluded package names not 4 after adds?", excludedPackageNames.size() == 4); + assertEquals("updated exluded package names not 4 after adds?", 4, excludedPackageNames.size()); assertTrue("fakepackage1.package not in exclusions?", excludedPackageNames.contains("fakepackage1.package")); assertTrue("fakepackage2.package not in exclusions?", excludedPackageNames.contains("fakepackage2.package")); assertTrue("fakepackage3.package not in exclusions?", excludedPackageNames.contains("fakepackage3.package")); @@ -1128,17 +1164,17 @@ public class OgnlUtilTest extends XWorkTestCase { /** * Ensure getValue: - * 1) When allowStaticFieldAccess true - Permits public static field access, - * prevents non-public static field access. - * 2) When allowStaticFieldAccess false - blocks all static field access, + * 1) When allowStaticFieldAccess true - Permits public static field access, + * prevents non-public static field access. + * 2) When allowStaticFieldAccess false - blocks all static field access, */ public void testStaticFieldGetValue() { - OgnlContext context = null; + Map context = null; Object accessedValue; try { reloadTestContainerConfiguration(true); // Test with allowStaticFieldAccess true - context = (OgnlContext) ognlUtil.createDefaultContext(null); + context = ognlUtil.createDefaultContext(null); } catch (Exception ex) { fail("unable to reload test configuration? Exception: " + ex); } @@ -1155,37 +1191,37 @@ public class OgnlUtilTest extends XWorkTestCase { fail("static public field access failed ? Exception: " + ex); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); fail("static final package field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); fail("static package field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); fail("static final protected field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); fail("static protected field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); fail("static final private field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); fail("static private field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); @@ -1193,54 +1229,54 @@ public class OgnlUtilTest extends XWorkTestCase { try { reloadTestContainerConfiguration(false); // Re-test with allowStaticFieldAccess false - context = (OgnlContext) ognlUtil.createDefaultContext(null); + context = ognlUtil.createDefaultContext(null); } catch (Exception ex) { fail("unable to reload test configuration? Exception: " + ex); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null); fail("static final public field access succeded ?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null); fail("static public field access succeded ?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); fail("static final package field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); fail("static package field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); fail("static final protected field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); fail("static protected field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); fail("static final private field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); } try { - accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); + ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); fail("static private field access succeeded?"); } catch (Exception ex) { assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); @@ -1249,7 +1285,7 @@ public class OgnlUtilTest extends XWorkTestCase { /** * Test OGNL Expression Max Length feature setting via OgnlUtil is disabled by default (in default.properties). - * + * * @since 2.5.21 */ public void testDefaultExpressionMaxLengthDisabled() { @@ -1258,19 +1294,19 @@ public class OgnlUtilTest extends XWorkTestCase { Object compileResult = ognlUtil.compile(LONG_OGNL_EXPRESSION); assertNotNull("Long OGNL expression compilation produced a null result ?", compileResult); } catch (OgnlException oex) { - if (oex.getReason() instanceof SecurityException) { - fail ("Unable to compile expression (unexpected). 'struts.ognl.expressionMaxLength' may have accidentally been enabled by default. Exception: " + oex); - } else { - fail ("Unable to compile expression (unexpected). Exception: " + oex); - } + if (oex.getReason() instanceof SecurityException) { + fail("Unable to compile expression (unexpected). 'struts.ognl.expressionMaxLength' may have accidentally been enabled by default. Exception: " + oex); + } else { + fail("Unable to compile expression (unexpected). Exception: " + oex); + } } catch (Exception ex) { - fail ("Unable to compile expression (unexpected). Exception: " + ex); + fail("Unable to compile expression (unexpected). Exception: " + ex); } } /** * Test OGNL Expression Max Length feature setting via OgnlUtil. - * + * * @since 2.5.21 */ public void testApplyExpressionMaxLength() { @@ -1278,28 +1314,28 @@ public class OgnlUtilTest extends XWorkTestCase { try { ognlUtil.applyExpressionMaxLength(null); } catch (Exception ex) { - fail ("applyExpressionMaxLength did not accept null maxlength string (disable feature) ?"); + fail("applyExpressionMaxLength did not accept null maxlength string (disable feature) ?"); } try { ognlUtil.applyExpressionMaxLength(""); } catch (Exception ex) { - fail ("applyExpressionMaxLength did not accept empty maxlength string (disable feature) ?"); + fail("applyExpressionMaxLength did not accept empty maxlength string (disable feature) ?"); } try { ognlUtil.applyExpressionMaxLength("-1"); - fail ("applyExpressionMaxLength accepted negative maxlength string ?"); + fail("applyExpressionMaxLength accepted negative maxlength string ?"); } catch (IllegalArgumentException iae) { // Expected rejection of -ive length. } try { ognlUtil.applyExpressionMaxLength("0"); } catch (Exception ex) { - fail ("applyExpressionMaxLength did not accept maxlength string 0 ?"); + fail("applyExpressionMaxLength did not accept maxlength string 0 ?"); } try { ognlUtil.applyExpressionMaxLength(Integer.toString(Integer.MAX_VALUE, 10)); } catch (Exception ex) { - fail ("applyExpressionMaxLength did not accept MAX_VALUE maxlength string ?"); + fail("applyExpressionMaxLength did not accept MAX_VALUE maxlength string ?"); } } finally { // Reset expressionMaxLength value to default (disabled) @@ -1307,7 +1343,7 @@ public class OgnlUtilTest extends XWorkTestCase { } } - private void internalTestInitialEmptyOgnlUtilExclusions(OgnlUtil ognlUtilParam) throws Exception { + private void internalTestInitialEmptyOgnlUtilExclusions(OgnlUtil ognlUtilParam) { Set> excludedClasses = ognlUtilParam.getExcludedClasses(); assertNotNull("parameter (default) exluded classes null?", excludedClasses); assertTrue("parameter (default) exluded classes not empty?", excludedClasses.isEmpty()); @@ -1321,7 +1357,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertTrue("parameter (default) exluded package names not empty?", excludedPackageNames.isEmpty()); } - private void internalTestOgnlUtilExclusionsImmutable(OgnlUtil ognlUtilParam) throws Exception { + private void internalTestOgnlUtilExclusionsImmutable(OgnlUtil ognlUtilParam) { Pattern somePattern = Pattern.compile("SomeRegexPattern"); Set> excludedClasses = ognlUtilParam.getExcludedClasses(); assertNotNull("parameter exluded classes null?", excludedClasses); @@ -1406,18 +1442,17 @@ public class OgnlUtilTest extends XWorkTestCase { } public void testGetExcludedPackageNames() { - // Getter should return an immutable collection - OgnlUtil util = new OgnlUtil(); - util.setExcludedPackageNames("java.lang,java.awt"); - assertEquals(util.getExcludedPackageNames().size(), 2); - try { - util.getExcludedPackageNames().clear(); - } - catch (Exception ex) { - assertTrue(ex instanceof UnsupportedOperationException); - } finally { - assertEquals(util.getExcludedPackageNames().size(), 2); - } + // Getter should return an immutable collection + OgnlUtil util = new OgnlUtil(); + util.setExcludedPackageNames("java.lang,java.awt"); + assertEquals(util.getExcludedPackageNames().size(), 2); + try { + util.getExcludedPackageNames().clear(); + } catch (Exception ex) { + assertTrue(ex instanceof UnsupportedOperationException); + } finally { + assertEquals(util.getExcludedPackageNames().size(), 2); + } } public void testGetExcludedClasses() { @@ -1427,8 +1462,7 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(util.getExcludedClasses().size(), 3); try { util.getExcludedClasses().clear(); - } - catch (Exception ex) { + } catch (Exception ex) { assertTrue(ex instanceof UnsupportedOperationException); } finally { assertEquals(util.getExcludedClasses().size(), 3); @@ -1442,15 +1476,14 @@ public class OgnlUtilTest extends XWorkTestCase { assertEquals(util.getExcludedPackageNamePatterns().size(), 1); try { util.getExcludedPackageNamePatterns().clear(); - } - catch (Exception ex) { + } catch (Exception ex) { assertTrue(ex instanceof UnsupportedOperationException); } finally { assertEquals(util.getExcludedPackageNamePatterns().size(), 1); } } - private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticMethod) throws Exception { + private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticMethod) { loadConfigurationProviders(new StubConfigurationProvider() { @Override public void register(ContainerBuilder builder, @@ -1462,7 +1495,7 @@ public class OgnlUtilTest extends XWorkTestCase { ognlUtil = container.getInstance(OgnlUtil.class); } - private void reloadTestContainerConfiguration(boolean allowStaticField) throws Exception { + private void reloadTestContainerConfiguration(boolean allowStaticField) { loadConfigurationProviders(new StubConfigurationProvider() { @Override public void register(ContainerBuilder builder, @@ -1516,23 +1549,23 @@ public class OgnlUtilTest extends XWorkTestCase { } } - class EmailAction { - public List email = new OgnlList(Email.class); + static class EmailAction { + public List email = new OgnlList<>(Email.class); - public List getEmail() { + public List getEmail() { return this.email; } } - class OgnlList extends ArrayList { - private Class clazz; + static class OgnlList extends ArrayList { + private Class clazz; - public OgnlList(Class clazz) { + public OgnlList(Class clazz) { this.clazz = clazz; } @Override - public synchronized Object get(int index) { + public synchronized T get(int index) { while (index >= this.size()) { try { this.add(clazz.newInstance()); @@ -1544,24 +1577,24 @@ public class OgnlUtilTest extends XWorkTestCase { return super.get(index); } } - - private class MyWriteBar { - private int id; - - public int getId() { - return id; - } - - public void setBar(String name) { - if ("Sams".equals(name)) - id = 1; - else - id = 999; - } - + + private static class MyWriteBar { + private int id; + + public int getId() { + return id; + } + + public void setBar(String name) { + if ("Sams".equals(name)) + id = 1; + else + id = 999; + } + } - class TestBean1 { + static class TestBean1 { private String testBeanProperty; public TestBean1() { @@ -1577,7 +1610,7 @@ public class OgnlUtilTest extends XWorkTestCase { } } - class TestBean2 { + static class TestBean2 { private String testBeanProperty; public TestBean2() { diff --git a/core/src/test/java/com/opensymphony/xwork2/util/Foo.java b/core/src/test/java/com/opensymphony/xwork2/util/Foo.java index f8b67c71a..80fb9c84f 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/Foo.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/Foo.java @@ -252,4 +252,9 @@ public class Foo { public void setAnimalMap(Map animalMap) { this.animalMap = animalMap; } + + @Override + public String toString() { + return "Foo"; + } } diff --git a/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java b/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java index 00421d4ca..01503dd42 100644 --- a/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java +++ b/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java @@ -18,6 +18,13 @@ */ package org.apache.struts2.config.entities; +import com.opensymphony.xwork2.TestBean; +import com.opensymphony.xwork2.inject.Container; +import org.apache.struts2.StrutsConstants; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; @@ -25,20 +32,14 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import org.apache.struts2.StrutsConstants; -import org.junit.Assert; -import org.junit.Test; - -import com.opensymphony.xwork2.TestBean; -import com.opensymphony.xwork2.inject.Container; - public class ConstantConfigTest { + @Test - public void testBeanConfToString() throws Exception { + public void testBeanConfToString() { ConstantConfig constantConfig = new ConstantConfig(); String actual = constantConfig.beanConfToString(null); - Assert.assertEquals(null, actual); + Assert.assertNull(actual); actual = constantConfig.beanConfToString(new BeanConfig(TestBean.class)); Assert.assertEquals(Container.DEFAULT_NAME, actual); @@ -49,7 +50,7 @@ public class ConstantConfigTest { } @Test - public void testGetAllAsStringsMap() throws Exception { + public void testGetAllAsStringsMap() { ConstantConfig constantConfig = new ConstantConfig(); boolean expectedDevMode = true; @@ -65,22 +66,32 @@ public class ConstantConfigTest { Assert.assertEquals(String.valueOf(expectedDevMode), map.get(StrutsConstants.STRUTS_DEVMODE)); Assert.assertEquals(expectedActionExtensions, map.get(StrutsConstants.STRUTS_ACTION_EXTENSION)); - Assert.assertEquals(null, map.get(StrutsConstants.STRUTS_I18N_RELOAD)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_I18N_RELOAD)); Assert.assertEquals(expectedLanguage, map.get(StrutsConstants.STRUTS_LOCALE)); } @Test - public void testEmptyClassesToString() throws Exception { + public void testEmptyClassesToString() { ConstantConfig constantConfig = new ConstantConfig(); - constantConfig.setExcludedClasses(new HashSet>()); + constantConfig.setExcludedClasses(null); + constantConfig.setExcludedPackageNamePatterns(null); + constantConfig.setExcludedPackageNames(null); + constantConfig.setDevModeExcludedClasses(null); + constantConfig.setDevModeExcludedPackageNamePatterns(null); + constantConfig.setDevModeExcludedPackageNames(null); Map map = constantConfig.getAllAsStringsMap(); - Assert.assertEquals(null, map.get(StrutsConstants.STRUTS_EXCLUDED_CLASSES)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_EXCLUDED_CLASSES)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAMES)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS)); + Assert.assertNull(map.get(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES)); } @Test - public void testClassesToString() throws Exception { + public void testClassesToString() { ConstantConfig constantConfig = new ConstantConfig(); Set> excludedClasses = new LinkedHashSet<>(); @@ -89,9 +100,13 @@ public class ConstantConfigTest { excludedClasses.add(System.class); constantConfig.setExcludedClasses(excludedClasses); + constantConfig.setDevModeExcludedClasses(excludedClasses); Map map = constantConfig.getAllAsStringsMap(); Assert.assertEquals("java.lang.Object,java.lang.Runtime,java.lang.System", - map.get(StrutsConstants.STRUTS_EXCLUDED_CLASSES)); + map.get(StrutsConstants.STRUTS_EXCLUDED_CLASSES)); + Assert.assertEquals("java.lang.Object,java.lang.Runtime,java.lang.System", + map.get(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES)); } + } diff --git a/plugins/config-browser/src/main/resources/config-browser/actionNames.ftl b/plugins/config-browser/src/main/resources/config-browser/actionNames.ftl index 54a556599..226f2a537 100644 --- a/plugins/config-browser/src/main/resources/config-browser/actionNames.ftl +++ b/plugins/config-browser/src/main/resources/config-browser/actionNames.ftl @@ -26,7 +26,7 @@
      <#list actionNames as name> - <@s.url var="showConfig" action="showConfig" includeParams="none"> + <@s.url var="showConfig" action="showConfig" includeParams="none" escapeAmp="false"> <@s.param name="namespace">${namespace} <@s.param name="actionName">${name} diff --git a/plugins/config-browser/src/main/resources/config-browser/showConfig.ftl b/plugins/config-browser/src/main/resources/config-browser/showConfig.ftl index 7daff4702..1c4354e3b 100644 --- a/plugins/config-browser/src/main/resources/config-browser/showConfig.ftl +++ b/plugins/config-browser/src/main/resources/config-browser/showConfig.ftl @@ -39,11 +39,11 @@ -<@s.url var="url" action="showConfig" includeParams="none"> +<@s.url var="url" action="showConfig" includeParams="none" escapeAmp="false"> <@s.param name="namespace">${namespace} <@s.param name="actionName">${actionName} -<#assign url = url + "&detailView="> +<#assign url = url + "&detailView="> <#assign detailsSelected = false> <#assign exceptionsSelected = false>