This is an automated email from the ASF dual-hosted git repository.

kusal pushed a commit to branch WW-5355-cache-lru
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 74d2fdcc6cd7563eb87d475e92fd2a7edb6f3d02
Author: Kusal Kithul-Godage <g...@kusal.io>
AuthorDate: Fri Oct 13 21:56:25 2023 +1100

    WW-5355 Use LRU cache by default
---
 .../opensymphony/xwork2/ognl/OgnlDefaultCache.java |  4 +-
 .../com/opensymphony/xwork2/ognl/OgnlLRUCache.java |  6 +--
 .../com/opensymphony/xwork2/ognl/OgnlUtil.java     | 55 ++++++++++++----------
 .../org/apache/struts2/default.properties          |  8 ++--
 4 files changed, 40 insertions(+), 33 deletions(-)

diff --git 
a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlDefaultCache.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlDefaultCache.java
index a32736da6..43b24bb18 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlDefaultCache.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlDefaultCache.java
@@ -30,10 +30,10 @@ import java.util.concurrent.atomic.AtomicInteger;
 public class OgnlDefaultCache<Key, Value> implements OgnlCache<Key, Value> {
 
     private final ConcurrentHashMap<Key, Value> ognlCache;
-    private final AtomicInteger cacheEvictionLimit = new AtomicInteger(25000);
+    private final AtomicInteger cacheEvictionLimit = new AtomicInteger();
 
     public OgnlDefaultCache(int evictionLimit, int initialCapacity, float 
loadFactor) {
-        this.cacheEvictionLimit.set(evictionLimit);
+        cacheEvictionLimit.set(evictionLimit);
         ognlCache = new ConcurrentHashMap<>(initialCapacity, loadFactor);
     }
 
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlLRUCache.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlLRUCache.java
index 93ab56d36..81286af34 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlLRUCache.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlLRUCache.java
@@ -36,15 +36,15 @@ import java.util.concurrent.atomic.AtomicInteger;
 public class OgnlLRUCache<Key, Value> implements OgnlCache<Key, Value> {
 
     private final Map<Key, Value> ognlLRUCache;
-    private final AtomicInteger cacheEvictionLimit = new AtomicInteger(2500);
+    private final AtomicInteger cacheEvictionLimit = new AtomicInteger();
 
     public OgnlLRUCache(int evictionLimit, int initialCapacity, float 
loadFactor) {
-        this.cacheEvictionLimit.set(evictionLimit);
+        cacheEvictionLimit.set(evictionLimit);
         // Access-order mode selected (order mode true in LinkedHashMap 
constructor).
         ognlLRUCache = Collections.synchronizedMap (new LinkedHashMap<Key, 
Value>(initialCapacity, loadFactor, true) {
             @Override
             protected boolean removeEldestEntry(Map.Entry<Key,Value> eldest) {
-                return (this.size() > cacheEvictionLimit.get());
+                return size() > cacheEvictionLimit.get();
             }
         });
     }
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 4bddad63a..16c80d99d 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -673,9 +673,15 @@ public class OgnlUtil {
      *                   note if exclusions AND inclusions are supplied and 
not null nothing will get copied.
      * @param editable the class (or interface) to restrict property setting to
      */
-    public void copy(final Object from, final Object to, final Map<String, 
Object> context, Collection<String> exclusions, Collection<String> inclusions, 
Class<?> editable) {
+    public void copy(final Object from,
+                     final Object to,
+                     final Map<String, Object> context,
+                     Collection<String> exclusions,
+                     Collection<String> inclusions,
+                     Class<?> editable) {
         if (from == null || to == null) {
-            LOG.warn("Attempting to copy from or to a null source. This is 
illegal and is bein skipped. This may be due to an error in an OGNL expression, 
action chaining, or some other event.");
+            LOG.warn(
+                    "Skipping attempt to copy from, or to, a null source.", 
new RuntimeException());
             return;
         }
 
@@ -689,8 +695,7 @@ public class OgnlUtil {
             fromPds = getPropertyDescriptors(from);
             if (editable != null) {
                 toPds = getPropertyDescriptors(editable);
-            }
-            else {
+            } else {
                 toPds = getPropertyDescriptors(to);
             }
         } catch (IntrospectionException e) {
@@ -705,29 +710,31 @@ public class OgnlUtil {
         }
 
         for (PropertyDescriptor fromPd : fromPds) {
-            if (fromPd.getReadMethod() != null) {
-                boolean copy = true;
-                if (exclusions != null && 
exclusions.contains(fromPd.getName())) {
-                    copy = false;
-                } else if (inclusions != null && 
!inclusions.contains(fromPd.getName())) {
-                    copy = false;
-                }
-
-                if (copy) {
-                    PropertyDescriptor toPd = toPdHash.get(fromPd.getName());
-                    if ((toPd != null) && (toPd.getWriteMethod() != null)) {
-                        try {
-                            Object value = ognlGet(fromPd.getName(), 
contextFrom, from, null, context, this::checkEnableEvalExpression);
-                            ognlSet(fromPd.getName(), contextTo, to, value, 
context);
-                        } catch (OgnlException e) {
-                            LOG.debug("Got OGNL exception", e);
-                        }
-                    }
+            if (fromPd.getReadMethod() == null) {
+                continue;
+            }
 
-                }
+            if (exclusions != null && exclusions.contains(fromPd.getName()) ||
+                    inclusions != null && 
!inclusions.contains(fromPd.getName())) {
+                continue;
+            }
 
+            PropertyDescriptor toPd = toPdHash.get(fromPd.getName());
+            if (toPd == null || toPd.getWriteMethod() == null) {
+                continue;
             }
 
+            try {
+                Object value = ognlGet(fromPd.getName(),
+                        contextFrom,
+                        from,
+                        null,
+                        context,
+                        this::checkEnableEvalExpression);
+                ognlSet(fromPd.getName(), contextTo, to, value, context);
+            } catch (OgnlException e) {
+                LOG.debug("Got OGNL exception", e);
+            }
         }
     }
 
@@ -746,7 +753,7 @@ public class OgnlUtil {
     }
 
     /**
-     * Get's the java beans property descriptors for the given source.
+     * Gets the java beans property descriptors for the given source.
      *
      * @param source the source object.
      * @return property descriptors.
diff --git a/core/src/main/resources/org/apache/struts2/default.properties 
b/core/src/main/resources/org/apache/struts2/default.properties
index 56bc714de..60257465b 100644
--- a/core/src/main/resources/org/apache/struts2/default.properties
+++ b/core/src/main/resources/org/apache/struts2/default.properties
@@ -243,12 +243,12 @@ struts.ognl.enableExpressionCache=true
 ### For expressionCacheLRUMode true, the limit will ensure the cache does not 
exceed
 ### that size, dropping the oldest (least-recently-used) expressions to add 
new ones.
 ### NOTE: If not set, the default is 25000, which may be excessive.
-# struts.ognl.expressionCacheMaxSize=1000
+struts.ognl.expressionCacheMaxSize=10000
 
 ### Indicates if the OGNL expressionCache should use LRU mode.
 ### NOTE: When true, make sure to set the expressionCacheMaxSize to a 
reasonable value
 ###       for your application.  Otherwise the default limit will never 
(practically) be reached.
-# struts.ognl.expressionCacheLRUMode=false
+struts.ognl.expressionCacheLRUMode=true
 
 ### Specify a limit to the number of entries in the OGNL beanInfoCache.
 ### For the standard beanInfoCache mode, when the limit is exceeded the entire 
cache's
@@ -256,12 +256,12 @@ struts.ognl.enableExpressionCache=true
 ### For beanInfoCacheLRUMode true, the limit will ensure the cache does not 
exceed
 ### that size, dropping the oldest (least-recently-used) expressions to add 
new ones.
 ### NOTE: If not set, the default is 25000, which may be excessive.
-# struts.ognl.beanInfoCacheMaxSize=1000
+struts.ognl.beanInfoCacheMaxSize=5000
 
 ### Indicates if the OGNL beanInfoCache should use LRU mode.
 ### NOTE: When true, make sure to set the beanInfoCacheMaxSize to a reasonable 
value
 ###       for your application.  Otherwise the default limit will never 
(practically) be reached.
-# struts.ognl.beanInfoCacheLRUMode=false
+struts.ognl.beanInfoCacheLRUMode=true
 
 ### Indicates if Dispatcher should handle unexpected exceptions by calling 
sendError()
 ### or simply rethrow it as a ServletException to allow future processing by 
other frameworks like Spring Security

Reply via email to