From 2de0f4b5b10627c53f85a895d310fdaa53c0d2b0 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Tue, 29 Jul 2014 17:44:28 +0200 Subject: [PATCH 01/11] This update enables struts to be used as JBoss AS 7/WildFly 8/JBoss EAP 6 module. --- .../xwork2/util/LocalizedTextUtil.java | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index 8256cfb0d8..dae9925824 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -38,7 +38,6 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArrayList; /** @@ -87,7 +86,8 @@ */ public class LocalizedTextUtil { - private static final List DEFAULT_RESOURCE_BUNDLES = new CopyOnWriteArrayList(); + private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); +// private static final List DEFAULT_RESOURCE_BUNDLES = new CopyOnWriteArrayList(); private static final Logger LOG = LoggerFactory.getLogger(LocalizedTextUtil.class); private static boolean reloadBundles = false; private static final ResourceBundle EMPTY_BUNDLE = new EmptyResourceBundle(); @@ -96,6 +96,7 @@ public class LocalizedTextUtil { private static ClassLoader delegatedClassLoader; private static final String RELOADED = "com.opensymphony.xwork2.util.LocalizedTextUtil.reloaded"; + private static final String XWORK_MESSAGES_BUNDLE = "com/opensymphony/xwork2/xwork-messages"; static { clearDefaultResourceBundles(); @@ -106,16 +107,12 @@ public class LocalizedTextUtil { * Clears the internal list of resource bundles. */ public static void clearDefaultResourceBundles() { - if (DEFAULT_RESOURCE_BUNDLES != null) { - synchronized (DEFAULT_RESOURCE_BUNDLES) { - DEFAULT_RESOURCE_BUNDLES.clear(); - DEFAULT_RESOURCE_BUNDLES.add("com/opensymphony/xwork2/xwork-messages"); - } - } else { - synchronized (DEFAULT_RESOURCE_BUNDLES) { - DEFAULT_RESOURCE_BUNDLES.add("com/opensymphony/xwork2/xwork-messages"); - } - } +// DEFAULT_RESOURCE_BUNDLES.clear(); +// DEFAULT_RESOURCE_BUNDLES.add(XWORK_MESSAGES_BUNDLE); + ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + List bundles = new ArrayList(); + classLoaderMap.put(ccl.hashCode(), bundles); + bundles.add(0, XWORK_MESSAGES_BUNDLE); } /** @@ -136,13 +133,20 @@ public static void setReloadBundles(boolean reloadBundles) { */ public static void addDefaultResourceBundle(String resourceBundleName) { //make sure this doesn't get added more than once - synchronized (DEFAULT_RESOURCE_BUNDLES) { - DEFAULT_RESOURCE_BUNDLES.remove(resourceBundleName); - DEFAULT_RESOURCE_BUNDLES.add(0, resourceBundleName); + synchronized (classLoaderMap) { + ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + List bundles = classLoaderMap.get(ccl.hashCode()); + if (bundles == null) { + bundles = new ArrayList(); + classLoaderMap.put(ccl.hashCode(), bundles); + bundles.add(XWORK_MESSAGES_BUNDLE); + } + bundles.remove(resourceBundleName); + bundles.add(0, resourceBundleName); } if (LOG.isDebugEnabled()) { - LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles = " + DEFAULT_RESOURCE_BUNDLES); + //LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles = " + DEFAULT_RESOURCE_BUNDLES); } } @@ -197,7 +201,7 @@ public static Locale localeFromString(String localeStr, Locale defaultLocale) { * @return a localized message based on the specified key, or null if no localized message can be found for it */ public static String findDefaultText(String aTextName, Locale locale) { - List localList = DEFAULT_RESOURCE_BUNDLES; + List localList = classLoaderMap.get(Thread.currentThread().getContextClassLoader().hashCode()); for (String bundleName : localList) { ResourceBundle bundle = findResourceBundle(bundleName, locale); @@ -252,26 +256,25 @@ public static ResourceBundle findResourceBundle(String aBundleName, Locale local if (!bundlesMap.containsKey(key)) { bundle = ResourceBundle.getBundle(aBundleName, locale, Thread.currentThread().getContextClassLoader()); bundlesMap.putIfAbsent(key, bundle); + } else { + bundle = bundlesMap.get(key); } - - bundle = bundlesMap.get(key); } catch (MissingResourceException ex) { if (delegatedClassLoader != null) { try { if (!bundlesMap.containsKey(key)) { bundle = ResourceBundle.getBundle(aBundleName, locale, delegatedClassLoader); bundlesMap.putIfAbsent(key, bundle); + } else { + bundle = bundlesMap.get(key); } - - bundle = bundlesMap.get(key); - } catch (MissingResourceException e) { bundle = EMPTY_BUNDLE; - bundlesMap.putIfAbsent(key, bundle); +// bundlesMap.putIfAbsent(key, bundle); } } else { bundle = EMPTY_BUNDLE; - bundlesMap.putIfAbsent(key, bundle); +// bundlesMap.putIfAbsent(key, bundle); } } return (bundle == EMPTY_BUNDLE) ? null : bundle; From 4586d1f148ef43c7582038306a626144c75d0e49 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Tue, 29 Jul 2014 17:46:04 +0200 Subject: [PATCH 02/11] Added pom's version as 2.3.16.4-SNAPSHOT --- xwork-core/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/xwork-core/pom.xml b/xwork-core/pom.xml index 710f635ec5..aac5da05ed 100644 --- a/xwork-core/pom.xml +++ b/xwork-core/pom.xml @@ -10,6 +10,7 @@ org.apache.struts.xwork xwork-core + 2.3.16.4-SNAPSHOT jar XWork: Core From c826d97cafafc9ce54e15745b23cd211e233c2fa Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Tue, 29 Jul 2014 18:44:50 +0200 Subject: [PATCH 03/11] Removed unused code, comments and variables. Also, added delegatedClassLoaderMap to handle delegatedClassLoader as per Tomcat. --- .../xwork2/util/LocalizedTextUtil.java | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index dae9925824..dbaef27438 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -87,14 +87,12 @@ public class LocalizedTextUtil { private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); -// private static final List DEFAULT_RESOURCE_BUNDLES = new CopyOnWriteArrayList(); private static final Logger LOG = LoggerFactory.getLogger(LocalizedTextUtil.class); private static boolean reloadBundles = false; - private static final ResourceBundle EMPTY_BUNDLE = new EmptyResourceBundle(); private static final ConcurrentMap bundlesMap = new ConcurrentHashMap(); private static final ConcurrentMap messageFormats = new ConcurrentHashMap(); + private static final ConcurrentMap delegatedClassLoaderMap = new ConcurrentHashMap(); - private static ClassLoader delegatedClassLoader; private static final String RELOADED = "com.opensymphony.xwork2.util.LocalizedTextUtil.reloaded"; private static final String XWORK_MESSAGES_BUNDLE = "com/opensymphony/xwork2/xwork-messages"; @@ -107,9 +105,7 @@ public class LocalizedTextUtil { * Clears the internal list of resource bundles. */ public static void clearDefaultResourceBundles() { -// DEFAULT_RESOURCE_BUNDLES.clear(); -// DEFAULT_RESOURCE_BUNDLES.add(XWORK_MESSAGES_BUNDLE); - ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + ClassLoader ccl = getThreadCurrentThreadGetContextClassLoader(); List bundles = new ArrayList(); classLoaderMap.put(ccl.hashCode(), bundles); bundles.add(0, XWORK_MESSAGES_BUNDLE); @@ -133,8 +129,9 @@ public static void setReloadBundles(boolean reloadBundles) { */ public static void addDefaultResourceBundle(String resourceBundleName) { //make sure this doesn't get added more than once + ClassLoader ccl = null; synchronized (classLoaderMap) { - ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + ccl = getThreadCurrentThreadGetContextClassLoader(); List bundles = classLoaderMap.get(ccl.hashCode()); if (bundles == null) { bundles = new ArrayList(); @@ -146,7 +143,7 @@ public static void addDefaultResourceBundle(String resourceBundleName) { } if (LOG.isDebugEnabled()) { - //LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles = " + DEFAULT_RESOURCE_BUNDLES); + LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles for the following classloader " + ccl.toString()); } } @@ -201,7 +198,7 @@ public static Locale localeFromString(String localeStr, Locale defaultLocale) { * @return a localized message based on the specified key, or null if no localized message can be found for it */ public static String findDefaultText(String aTextName, Locale locale) { - List localList = classLoaderMap.get(Thread.currentThread().getContextClassLoader().hashCode()); + List localList = classLoaderMap.get(getThreadCurrentThreadGetContextClassLoader().hashCode()); for (String bundleName : localList) { ResourceBundle bundle = findResourceBundle(bundleName, locale); @@ -240,8 +237,6 @@ public static String findDefaultText(String aTextName, Locale locale, Object[] p * Finds the given resorce bundle by it's name. *

