Skip to content

Conversation

@kusalk
Copy link
Member

@kusalk kusalk commented Feb 27, 2025

WW-5534

These changes prepare us for introducing Spring proxy support for the OGNL allowlist and @StrutsParameter capabilities in a follow-up PR. Refer to PR comments for details on changes.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 3, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
37.8% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@kusalk
Copy link
Member Author

kusalk commented Mar 3, 2025

org.apache.struts2.util.ProxyUtil is covered by org.apache.struts2.spring.SpringProxyUtilTest but it seems Sonar doesn't recognise this due to it being in a different module.

editable = ProxyUtil.ultimateTargetClass(action);
}
reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable);
if (!shouldCopy(object)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing much to see here, just denested this code for slight readability improvement

<optional>true</optional>
</dependency>
<dependency>
<!-- Optional used in org.apache.struts2.util.ProxyUtil to detect if object is Spring proxy -->
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using the same optional dependency technique we used for Hibernate proxy resolution - it allows us to avoid reflecting and duplicating code in ProxyUtil leading to improved maintainability

/**
* @since 7.1
*/
default V computeIfAbsent(K key,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a default implementation preserves API compatibility in case some Struts users have defined their own OgnlCache implementations using the extension points. It allows them to upgrade to Struts 7.1 without requiring any additional changes

beanInfo = Introspector.getBeanInfo(clazz, Object.class);
beanInfoCache.putIfAbsent(clazz, beanInfo);
try {
return beanInfoCache.computeIfAbsent(clazz, k -> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By removing the synchronized blcok and using #computeIfAbsent we uplift performance as now we only lock on the class name rather than whenever we enter this method

throw new IllegalArgumentException(e);
}
});
} catch (IllegalArgumentException e) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is rather ugly but it's to ensure backwards compatibility with respect to the exception throwing behaviour. The lambda we pass to #computeIfAbsent doesn't allow us to throw checked exceptions

}

return result;
return targetClassCache.computeIfAbsent(candidate, k -> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added caching here too to uplift SecurityMemberAccess performance for applications which have chosen to allow Hibernate and Spring proxies

*
*/
public class ProxyUtil {
private static final String SPRING_ADVISED_CLASS_NAME = "org.springframework.aop.framework.Advised";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed these fields which were previously used for reflection based code - we now use the optional Spring dependency with catch clauses

@kusalk kusalk marked this pull request as ready for review March 3, 2025 11:02
@kusalk kusalk requested a review from lukaszlenart March 3, 2025 11:02
@lukaszlenart
Copy link
Member

org.apache.struts2.util.ProxyUtil is covered by org.apache.struts2.spring.SpringProxyUtilTest but it seems Sonar doesn't recognise this due to it being in a different module.

I think I must put back the code in GH Actions about branches, in theory Sonar should figure it out automatically, but it doesn't :\

Copy link
Member

@lukaszlenart lukaszlenart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

@kusalk kusalk merged commit 4cc874d into main Mar 5, 2025
8 of 9 checks passed
@kusalk kusalk deleted the WW-5534-proxyutil branch March 5, 2025 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants