[
https://issues.apache.org/jira/browse/WW-5343?focusedWorklogId=891833&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-891833
]
ASF GitHub Bot logged work on WW-5343:
--------------------------------------
Author: ASF GitHub Bot
Created on: 22/Nov/23 14:20
Start Date: 22/Nov/23 14:20
Worklog Time Spent: 10m
Work Description: kusalk commented on code in PR #791:
URL: https://github.com/apache/struts/pull/791#discussion_r1402127733
##########
core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java:
##########
@@ -133,7 +134,6 @@ public class DefaultConfiguration implements Configuration {
Map<String, Object> constants = new HashMap<>();
constants.put(StrutsConstants.STRUTS_DEVMODE, Boolean.FALSE);
constants.put(StrutsConstants.STRUTS_OGNL_LOG_MISSING_PROPERTIES,
Boolean.FALSE);
- constants.put(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION,
Boolean.FALSE);
Review Comment:
This constant is not required for bootstrapping
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java:
##########
@@ -84,27 +77,15 @@ public class OgnlUtil {
private final OgnlGuard ognlGuard;
private boolean devMode;
- private boolean enableExpressionCache = true;
+ private boolean enableExpressionCache;
private boolean enableEvalExpression;
- private Set<String> excludedClasses = emptySet();
Review Comment:
All the configuration is now injected directly into `SecurityMemberAccess`
except for devMode configuration
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java:
##########
@@ -175,166 +156,110 @@ protected void setEnableEvalExpression(String
evalExpression) {
}
}
- @Inject(value = StrutsConstants.STRUTS_EXCLUDED_CLASSES, required = false)
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
protected void setExcludedClasses(String commaDelimitedClasses) {
- excludedClasses = toNewClassesSet(excludedClasses,
commaDelimitedClasses);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required
= false)
protected void setDevModeExcludedClasses(String commaDelimitedClasses) {
- devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses,
commaDelimitedClasses);
+ this.devModeExcludedClasses = commaDelimitedClasses;
}
- private static Set<String> toClassesSet(String newDelimitedClasses) throws
ConfigurationException {
Review Comment:
Moved these utility methods into their own class
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java:
##########
@@ -175,166 +156,110 @@ protected void setEnableEvalExpression(String
evalExpression) {
}
}
- @Inject(value = StrutsConstants.STRUTS_EXCLUDED_CLASSES, required = false)
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
protected void setExcludedClasses(String commaDelimitedClasses) {
- excludedClasses = toNewClassesSet(excludedClasses,
commaDelimitedClasses);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required
= false)
protected void setDevModeExcludedClasses(String commaDelimitedClasses) {
- devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses,
commaDelimitedClasses);
+ this.devModeExcludedClasses = commaDelimitedClasses;
}
- private static Set<String> toClassesSet(String newDelimitedClasses) throws
ConfigurationException {
- Set<String> classNames =
commaDelimitedStringToSet(newDelimitedClasses);
- validateClasses(classNames, OgnlUtil.class.getClassLoader());
- return unmodifiableSet(classNames);
- }
-
- private static Set<String> toNewClassesSet(Set<String> oldClasses, String
newDelimitedClasses) throws ConfigurationException {
- Set<String> classNames =
commaDelimitedStringToSet(newDelimitedClasses);
- validateClasses(classNames, OgnlUtil.class.getClassLoader());
- Set<String> excludedClasses = new HashSet<>(oldClasses);
- excludedClasses.addAll(classNames);
- return unmodifiableSet(excludedClasses);
- }
-
- private static void validateClasses(Set<String> classNames, ClassLoader
validatingClassLoader) throws ConfigurationException {
- for (String className : classNames) {
- try {
- validatingClassLoader.loadClass(className);
- } catch (ClassNotFoundException e) {
- throw new ConfigurationException("Cannot load class for
exclusion/exemption configuration: " + className, e);
- }
- }
- }
-
- @Inject(value = StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS,
required = false)
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
protected void setExcludedPackageNamePatterns(String
commaDelimitedPackagePatterns) {
- excludedPackageNamePatterns =
toNewPatternsSet(excludedPackageNamePatterns, commaDelimitedPackagePatterns);
}
@Inject(value =
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required =
false)
protected void setDevModeExcludedPackageNamePatterns(String
commaDelimitedPackagePatterns) {
- devModeExcludedPackageNamePatterns =
toNewPatternsSet(devModeExcludedPackageNamePatterns,
commaDelimitedPackagePatterns);
+ this.devModeExcludedPackageNamePatterns =
commaDelimitedPackagePatterns;
}
- private static Set<Pattern> toNewPatternsSet(Set<Pattern> oldPatterns,
String newDelimitedPatterns) throws ConfigurationException {
- Set<String> patterns = commaDelimitedStringToSet(newDelimitedPatterns);
- Set<Pattern> newPatterns = new HashSet<>(oldPatterns);
- for (String pattern: patterns) {
- try {
- newPatterns.add(Pattern.compile(pattern));
- } catch (PatternSyntaxException e) {
- throw new ConfigurationException("Excluded package name
patterns could not be parsed due to invalid regex: " + pattern, e);
- }
- }
- return unmodifiableSet(newPatterns);
- }
-
- @Inject(value = StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAMES, required =
false)
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
protected void setExcludedPackageNames(String commaDelimitedPackageNames) {
- excludedPackageNames = toNewPackageNamesSet(excludedPackageNames,
commaDelimitedPackageNames);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES,
required = false)
protected void setDevModeExcludedPackageNames(String
commaDelimitedPackageNames) {
- devModeExcludedPackageNames =
toNewPackageNamesSet(devModeExcludedPackageNames, commaDelimitedPackageNames);
- }
-
- private static Set<String> toPackageNamesSet(String
newDelimitedPackageNames) throws ConfigurationException {
- Set<String> packageNames =
commaDelimitedStringToSet(newDelimitedPackageNames)
- .stream().map(s -> strip(s, ".")).collect(toSet());
- validatePackageNames(packageNames);
- return unmodifiableSet(packageNames);
- }
-
- private static Set<String> toNewPackageNamesSet(Collection<String>
oldPackageNames, String newDelimitedPackageNames) throws ConfigurationException
{
- Set<String> packageNames =
commaDelimitedStringToSet(newDelimitedPackageNames)
- .stream().map(s -> strip(s, ".")).collect(toSet());
- validatePackageNames(packageNames);
- Set<String> newPackageNames = new HashSet<>(oldPackageNames);
- newPackageNames.addAll(packageNames);
- return unmodifiableSet(newPackageNames);
+ this.devModeExcludedPackageNames = commaDelimitedPackageNames;
}
- private static void validatePackageNames(Collection<String> packageNames) {
- if (packageNames.stream().anyMatch(s ->
Pattern.compile("\\s").matcher(s).find())) {
- throw new ConfigurationException("Excluded package names could not
be parsed due to erroneous whitespace characters: " + packageNames);
- }
- }
-
- @Inject(value = StrutsConstants.STRUTS_EXCLUDED_PACKAGE_EXEMPT_CLASSES,
required = false)
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
public void setExcludedPackageExemptClasses(String commaDelimitedClasses) {
- excludedPackageExemptClasses = toClassesSet(commaDelimitedClasses);
}
@Inject(value =
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required =
false)
public void setDevModeExcludedPackageExemptClasses(String
commaDelimitedClasses) {
- devModeExcludedPackageExemptClasses =
toClassesSet(commaDelimitedClasses);
+ this.devModeExcludedPackageExemptClasses = commaDelimitedClasses;
}
+ /**
+ * @deprecated since 6.4.0, no replacement.
+ */
+ @Deprecated
public Set<String> getExcludedClasses() {
- return excludedClasses;
+ return toClassesSet(container.getInstance(String.class,
StrutsConstants.STRUTS_EXCLUDED_CLASSES));
Review Comment:
Deprecated getters are still functional for API compatibility
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java:
##########
@@ -77,38 +77,91 @@ public class OgnlValueStack implements Serializable,
ValueStack, ClearableValueS
private boolean devMode;
private boolean logMissingProperties;
+ /**
+ * @since 6.4.0
+ */
+ protected OgnlValueStack(ValueStack vs,
+ XWorkConverter xworkConverter,
+ CompoundRootAccessor accessor,
+ TextProvider prov,
+ SecurityMemberAccess securityMemberAccess) {
+ setRoot(xworkConverter,
+ accessor,
+ vs != null ? new CompoundRoot(vs.getRoot()) : new
CompoundRoot(),
+ securityMemberAccess);
+ if (prov != null) {
+ push(prov);
+ }
+ }
+
+ /**
+ * @since 6.4.0
+ */
+ protected OgnlValueStack(XWorkConverter xworkConverter,
CompoundRootAccessor accessor, TextProvider prov, SecurityMemberAccess
securityMemberAccess) {
+ this(null, xworkConverter, accessor, prov, securityMemberAccess);
+ }
+
+ /**
+ * @since 6.4.0
+ */
+ protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter,
CompoundRootAccessor accessor, SecurityMemberAccess securityMemberAccess) {
+ this(vs, xworkConverter, accessor, null, securityMemberAccess);
+ }
+
+ /**
+ * @deprecated since 6.4.0, use {@link #OgnlValueStack(ValueStack,
XWorkConverter, CompoundRootAccessor, TextProvider, SecurityMemberAccess)}
instead.
+ */
+ @Deprecated
+ protected OgnlValueStack(ValueStack vs,
+ XWorkConverter xworkConverter,
+ CompoundRootAccessor accessor,
+ TextProvider prov,
+ boolean allowStaticFieldAccess) {
+ this(vs, xworkConverter, accessor, prov, new
SecurityMemberAccess(allowStaticFieldAccess));
+ }
+
+ /**
+ * @deprecated since 6.4.0, use {@link #OgnlValueStack(XWorkConverter,
CompoundRootAccessor, TextProvider, SecurityMemberAccess)} instead.
+ */
+ @Deprecated
protected OgnlValueStack(XWorkConverter xworkConverter,
CompoundRootAccessor accessor, TextProvider prov, boolean
allowStaticFieldAccess) {
- setRoot(xworkConverter, accessor, new CompoundRoot(),
allowStaticFieldAccess);
- push(prov);
+ this(xworkConverter, accessor, prov, new
SecurityMemberAccess(allowStaticFieldAccess));
}
+ /**
+ * @deprecated since 6.4.0, use {@link #OgnlValueStack(ValueStack,
XWorkConverter, CompoundRootAccessor, SecurityMemberAccess)} instead.
+ */
+ @Deprecated
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter,
CompoundRootAccessor accessor, boolean allowStaticFieldAccess) {
- setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()),
allowStaticFieldAccess);
+ this(vs, xworkConverter, accessor, new
SecurityMemberAccess(allowStaticFieldAccess));
}
@Inject
protected void setOgnlUtil(OgnlUtil ognlUtil) {
this.ognlUtil = ognlUtil;
- securityMemberAccess.useExcludedClasses(ognlUtil.getExcludedClasses());
Review Comment:
No more fragile configuration setting duplicated in multiple places
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java:
##########
@@ -464,48 +517,42 @@ public int size() {
return root.size();
}
+ /**
+ * Retained for serializability - see {@link
com.opensymphony.xwork2.ognl.OgnlValueStackTest#testSerializable}
+ */
private Object readResolve() {
// TODO: this should be done better
ActionContext ac = ActionContext.getContext();
Container cont = ac.getContainer();
XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class);
CompoundRootAccessor accessor = (CompoundRootAccessor)
cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName());
TextProvider prov = cont.getInstance(TextProvider.class, "system");
- final boolean allowStaticField =
BooleanUtils.toBoolean(cont.getInstance(String.class,
StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
- OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor,
prov, allowStaticField);
+ SecurityMemberAccess sma =
cont.getInstance(SecurityMemberAccess.class);
+ OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor,
prov, sma);
aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class));
- aStack.setRoot(xworkConverter, accessor, this.root, allowStaticField);
-
+ aStack.setRoot(xworkConverter, accessor, this.root, sma);
return aStack;
}
-
public void clearContextValues() {
//this is an OGNL ValueStack so the context will be an OgnlContext
//it would be better to make context of type OgnlContext
((OgnlContext) context).getValues().clear();
}
- @Deprecated
- public void setAcceptProperties(Set<Pattern> acceptedProperties) {
- securityMemberAccess.useAcceptProperties(acceptedProperties);
- }
-
public void useAcceptProperties(Set<Pattern> acceptedProperties) {
securityMemberAccess.useAcceptProperties(acceptedProperties);
}
- @Deprecated
- public void setExcludeProperties(Set<Pattern> excludeProperties) {
- securityMemberAccess.useExcludeProperties(excludeProperties);
- }
-
public void useExcludeProperties(Set<Pattern> excludeProperties) {
securityMemberAccess.useExcludeProperties(excludeProperties);
}
- @Inject
Review Comment:
Not sure why this was injected again given it's already passed into the
constructor
##########
core/src/main/java/com/opensymphony/xwork2/util/MemberAccessValueStack.java:
##########
@@ -31,15 +31,19 @@ public interface MemberAccessValueStack {
* @deprecated please use {@link #useExcludeProperties(Set)}
*/
@Deprecated
- void setExcludeProperties(Set<Pattern> excludeProperties);
+ default void setExcludeProperties(Set<Pattern> excludeProperties) {
+ useExcludeProperties(excludeProperties);
Review Comment:
Lifted the deprecated implementations into the interface for cleanliness
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java:
##########
@@ -922,8 +855,7 @@ protected Map<String, Object> createDefaultContext(Object
root, ClassResolver cl
resolver = container.getInstance(CompoundRootAccessor.class);
}
- SecurityMemberAccess memberAccess = new
SecurityMemberAccess(allowStaticFieldAccess);
- memberAccess.disallowProxyMemberAccess(disallowProxyMemberAccess);
+ SecurityMemberAccess memberAccess =
container.getInstance(SecurityMemberAccess.class);
Review Comment:
This is a prototype bean so will be a new instance per context
##########
core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java:
##########
@@ -105,10 +98,10 @@ protected void setContainer(Container container) throws
ClassNotFoundException {
}
/**
- * Retrieve allowStaticFieldAccess state from the container (allows for
lazy fetching)
+ * @deprecated since 6.4.0, no replacement.
*/
+ @Deprecated
Review Comment:
Couldn't see any use for this method
##########
core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilStrutsTest.java:
##########
@@ -31,33 +31,6 @@ public void setUp() throws Exception {
ognlUtil = container.getInstance(OgnlUtil.class);
}
- public void testDefaultExcludes() {
Review Comment:
Deleted tests whose functionality is covered elsewhere
##########
core/src/test/java/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java:
##########
@@ -1180,43 +1178,6 @@ public void
testOgnlValueStackFromOgnlValueStackFactoryDefaultConfig() {
assertNull("accessed private field (result not null) ?",
accessedValue);
}
- /**
- * Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
- * when no static access flags are set (not present in configuration).
- */
- public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() {
Review Comment:
This flag is now a required constant so this test is no longer applicable
##########
core/src/test/java/com/opensymphony/xwork2/ognl/SecurityMemberAccessTest.java:
##########
@@ -58,6 +62,82 @@ protected void assignNewSma(boolean allowStaticFieldAccess) {
sma = new SecurityMemberAccess(allowStaticFieldAccess);
}
+ private <T> T reflectField(String fieldName) throws IllegalAccessException
{
+ return (T) FieldUtils.readField(sma, fieldName, true);
+ }
+
+ @Test
+ public void defaultExclusionList() throws Exception {
Review Comment:
Moved/rewrote some tests here from `OgnlUtilTest`
##########
core/src/main/java/org/apache/struts2/StrutsConstants.java:
##########
@@ -234,6 +234,8 @@ public final class StrutsConstants {
/** The name of the parameter to determine whether static field access
will be allowed in OGNL expressions or not */
public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS =
"struts.ognl.allowStaticFieldAccess";
+ public static final String STRUTS_MEMBER_ACCESS =
"struts.securityMemberAccess";
Review Comment:
Extension point!
Issue Time Tracking
-------------------
Worklog Id: (was: 891833)
Time Spent: 0.5h (was: 20m)
> Make SecurityMemberAccess extensible and a prototype bean
> ---------------------------------------------------------
>
> Key: WW-5343
> URL: https://issues.apache.org/jira/browse/WW-5343
> Project: Struts 2
> Issue Type: Improvement
> Components: Core
> Reporter: Kusal Kithul-Godage
> Priority: Minor
> Fix For: 6.4.0
>
> Time Spent: 0.5h
> Remaining Estimate: 0h
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)