* Will use Thread.currentThread().getContextClassLoader() as the classloader. - * If {@link #delegatedClassLoader} is defined and the bundle cannot be found the current - * classloader it will delegate to that. * * @param aBundleName the name of the bundle (usually it's FQN classname). * @param locale the locale. @@ -250,34 +245,32 @@ public static String findDefaultText(String aTextName, Locale locale, Object[] p public static ResourceBundle findResourceBundle(String aBundleName, Locale locale) { String key = createMissesKey(aBundleName, locale); - ResourceBundle bundle; + ResourceBundle bundle = null; + ClassLoader classLoader = getThreadCurrentThreadGetContextClassLoader(); try { + key = classLoader.hashCode()+key; + if (!bundlesMap.containsKey(key)) { - bundle = ResourceBundle.getBundle(aBundleName, locale, Thread.currentThread().getContextClassLoader()); + bundle = ResourceBundle.getBundle(aBundleName, locale, classLoader); bundlesMap.putIfAbsent(key, bundle); } else { bundle = bundlesMap.get(key); } } catch (MissingResourceException ex) { - if (delegatedClassLoader != null) { + if (delegatedClassLoaderMap.containsKey(classLoader.hashCode())) { try { if (!bundlesMap.containsKey(key)) { - bundle = ResourceBundle.getBundle(aBundleName, locale, delegatedClassLoader); + bundle = ResourceBundle.getBundle(aBundleName, locale, delegatedClassLoaderMap.get(classLoader.hashCode())); bundlesMap.putIfAbsent(key, bundle); } else { bundle = bundlesMap.get(key); } } catch (MissingResourceException e) { - bundle = EMPTY_BUNDLE; -// bundlesMap.putIfAbsent(key, bundle); } - } else { - bundle = EMPTY_BUNDLE; -// bundlesMap.putIfAbsent(key, bundle); } } - return (bundle == EMPTY_BUNDLE) ? null : bundle; + return bundle; } /** @@ -287,7 +280,7 @@ public static ResourceBundle findResourceBundle(String aBundleName, Locale local */ public static void setDelegatedClassLoader(final ClassLoader classLoader) { synchronized (bundlesMap) { - delegatedClassLoader = classLoader; + delegatedClassLoaderMap.put(getThreadCurrentThreadGetContextClassLoader().hashCode(), classLoader); } } @@ -297,7 +290,7 @@ public static void setDelegatedClassLoader(final ClassLoader classLoader) { * @param bundleName */ public static void clearBundle(final String bundleName) { - bundlesMap.remove(bundleName); + bundlesMap.remove(getThreadCurrentThreadGetContextClassLoader().hashCode() + bundleName); } @@ -819,7 +812,7 @@ private static void reloadBundles(Map context) { private static void clearTomcatCache() { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); + ClassLoader loader = getThreadCurrentThreadGetContextClassLoader(); // no need for compilation here. Class cl = loader.getClass(); @@ -896,6 +889,10 @@ public int hashCode() { } } + private static ClassLoader getThreadCurrentThreadGetContextClassLoader() { + return Thread.currentThread().getContextClassLoader(); + } + static class GetDefaultMessageReturnArg { String message; boolean foundInBundle; From d65270b9bb061bf16072e706f53060d3d9ab78ca Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Wed, 30 Jul 2014 11:42:46 +0200 Subject: [PATCH 04/11] Deleted internal versioning. --- xwork-core/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/xwork-core/pom.xml b/xwork-core/pom.xml index aac5da05ed..710f635ec5 100644 --- a/xwork-core/pom.xml +++ b/xwork-core/pom.xml @@ -10,7 +10,6 @@ org.apache.struts.xwork xwork-core - 2.3.16.4-SNAPSHOT jar XWork: Core From 00f424a3f6a36d75bb32bcbd5e9b95971fb88e7a Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Wed, 30 Jul 2014 12:42:47 +0200 Subject: [PATCH 05/11] Updates as stated in PR#20 comments. --- .../xwork2/util/LocalizedTextUtil.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index dbaef27438..953c6b2d47 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -105,7 +105,7 @@ public class LocalizedTextUtil { * Clears the internal list of resource bundles. */ public static void clearDefaultResourceBundles() { - ClassLoader ccl = getThreadCurrentThreadGetContextClassLoader(); + ClassLoader ccl = getCurrentThreadContextClassLoader(); List bundles = new ArrayList(); classLoaderMap.put(ccl.hashCode(), bundles); bundles.add(0, XWORK_MESSAGES_BUNDLE); @@ -131,7 +131,7 @@ public static void addDefaultResourceBundle(String resourceBundleName) { //make sure this doesn't get added more than once ClassLoader ccl = null; synchronized (classLoaderMap) { - ccl = getThreadCurrentThreadGetContextClassLoader(); + ccl = getCurrentThreadContextClassLoader(); List bundles = classLoaderMap.get(ccl.hashCode()); if (bundles == null) { bundles = new ArrayList(); @@ -143,7 +143,7 @@ public static void addDefaultResourceBundle(String resourceBundleName) { } if (LOG.isDebugEnabled()) { - LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles for the following classloader " + ccl.toString()); + LOG.debug("Added default resource bundle '{}' to default resource bundles for the following classloader '{}'", resourceBundleName, ccl.toString()); } } @@ -198,7 +198,7 @@ public static Locale localeFromString(String localeStr, Locale defaultLocale) { * @return a localized message based on the specified key, or null if no localized message can be found for it */ public static String findDefaultText(String aTextName, Locale locale) { - List localList = classLoaderMap.get(getThreadCurrentThreadGetContextClassLoader().hashCode()); + List localList = classLoaderMap.get(getCurrentThreadContextClassLoader().hashCode()); for (String bundleName : localList) { ResourceBundle bundle = findResourceBundle(bundleName, locale); @@ -243,14 +243,12 @@ public static String findDefaultText(String aTextName, Locale locale, Object[] p * @return the bundle, null if not found. */ public static ResourceBundle findResourceBundle(String aBundleName, Locale locale) { - String key = createMissesKey(aBundleName, locale); ResourceBundle bundle = null; - ClassLoader classLoader = getThreadCurrentThreadGetContextClassLoader(); + ClassLoader classLoader = getCurrentThreadContextClassLoader(); + String key = createMissesKey(String.valueOf(classLoader.hashCode()), aBundleName, locale); try { - key = classLoader.hashCode()+key; - if (!bundlesMap.containsKey(key)) { bundle = ResourceBundle.getBundle(aBundleName, locale, classLoader); bundlesMap.putIfAbsent(key, bundle); @@ -280,7 +278,7 @@ public static ResourceBundle findResourceBundle(String aBundleName, Locale local */ public static void setDelegatedClassLoader(final ClassLoader classLoader) { synchronized (bundlesMap) { - delegatedClassLoaderMap.put(getThreadCurrentThreadGetContextClassLoader().hashCode(), classLoader); + delegatedClassLoaderMap.put(getCurrentThreadContextClassLoader().hashCode(), classLoader); } } @@ -290,19 +288,20 @@ public static void setDelegatedClassLoader(final ClassLoader classLoader) { * @param bundleName */ public static void clearBundle(final String bundleName) { - bundlesMap.remove(getThreadCurrentThreadGetContextClassLoader().hashCode() + bundleName); + bundlesMap.remove(getCurrentThreadContextClassLoader().hashCode() + bundleName); } /** * Creates a key to used for lookup/storing in the bundle misses cache. * + * @param prefix the prefix for the returning String - it is supposed to be the ClassLoader hash code. * @param aBundleName the name of the bundle (usually it's FQN classname). * @param locale the locale. * @return the key to use for lookup/storing in the bundle misses cache. */ - private static String createMissesKey(String aBundleName, Locale locale) { - return aBundleName + "_" + locale.toString(); + private static String createMissesKey(String prefix, String aBundleName, Locale locale) { + return prefix + aBundleName + "_" + locale.toString(); } /** @@ -812,7 +811,7 @@ private static void reloadBundles(Map context) { private static void clearTomcatCache() { - ClassLoader loader = getThreadCurrentThreadGetContextClassLoader(); + ClassLoader loader = getCurrentThreadContextClassLoader(); // no need for compilation here. Class cl = loader.getClass(); @@ -889,7 +888,7 @@ public int hashCode() { } } - private static ClassLoader getThreadCurrentThreadGetContextClassLoader() { + private static ClassLoader getCurrentThreadContextClassLoader() { return Thread.currentThread().getContextClassLoader(); } From da9afaf84e367f0e195cc8f221778eb798595fb6 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Wed, 30 Jul 2014 14:29:03 +0200 Subject: [PATCH 06/11] Updates as stated in PR#20 comments. --- .../xwork2/util/LocalizedTextUtil.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index 953c6b2d47..4e9d4eb1da 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -86,7 +86,7 @@ */ public class LocalizedTextUtil { - private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); + private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); private static final Logger LOG = LoggerFactory.getLogger(LocalizedTextUtil.class); private static boolean reloadBundles = false; private static final ConcurrentMap bundlesMap = new ConcurrentHashMap(); @@ -106,9 +106,9 @@ public class LocalizedTextUtil { */ public static void clearDefaultResourceBundles() { ClassLoader ccl = getCurrentThreadContextClassLoader(); - List bundles = new ArrayList(); + Set bundles = new HashSet(); classLoaderMap.put(ccl.hashCode(), bundles); - bundles.add(0, XWORK_MESSAGES_BUNDLE); + bundles.add(XWORK_MESSAGES_BUNDLE); } /** @@ -132,14 +132,13 @@ public static void addDefaultResourceBundle(String resourceBundleName) { ClassLoader ccl = null; synchronized (classLoaderMap) { ccl = getCurrentThreadContextClassLoader(); - List bundles = classLoaderMap.get(ccl.hashCode()); + Set bundles = classLoaderMap.get(ccl.hashCode()); if (bundles == null) { - bundles = new ArrayList(); + bundles = new HashSet(); classLoaderMap.put(ccl.hashCode(), bundles); bundles.add(XWORK_MESSAGES_BUNDLE); } - bundles.remove(resourceBundleName); - bundles.add(0, resourceBundleName); + bundles.add(resourceBundleName); } if (LOG.isDebugEnabled()) { @@ -198,7 +197,7 @@ public static Locale localeFromString(String localeStr, Locale defaultLocale) { * @return a localized message based on the specified key, or null if no localized message can be found for it */ public static String findDefaultText(String aTextName, Locale locale) { - List localList = classLoaderMap.get(getCurrentThreadContextClassLoader().hashCode()); + Set localList = classLoaderMap.get(getCurrentThreadContextClassLoader().hashCode()); for (String bundleName : localList) { ResourceBundle bundle = findResourceBundle(bundleName, locale); From 9254aaaefefbf0cc523c1bd710b60b9b815825e2 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Wed, 30 Jul 2014 14:29:47 +0200 Subject: [PATCH 07/11] Updates as stated in PR#20 comments - removed test method testDefaultMessageOverride. --- .../com/opensymphony/xwork2/util/LocalizedTextUtilTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java index bac41ba413..22982973d7 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java @@ -133,6 +133,11 @@ public void testDefaultMessage() throws Exception { assertEquals("Error during Action invocation", message); } + /* + Stated that property's management does not care about ordering, + in fact it's held by a Set instead of List, + you cannot override a previous bundle, thus the test is wrong. + public void testDefaultMessageOverride() throws Exception { String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault()); assertEquals("Error during Action invocation", message); @@ -142,6 +147,7 @@ public void testDefaultMessageOverride() throws Exception { message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault()); assertEquals("Testing resource bundle override", message); } + */ public void testFindTextInChildProperty() throws Exception { ModelDriven action = new ModelDrivenAction2(); From 939a3e20400d915de809fbd0e304c1bd2fac5813 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Thu, 31 Jul 2014 12:08:30 +0200 Subject: [PATCH 08/11] Updates as stated in PR#20 comments - synchronized code block inside addDefaultResourceBundle method using XWORK_MESSAGES_BUNDLE. --- .../java/com/opensymphony/xwork2/util/LocalizedTextUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index 4e9d4eb1da..321945011d 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -130,7 +130,7 @@ public static void setReloadBundles(boolean reloadBundles) { public static void addDefaultResourceBundle(String resourceBundleName) { //make sure this doesn't get added more than once ClassLoader ccl = null; - synchronized (classLoaderMap) { + synchronized (XWORK_MESSAGES_BUNDLE) { ccl = getCurrentThreadContextClassLoader(); Set bundles = classLoaderMap.get(ccl.hashCode()); if (bundles == null) { From be7201062b472b3328ed6ae008997ce1d03d19a9 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Tue, 5 Aug 2014 15:48:12 +0200 Subject: [PATCH 09/11] Added the FIXME notation --- .../com/opensymphony/xwork2/util/LocalizedTextUtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java index 22982973d7..02e493df61 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java @@ -133,7 +133,7 @@ public void testDefaultMessage() throws Exception { assertEquals("Error during Action invocation", message); } - /* + /* FIXME Stated that property's management does not care about ordering, in fact it's held by a Set instead of List, you cannot override a previous bundle, thus the test is wrong. From c74f283626ac0c08f66e52b6102fcaa3d6614903 Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Mon, 18 Aug 2014 16:25:42 +0200 Subject: [PATCH 10/11] Restored the ordering feature. --- .../xwork2/util/LocalizedTextUtil.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java index 321945011d..9aad92864b 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/LocalizedTextUtil.java @@ -86,7 +86,7 @@ */ public class LocalizedTextUtil { - private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); + private static final ConcurrentMap> classLoaderMap = new ConcurrentHashMap>(); private static final Logger LOG = LoggerFactory.getLogger(LocalizedTextUtil.class); private static boolean reloadBundles = false; private static final ConcurrentMap bundlesMap = new ConcurrentHashMap(); @@ -106,9 +106,9 @@ public class LocalizedTextUtil { */ public static void clearDefaultResourceBundles() { ClassLoader ccl = getCurrentThreadContextClassLoader(); - Set bundles = new HashSet(); + List bundles = new ArrayList(); classLoaderMap.put(ccl.hashCode(), bundles); - bundles.add(XWORK_MESSAGES_BUNDLE); + bundles.add(0, XWORK_MESSAGES_BUNDLE); } /** @@ -132,13 +132,14 @@ public static void addDefaultResourceBundle(String resourceBundleName) { ClassLoader ccl = null; synchronized (XWORK_MESSAGES_BUNDLE) { ccl = getCurrentThreadContextClassLoader(); - Set bundles = classLoaderMap.get(ccl.hashCode()); + List bundles = classLoaderMap.get(ccl.hashCode()); if (bundles == null) { - bundles = new HashSet(); + bundles = new ArrayList(); classLoaderMap.put(ccl.hashCode(), bundles); bundles.add(XWORK_MESSAGES_BUNDLE); } - bundles.add(resourceBundleName); + bundles.remove(resourceBundleName); + bundles.add(0, resourceBundleName); } if (LOG.isDebugEnabled()) { @@ -197,7 +198,7 @@ public static Locale localeFromString(String localeStr, Locale defaultLocale) { * @return a localized message based on the specified key, or null if no localized message can be found for it */ public static String findDefaultText(String aTextName, Locale locale) { - Set localList = classLoaderMap.get(getCurrentThreadContextClassLoader().hashCode()); + List localList = classLoaderMap.get(Thread.currentThread().getContextClassLoader().hashCode()); for (String bundleName : localList) { ResourceBundle bundle = findResourceBundle(bundleName, locale); From 685bb1d069623d59103187d7fee4671e31c353cb Mon Sep 17 00:00:00 2001 From: Luigi Fugaro Date: Mon, 18 Aug 2014 16:27:13 +0200 Subject: [PATCH 11/11] Previous commit restored the ordering feature, thus testFindTextInChildProperty test also has been restored. --- .../com/opensymphony/xwork2/util/LocalizedTextUtilTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java index 02e493df61..bac41ba413 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/util/LocalizedTextUtilTest.java @@ -133,11 +133,6 @@ public void testDefaultMessage() throws Exception { assertEquals("Error during Action invocation", message); } - /* FIXME - Stated that property's management does not care about ordering, - in fact it's held by a Set instead of List, - you cannot override a previous bundle, thus the test is wrong. - public void testDefaultMessageOverride() throws Exception { String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault()); assertEquals("Error during Action invocation", message); @@ -147,7 +142,6 @@ public void testDefaultMessageOverride() throws Exception { message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault()); assertEquals("Testing resource bundle override", message); } - */ public void testFindTextInChildProperty() throws Exception { ModelDriven action = new ModelDrivenAction2();