-
Notifications
You must be signed in to change notification settings - Fork 834
WW-5534 Simplify ProxyUtil, add OgnlCache#computeIfAbsent #1236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,11 +20,11 @@ | |
|
|
||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.apache.struts2.result.ActionChainResult; | ||
| import org.apache.struts2.ActionInvocation; | ||
| import org.apache.struts2.StrutsConstants; | ||
| import org.apache.struts2.Unchainable; | ||
| import org.apache.struts2.inject.Inject; | ||
| import org.apache.struts2.result.ActionChainResult; | ||
| import org.apache.struts2.result.Result; | ||
| import org.apache.struts2.util.CompoundRoot; | ||
| import org.apache.struts2.util.ProxyUtil; | ||
|
|
@@ -167,17 +167,18 @@ public String intercept(ActionInvocation invocation) throws Exception { | |
| } | ||
|
|
||
| private void copyStack(ActionInvocation invocation, CompoundRoot root) { | ||
| List list = prepareList(root); | ||
| List<Object> list = prepareList(root); | ||
| Map<String, Object> ctxMap = invocation.getInvocationContext().getContextMap(); | ||
| for (Object object : list) { | ||
| if (shouldCopy(object)) { | ||
| Object action = invocation.getAction(); | ||
| Class<?> editable = null; | ||
| if(ProxyUtil.isProxy(action)) { | ||
| editable = ProxyUtil.ultimateTargetClass(action); | ||
| } | ||
| reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable); | ||
| if (!shouldCopy(object)) { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| continue; | ||
| } | ||
| Object action = invocation.getAction(); | ||
| Class<?> editable = null; | ||
| if (ProxyUtil.isProxy(action)) { | ||
| editable = ProxyUtil.ultimateTargetClass(action); | ||
| } | ||
| reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -204,9 +205,8 @@ private boolean shouldCopy(Object o) { | |
| return o != null && !(o instanceof Unchainable); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private List prepareList(CompoundRoot root) { | ||
| List list = new ArrayList(root); | ||
| private List<Object> prepareList(CompoundRoot root) { | ||
| var list = new ArrayList<>(root); | ||
| list.remove(0); | ||
| Collections.reverse(list); | ||
| return list; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,21 +15,37 @@ | |
| */ | ||
| package org.apache.struts2.ognl; | ||
|
|
||
| import java.util.function.Function; | ||
|
|
||
| import static java.util.Objects.requireNonNull; | ||
|
|
||
| /** | ||
| * A basic cache interface for use with OGNL processing (such as Expression, BeanInfo). | ||
| * All OGNL caches will have an eviction limit, but setting an extremely high value can | ||
| * simulate an "effectively unlimited" cache. | ||
| * A basic cache interface for use with OGNL processing (such as Expression, BeanInfo). Implementation must be | ||
| * thread-safe. All OGNL caches will have an eviction limit, but setting an extremely high value can simulate an | ||
| * "effectively unlimited" cache. | ||
| * | ||
| * @param <Key> The type for the cache key entries | ||
| * @param <Value> The type for the cache value entries | ||
| * @param <K> The type for the cache key entries | ||
| * @param <V> The type for the cache value entries | ||
| */ | ||
| public interface OgnlCache<Key, Value> { | ||
| public interface OgnlCache<K, V> { | ||
|
|
||
| V get(K key); | ||
|
|
||
| Value get(Key key); | ||
| /** | ||
| * @since 7.1 | ||
| */ | ||
| default V computeIfAbsent(K key, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| Function<? super K, ? extends V> mappingFunction) { | ||
| requireNonNull(mappingFunction); | ||
| if (get(key) == null) { | ||
| putIfAbsent(key, mappingFunction.apply(key)); | ||
| } | ||
| return get(key); | ||
| } | ||
|
|
||
| void put(Key key, Value value); | ||
| void put(K key, V value); | ||
|
|
||
| void putIfAbsent(Key key, Value value); | ||
| void putIfAbsent(K key, V value); | ||
|
|
||
| int size(); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,12 +18,6 @@ | |
| */ | ||
| package org.apache.struts2.ognl; | ||
|
|
||
| import org.apache.struts2.conversion.impl.XWorkConverter; | ||
| import org.apache.struts2.inject.Container; | ||
| import org.apache.struts2.inject.Inject; | ||
| import org.apache.struts2.ognl.accessor.RootAccessor; | ||
| import org.apache.struts2.util.CompoundRoot; | ||
| import org.apache.struts2.util.reflection.ReflectionException; | ||
| import ognl.ClassResolver; | ||
| import ognl.Ognl; | ||
| import ognl.OgnlContext; | ||
|
|
@@ -35,7 +29,12 @@ | |
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.apache.struts2.StrutsConstants; | ||
| import org.apache.struts2.ognl.OgnlGuard; | ||
| import org.apache.struts2.conversion.impl.XWorkConverter; | ||
| import org.apache.struts2.inject.Container; | ||
| import org.apache.struts2.inject.Inject; | ||
| import org.apache.struts2.ognl.accessor.RootAccessor; | ||
| import org.apache.struts2.util.CompoundRoot; | ||
| import org.apache.struts2.util.reflection.ReflectionException; | ||
|
|
||
| import java.beans.BeanInfo; | ||
| import java.beans.IntrospectionException; | ||
|
|
@@ -676,13 +675,19 @@ public BeanInfo getBeanInfo(Object from) throws IntrospectionException { | |
| * @throws IntrospectionException is thrown if an exception occurs during introspection. | ||
| */ | ||
| public BeanInfo getBeanInfo(Class<?> clazz) throws IntrospectionException { | ||
| synchronized (beanInfoCache) { | ||
| BeanInfo beanInfo = beanInfoCache.get(clazz); | ||
| if (beanInfo == null) { | ||
| beanInfo = Introspector.getBeanInfo(clazz, Object.class); | ||
| beanInfoCache.putIfAbsent(clazz, beanInfo); | ||
| try { | ||
| return beanInfoCache.computeIfAbsent(clazz, k -> { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By removing the |
||
| try { | ||
| return Introspector.getBeanInfo(k, Object.class); | ||
| } catch (IntrospectionException e) { | ||
| throw new IllegalArgumentException(e); | ||
| } | ||
| }); | ||
| } catch (IllegalArgumentException e) { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| if (e.getCause() instanceof IntrospectionException innerEx) { | ||
| throw innerEx; | ||
| } | ||
| return beanInfo; | ||
| throw e; | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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
ProxyUtilleading to improved maintainability