Skip to content

Commit bcf569b

Browse files
committed
WW-5534 Simplify ProxyUtil, add OgnlCache#computeIfAbsent
1 parent 0d2d110 commit bcf569b

File tree

10 files changed

+162
-176
lines changed

10 files changed

+162
-176
lines changed

core/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,19 @@
187187
<artifactId>commons-text</artifactId>
188188
</dependency>
189189

190-
<!-- Optional used in org.apache.struts2.util.ProxyUtil to detect if object is HibernateProxy -->
191190
<dependency>
191+
<!-- Optional used in org.apache.struts2.util.ProxyUtil to detect if object is HibernateProxy -->
192192
<groupId>org.hibernate</groupId>
193193
<artifactId>hibernate-core</artifactId>
194194
<version>5.6.15.Final</version>
195195
<optional>true</optional>
196196
</dependency>
197+
<dependency>
198+
<!-- Optional used in org.apache.struts2.util.ProxyUtil to detect if object is Spring proxy -->
199+
<groupId>org.springframework</groupId>
200+
<artifactId>spring-aop</artifactId>
201+
<optional>true</optional>
202+
</dependency>
197203

198204
<dependency>
199205
<groupId>org.springframework</groupId>

core/src/main/java/org/apache/struts2/interceptor/ChainingInterceptor.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
import org.apache.logging.log4j.LogManager;
2222
import org.apache.logging.log4j.Logger;
23-
import org.apache.struts2.result.ActionChainResult;
2423
import org.apache.struts2.ActionInvocation;
2524
import org.apache.struts2.StrutsConstants;
2625
import org.apache.struts2.Unchainable;
2726
import org.apache.struts2.inject.Inject;
27+
import org.apache.struts2.result.ActionChainResult;
2828
import org.apache.struts2.result.Result;
2929
import org.apache.struts2.util.CompoundRoot;
3030
import org.apache.struts2.util.ProxyUtil;
@@ -167,17 +167,18 @@ public String intercept(ActionInvocation invocation) throws Exception {
167167
}
168168

169169
private void copyStack(ActionInvocation invocation, CompoundRoot root) {
170-
List list = prepareList(root);
170+
List<Object> list = prepareList(root);
171171
Map<String, Object> ctxMap = invocation.getInvocationContext().getContextMap();
172172
for (Object object : list) {
173-
if (shouldCopy(object)) {
174-
Object action = invocation.getAction();
175-
Class<?> editable = null;
176-
if(ProxyUtil.isProxy(action)) {
177-
editable = ProxyUtil.ultimateTargetClass(action);
178-
}
179-
reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable);
173+
if (!shouldCopy(object)) {
174+
continue;
175+
}
176+
Object action = invocation.getAction();
177+
Class<?> editable = null;
178+
if (ProxyUtil.isProxy(action)) {
179+
editable = ProxyUtil.ultimateTargetClass(action);
180180
}
181+
reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable);
181182
}
182183
}
183184

@@ -204,9 +205,8 @@ private boolean shouldCopy(Object o) {
204205
return o != null && !(o instanceof Unchainable);
205206
}
206207

