mirror of
https://github.com/apache/struts.git
synced 2026-08-06 07:06:58 +00:00
Merge pull request #361 from JCgH4164838Gh792C124B5/localS2_25x_OgnlCachecontrol
Proposed WW-5035 enhancement:
This commit is contained in:
@@ -188,6 +188,76 @@ public class OgnlUtil {
|
||||
return disallowProxyMemberAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience mechanism to clear the OGNL Runtime Cache via OgnlUtil. May be utilized
|
||||
* by applications that generate many unique OGNL expressions over time.
|
||||
*
|
||||
* Note: This call affects the global OGNL cache, see ({@link ognl.OgnlRuntime#clearCache()} for details.
|
||||
*
|
||||
* Warning: Frequent calling if this method may negatively impact performance, but may be required
|
||||
* to avoid memory exhaustion (resource leak) with too many OGNL expressions being cached.
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public static void clearRuntimeCache() {
|
||||
OgnlRuntime.clearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a mechanism to clear the OGNL expression cache. May be utilized by applications
|
||||
* that generate many unique OGNL expressions over time.
|
||||
*
|
||||
* Note: This call affects the current OgnlUtil instance. For Struts this is often a Singleton
|
||||
* instance so it can be "effectively global".
|
||||
*
|
||||
* Warning: Frequent calling if this method may negatively impact performance, but may be required
|
||||
* to avoid memory exhaustion (resource leak) with too many OGNL expressions being cached.
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void clearExpressionCache() {
|
||||
expressions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the size of the expression cache (current number of elements).
|
||||
*
|
||||
* @return current number of elements in the expression cache.
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public int expressionCacheSize() {
|
||||
return expressions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a mechanism to clear the BeanInfo cache. May be utilized by applications
|
||||
* that request BeanInfo and/or PropertyDescriptors for many unique classes or objects over time
|
||||
* (especially dynamic objects).
|
||||
*
|
||||
* Note: This call affects the current OgnlUtil instance. For Struts this is often a Singleton
|
||||
* instance so it can be "effectively global".
|
||||
*
|
||||
* Warning: Frequent calling if this method may negatively impact performance, but may be required
|
||||
* to avoid memory exhaustion (resource leak) with too many BeanInfo elements being cached.
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void clearBeanInfoCache() {
|
||||
beanInfoCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the size of the BeanInfo cache (current number of elements).
|
||||
*
|
||||
* @return current number of elements in the BeanInfo cache.
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public int beanInfoCacheSize() {
|
||||
return beanInfoCache.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object's properties using the default type converter, defaulting to not throw
|
||||
* exceptions for problems setting the properties.
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.opensymphony.xwork2.test.User;
|
||||
import com.opensymphony.xwork2.util.*;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import java.beans.IntrospectionException;
|
||||
import ognl.*;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
@@ -113,6 +114,84 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
assertSame(expr0, expr2);
|
||||
}
|
||||
|
||||
public void testClearExpressionCache() throws OgnlException {
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
// Test that the expression cache is functioning as expected.
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
Object expr1 = ognlUtil.compile("test");
|
||||
Object expr2 = ognlUtil.compile("test");
|
||||
// Cache in effect, so expr0, expr1, expr2 should be the same.
|
||||
assertSame(expr0, expr1);
|
||||
assertSame(expr0, expr2);
|
||||
assertTrue("Expression cache empty before clear ?", ognlUtil.expressionCacheSize() > 0);
|
||||
// Clear the Epxression cache and confirm subsequent requests are new.
|
||||
ognlUtil.clearExpressionCache();
|
||||
assertTrue("Expression cache not empty after clear ?", ognlUtil.expressionCacheSize() == 0);
|
||||
Object expr3 = ognlUtil.compile("test");
|
||||
Object expr4 = ognlUtil.compile("test");
|
||||
Object expr5 = ognlUtil.compile("test");
|
||||
// Cache cleared, expr3 should be a new instance.
|
||||
assertNotSame(expr0, expr3);
|
||||
// Cache still in effect, so expr3, expr4, expr5 should be the same.
|
||||
assertSame(expr3, expr4);
|
||||
assertSame(expr3, expr5);
|
||||
assertTrue("Expression cache empty after usage ?", ognlUtil.expressionCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testClearBeanInfoCache() throws IntrospectionException {
|
||||
final TestBean1 testBean1 = new TestBean1();
|
||||
final TestBean2 testBean2 = new TestBean2();
|
||||
// Test that the BeanInfo cache is functioning as expected.
|
||||
Object beanInfo1_1 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_2 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_3 = ognlUtil.getBeanInfo(testBean1);
|
||||
// Cache in effect, so beanInfo1_1, beanInfo1_2, beanInfo1_3 should be the same.
|
||||
assertSame(beanInfo1_1, beanInfo1_2);
|
||||
assertSame(beanInfo1_1, beanInfo1_3);
|
||||
Object beanInfo2_1 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_2 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_3 = ognlUtil.getBeanInfo(testBean2);
|
||||
// Cache in effect, so beanInfo2_1, beanInfo2_2, beanInfo2_3 should be the same.
|
||||
assertSame(beanInfo2_1, beanInfo2_2);
|
||||
assertSame(beanInfo2_1, beanInfo2_3);
|
||||
// BeanInfo for TestBean1 and TestBean2 should always be different.
|
||||
assertNotSame(beanInfo1_1, beanInfo2_1);
|
||||
assertTrue("BeanInfo cache empty before clear ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
// Clear the BeanInfo cache and confirm subsequent requests are new.
|
||||
ognlUtil.clearBeanInfoCache();
|
||||
assertTrue("BeanInfo cache not empty after clear ?", ognlUtil.beanInfoCacheSize() == 0);
|
||||
Object beanInfo1_4 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_5 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_6 = ognlUtil.getBeanInfo(testBean1);
|
||||
// Cache in effect, so beanInfo1_4, beanInfo1_5, beanInfo1_6 should be the same.
|
||||
assertSame(beanInfo1_4, beanInfo1_5);
|
||||
assertSame(beanInfo1_4, beanInfo1_6);
|
||||
// Cache was cleared in-between, so beanInfo1_1/beanInfo1_2/beanInfo1_3 should differ
|
||||
// from beanInfo1_4/beanInfo1_5/beanInfo1_6.
|
||||
assertNotSame(beanInfo1_1, beanInfo1_4);
|
||||
assertNotSame(beanInfo1_2, beanInfo1_5);
|
||||
assertNotSame(beanInfo1_3, beanInfo1_6);
|
||||
Object beanInfo2_4 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_5 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_6 = ognlUtil.getBeanInfo(testBean2);
|
||||
// Cache in effect, so beanInfo2_4, beanInfo2_5, beanInfo2_6 should be the same.
|
||||
assertSame(beanInfo2_4, beanInfo2_5);
|
||||
assertSame(beanInfo2_4, beanInfo2_6);
|
||||
// Cache was cleared in-between, so beanInfo2_1/beanInfo2_2/beanInfo2_3 should differ
|
||||
// from beanInfo2_4/beanInfo2_5/beanInfo2_6.
|
||||
assertNotSame(beanInfo2_1, beanInfo2_4);
|
||||
assertNotSame(beanInfo2_2, beanInfo2_5);
|
||||
assertNotSame(beanInfo2_3, beanInfo2_6);
|
||||
// BeanInfo for TestBean1 and TestBean2 should always be different.
|
||||
assertNotSame(beanInfo1_4, beanInfo2_4);
|
||||
assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testClearRuntimeCache() {
|
||||
// Confirm that no exceptions or failures arise when calling the convenience global clear method.
|
||||
OgnlUtil.clearRuntimeCache();
|
||||
}
|
||||
|
||||
public void testCacheDisabled() throws OgnlException {
|
||||
ognlUtil.setEnableExpressionCache("false");
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
@@ -1333,4 +1412,37 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestBean1 {
|
||||
private String testBeanProperty;
|
||||
|
||||
public TestBean1() {
|
||||
testBeanProperty = "defaultTestBean1Property";
|
||||
}
|
||||
|
||||
public String getTestBeanProperty() {
|
||||
return testBeanProperty;
|
||||
}
|
||||
|
||||
public void setTestBeanProperty(String testBeanProperty) {
|
||||
this.testBeanProperty = testBeanProperty;
|
||||
}
|
||||
}
|
||||
|
||||
class TestBean2 {
|
||||
private String testBeanProperty;
|
||||
|
||||
public TestBean2() {
|
||||
testBeanProperty = "defaultTestBean2Property";
|
||||
}
|
||||
|
||||
public String getTestBeanProperty() {
|
||||
return testBeanProperty;
|
||||
}
|
||||
|
||||
public void setTestBeanProperty(String testBeanProperty) {
|
||||
this.testBeanProperty = testBeanProperty;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user