mirror of
https://github.com/apache/struts.git
synced 2026-08-06 15:17:00 +00:00
Updated commit based on feedback, plus a few minor changes:
- Changed formatting as per review. - Added null guard for unlikely dereference in clearTomcatCache() logging statement. - Added a unit test for basic correctness check and better code coverage.
This commit is contained in:
@@ -336,7 +336,6 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
*
|
||||
* Note: With Java 9+, calling this method may result in "Illegal reflective access" warnings. Be aware
|
||||
* its logic may fail in a future version of Java that blocks the reflection calls needed for this method.
|
||||
* {<code></code>
|
||||
*/
|
||||
private void clearTomcatCache() {
|
||||
ClassLoader loader = getCurrentThreadContextClassLoader();
|
||||
@@ -345,8 +344,8 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
Class superCl = cl.getSuperclass();
|
||||
|
||||
try {
|
||||
if ( (TOMCAT_WEBAPP_CLASSLOADER.equals(cl.getName()) || TOMCAT_PARALLEL_WEBAPP_CLASSLOADER.equals(cl.getName())) &&
|
||||
(superCl != null && TOMCAT_WEBAPP_CLASSLOADER_BASE.equals(superCl.getName())) ) {
|
||||
if ((TOMCAT_WEBAPP_CLASSLOADER.equals(cl.getName()) || TOMCAT_PARALLEL_WEBAPP_CLASSLOADER.equals(cl.getName())) &&
|
||||
(superCl != null && TOMCAT_WEBAPP_CLASSLOADER_BASE.equals(superCl.getName()))) {
|
||||
// The classloader name and superclass name match the expecations for a Tomcat classloader.
|
||||
// Expect the classloader superclass to have the field, otherwise fallback to the classloader class if the field is not found.
|
||||
clearMap(superCl, loader, TOMCAT_RESOURCE_ENTRIES_FIELD);
|
||||
@@ -363,7 +362,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
LOG.warn("Couldn't clear tomcat cache using {}", cl.getName(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Couldn't clear tomcat cache using {}", superCl.getName(), e);
|
||||
LOG.warn("Couldn't clear tomcat cache using {}", (superCl != null ? superCl.getName() : null), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +327,50 @@ public class StrutsLocalizedTextProviderTest extends XWorkTestCase {
|
||||
testStrutsLocalizedTextProvider.callClearMissingBundlesCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test to confirm the basic behaviour of bundle reload methods provided to
|
||||
* StrutsLocalizedTextProvider (from AbstractLocalizedTextProvider).
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public void testLocalizedTextProviderReloadMethods() {
|
||||
TestStrutsLocalizedTextProvider testStrutsLocalizedTextProvider = new TestStrutsLocalizedTextProvider();
|
||||
assertTrue("testStrutsLocalizedTextProvider not instance of AbstractLocalizedTextProvider ?",
|
||||
testStrutsLocalizedTextProvider instanceof AbstractLocalizedTextProvider);
|
||||
assertEquals("testStrutsLocalizedTextProvider starting default bundle map size not 0 before any retrievals ?",
|
||||
0, testStrutsLocalizedTextProvider.currentBundlesMapSize());
|
||||
|
||||
// Access the two default bundles to populate their cache entries and test bundle map size.
|
||||
ResourceBundle tempBundle = testStrutsLocalizedTextProvider.findResourceBundle(
|
||||
TestStrutsLocalizedTextProvider.XWORK_MESSAGES_BUNDLE, Locale.ENGLISH);
|
||||
assertNotNull("XWORK_MESSAGES_BUNDLE retrieval null ?", tempBundle);
|
||||
tempBundle = testStrutsLocalizedTextProvider.findResourceBundle(
|
||||
TestStrutsLocalizedTextProvider.STRUTS_MESSAGES_BUNDLE, Locale.ENGLISH);
|
||||
assertNotNull("STRUTS_MESSAGES_BUNDLE retrieval null ?", tempBundle);
|
||||
assertEquals("testStrutsLocalizedTextProvider bundle map size not 2 after retrievals ?",
|
||||
2, testStrutsLocalizedTextProvider.currentBundlesMapSize());
|
||||
|
||||
// Force a bundle reload call for code coverage and to confirm it causes the bundle map to be emptied.
|
||||
assertNotNull("ActionContext is somehow null ?", ActionContext.getContext());
|
||||
boolean bundlesReloadedBeforeCall = testStrutsLocalizedTextProvider.getBundlesReloadedIndicatorValue();
|
||||
assertFalse("Bundles reload value true before forced reload ?", bundlesReloadedBeforeCall);
|
||||
testStrutsLocalizedTextProvider.callReloadBundlesForceReload();
|
||||
boolean bundlesReloadedAfterCall = testStrutsLocalizedTextProvider.getBundlesReloadedIndicatorValue();
|
||||
assertTrue("Bundles reload value false after forced reload ?", bundlesReloadedAfterCall);
|
||||
assertEquals("testStrutsLocalizedTextProvider bundle map size not 0 after reload (which should clear it) ?",
|
||||
0, testStrutsLocalizedTextProvider.currentBundlesMapSize());
|
||||
|
||||
// Access the two default bundles again (after reload) to populate their cache entries and test bundle map size.
|
||||
tempBundle = testStrutsLocalizedTextProvider.findResourceBundle(
|
||||
TestStrutsLocalizedTextProvider.XWORK_MESSAGES_BUNDLE, Locale.ENGLISH);
|
||||
assertNotNull("XWORK_MESSAGES_BUNDLE retrieval null ?", tempBundle);
|
||||
tempBundle = testStrutsLocalizedTextProvider.findResourceBundle(
|
||||
TestStrutsLocalizedTextProvider.STRUTS_MESSAGES_BUNDLE, Locale.ENGLISH);
|
||||
assertNotNull("STRUTS_MESSAGES_BUNDLE retrieval null ?", tempBundle);
|
||||
assertEquals("testStrutsLocalizedTextProvider bundle map size not 2 after retrievals ?",
|
||||
2, testStrutsLocalizedTextProvider.currentBundlesMapSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -352,6 +396,13 @@ public class StrutsLocalizedTextProviderTest extends XWorkTestCase {
|
||||
*/
|
||||
class TestStrutsLocalizedTextProvider extends StrutsLocalizedTextProvider {
|
||||
|
||||
/**
|
||||
* Some test correctness depends on this {@link #RELOADED} value matching that of the private ancestor
|
||||
* field {@link AbstractLocalizedTextProvider#RELOADED}. If the ancestor field value changes, ensure this
|
||||
* field's value is updated to match it exactly.
|
||||
*/
|
||||
private static final String RELOADED = "com.opensymphony.xwork2.util.LocalizedTextProvider.reloaded";
|
||||
|
||||
public void callClearBundleNoLocale(String bundleName) {
|
||||
super.clearBundle(bundleName);
|
||||
}
|
||||
@@ -367,5 +418,32 @@ public class StrutsLocalizedTextProviderTest extends XWorkTestCase {
|
||||
public int currentBundlesMapSize() {
|
||||
return super.bundlesMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to force the resource bundles to be reloaded, even if configuration would otherwise prevent it.
|
||||
* It will preserve the current reloadBundles state, attempt to force a reload and then restore the
|
||||
* original reloadBundles value.
|
||||
*/
|
||||
public void callReloadBundlesForceReload() {
|
||||
final boolean originalReloadState = super.reloadBundles;
|
||||
try {
|
||||
super.setReloadBundles(Boolean.TRUE.toString());
|
||||
super.reloadBundles();
|
||||
} finally {
|
||||
super.setReloadBundles(Boolean.toString(originalReloadState));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the resource bundles reloaded state from the context, provided that one was
|
||||
* previously set. If no value is found, the result will be false (same as if bundles had not been reloaded).
|
||||
*
|
||||
* @return true if resource bundles reloaded indicator is true, false otherwise (including if value was never set).
|
||||
*/
|
||||
public boolean getBundlesReloadedIndicatorValue() {
|
||||
final ActionContext actionContext = ActionContext.getContext();
|
||||
final Object reloadedObject = actionContext.get(RELOADED);
|
||||
return ((reloadedObject instanceof Boolean) ? ((Boolean) reloadedObject).booleanValue() : false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user