207-
@SuppressWarnings("unchecked")
208-
private List prepareList(CompoundRoot root) {
209-
List list = new ArrayList(root);
208+
private List<Object> prepareList(CompoundRoot root) {
209+
var list = new ArrayList<>(root);
210210
list.remove(0);
211211
Collections.reverse(list);
212212
return list;

core/src/main/java/org/apache/struts2/ognl/OgnlCache.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,37 @@
1515
*/
1616
package org.apache.struts2.ognl;
1717

18+
import java.util.function.Function;
19+
20+
import static java.util.Objects.requireNonNull;
21+
1822
/**
19-
* A basic cache interface for use with OGNL processing (such as Expression, BeanInfo).
20-
* All OGNL caches will have an eviction limit, but setting an extremely high value can
21-
* simulate an "effectively unlimited" cache.
23+
* A basic cache interface for use with OGNL processing (such as Expression, BeanInfo). Implementation must be
24+
* thread-safe. All OGNL caches will have an eviction limit, but setting an extremely high value can simulate an
25+
* "effectively unlimited" cache.
2226
*
23-
* @param <Key> The type for the cache key entries
24-
* @param <Value> The type for the cache value entries
27+
* @param <K> The type for the cache key entries
28+
* @param <V> The type for the cache value entries
2529
*/
26-
public interface OgnlCache<Key, Value> {
30+
public interface OgnlCache<K, V> {
31+
32+
V get(K key);
2733

28-
Value get(Key key);
34+
/**
35+
* @since 7.1
36+
*/
37+
default V computeIfAbsent(K key,
38+
Function<? super K, ? extends V> mappingFunction) {
39+
requireNonNull(mappingFunction);
40+
if (get(key) == null) {
41+
putIfAbsent(key, mappingFunction.apply(key));
42+
}
43+
return get(key);
44+
}
2945

30-
void put(Key key, Value value);
46+
void put(K key, V value);
3147

32-
void putIfAbsent(Key key, Value value);
48+
void putIfAbsent(K key, V value);
3349

3450
int size();
3551

core/src/main/java/org/apache/struts2/ognl/OgnlCaffeineCache.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import com.github.benmanes.caffeine.cache.Cache;
1919
import com.github.benmanes.caffeine.cache.Caffeine;
2020

21+
import java.util.function.Function;
22+
2123
/**
2224
* <p>This OGNL Cache implementation is backed by {@link Caffeine} which uses the Window TinyLfu algorithm.</p>
2325
*
@@ -46,6 +48,11 @@ public V get(K key) {
4648
return cache.getIfPresent(key);
4749
}
4850

51+
@Override
52+
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
53+
return cache.asMap().computeIfAbsent(key, mappingFunction);
54+
}
55+
4956
@Override
5057
public void put(K key, V value) {
5158
cache.put(key, value);

core/src/main/java/org/apache/struts2/ognl/OgnlDefaultCache.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.concurrent.ConcurrentHashMap;
1919
import java.util.concurrent.atomic.AtomicInteger;
20+
import java.util.function.Function;
2021

2122
/**
2223
* <p>Basic OGNL cache implementation.</p>
@@ -45,16 +46,21 @@ public V get(K key) {
4546
return ognlCache.get(key);
4647
}
4748

49+
@Override
50+
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
51+
return ognlCache.computeIfAbsent(key, mappingFunction);
52+
}
53+
4854
@Override
4955
public void put(K key, V value) {
5056
ognlCache.put(key, value);
51-
this.clearIfEvictionLimitExceeded();
57+
clearIfEvictionLimitExceeded();
5258
}
5359

5460
@Override
5561
public void putIfAbsent(K key, V value) {
5662
ognlCache.putIfAbsent(key, value);
57-
this.clearIfEvictionLimitExceeded();
63+
clearIfEvictionLimitExceeded();
5864
}
5965

6066
@Override
@@ -69,12 +75,12 @@ public void clear() {
6975

7076
@Override
7177
public int getEvictionLimit() {
72-
return this.cacheEvictionLimit.get();
78+
return cacheEvictionLimit.get();
7379
}
7480

7581
@Override
76-
public void setEvictionLimit(int cacheEvictionLimit) {
77-
this.cacheEvictionLimit.set(cacheEvictionLimit);
82+
public void setEvictionLimit(int newCacheEvictionLimit) {
83+
cacheEvictionLimit.set(newCacheEvictionLimit);
7884
}
7985

8086
/**

core/src/main/java/org/apache/struts2/ognl/OgnlLRUCache.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.LinkedHashMap;
2020
import java.util.Map;
2121
import java.util.concurrent.atomic.AtomicInteger;
22+
import java.util.function.Function;
2223

2324
/**
2425
* <p>A basic OGNL LRU cache implementation.</p>
@@ -54,6 +55,11 @@ public V get(K key) {
5455
return ognlLRUCache.get(key);
5556
}
5657

58+
@Override
59+
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
60+
return ognlLRUCache.computeIfAbsent(key, mappingFunction);
61+
}
62+
5763
@Override
5864
public void put(K key, V value) {
5965
ognlLRUCache.put(key, value);

core/src/main/java/org/apache/struts2/ognl/OgnlUtil.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@
1818
*/
1919
package org.apache.struts2.ognl;
2020

21-
import org.apache.struts2.conversion.impl.XWorkConverter;
22-
import org.apache.struts2.inject.Container;
23-
import org.apache.struts2.inject.Inject;
24-
import org.apache.struts2.ognl.accessor.RootAccessor;
25-
import org.apache.struts2.util.CompoundRoot;
26-
import org.apache.struts2.util.reflection.ReflectionException;
2721
import ognl.ClassResolver;
2822
import ognl.Ognl;
2923
import ognl.OgnlContext;
@@ -35,7 +29,12 @@
3529
import org.apache.logging.log4j.LogManager;
3630
import org.apache.logging.log4j.Logger;
3731
import org.apache.struts2.StrutsConstants;
38-
import org.apache.struts2.ognl.OgnlGuard;
32+
import org.apache.struts2.conversion.impl.XWorkConverter;
33+
import org.apache.struts2.inject.Container;
34+
import org.apache.struts2.inject.Inject;
35+
import org.apache.struts2.ognl.accessor.RootAccessor;
36+
import org.apache.struts2.util.CompoundRoot;
37+
import org.apache.struts2.util.reflection.ReflectionException;
3938

4039
import java.beans.BeanInfo;
4140
import java.beans.IntrospectionException;
@@ -676,13 +675,19 @@ public BeanInfo getBeanInfo(Object from) throws IntrospectionException {
676675
* @throws IntrospectionException is thrown if an exception occurs during introspection.
677676
*/
678677
public BeanInfo getBeanInfo(Class<?> clazz) throws IntrospectionException {
679-
synchronized (beanInfoCache) {
680-
BeanInfo beanInfo = beanInfoCache.get(clazz);
681-
if (beanInfo == null) {
682-
beanInfo = Introspector.getBeanInfo(clazz, Object.class);
683-
beanInfoCache.putIfAbsent(clazz, beanInfo);
678+
try {
679+
return beanInfoCache.computeIfAbsent(clazz, k -> {
680+
try {
681+
return Introspector.getBeanInfo(k, Object.class);
682+
} catch (IntrospectionException e) {
683+
throw new IllegalArgumentException(e);
684+
}
685+
});
686+
} catch (IllegalArgumentException e) {
687+
if (e.getCause() instanceof IntrospectionException innerEx) {
688+
throw innerEx;
684689
}
685-
return beanInfo;
690+
throw e;
686691
}
687692
}
688693

0 commit comments

Comments
 (0)