Merged V2.2 to HEAD 8290: Merged V2.1-A to V2.2 8229: AWC-1149: Resource bundles in AMP files

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8323 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2008-02-19 12:52:48 +00:00
parent f45bccdbd8
commit 12656d59b8
5 changed files with 286 additions and 145 deletions

View File

@@ -688,7 +688,7 @@ public class Application
{ {
locale = Locale.getDefault(); locale = Locale.getDefault();
} }
bundle = ResourceBundleWrapper.getResourceBundleWrapper(session.getServletContext()).getResourceBundle(MESSAGE_BUNDLE, locale); bundle = ResourceBundleWrapper.getResourceBundle(session.getServletContext(), MESSAGE_BUNDLE, locale);
session.setAttribute(MESSAGE_BUNDLE, bundle); session.setAttribute(MESSAGE_BUNDLE, bundle);
} }
@@ -719,7 +719,7 @@ public class Application
{ {
locale = Locale.getDefault(); locale = Locale.getDefault();
} }
bundle = ResourceBundleWrapper.getResourceBundleWrapper(FacesContextUtils.getRequiredWebApplicationContext(context).getServletContext()).getResourceBundle(MESSAGE_BUNDLE, locale); bundle = ResourceBundleWrapper.getResourceBundle(FacesContextUtils.getRequiredWebApplicationContext(context).getServletContext(), MESSAGE_BUNDLE, locale);
session.put(MESSAGE_BUNDLE, bundle); session.put(MESSAGE_BUNDLE, bundle);
} }

View File

@@ -0,0 +1,28 @@
/**
*
*/
package org.alfresco.web.app;
import java.util.List;
/**
* Resource bundle bootstrap bean
*
* @author Roy Wetherall
*/
public class ResourceBundleBootstrap
{
/**
* Set the resource bundles to be registered. This should be a list of resource
* bundle base names whose content will be made available to the web client.
*
* @param resourceBundles the resource bundles
*/
public void setResourceBundles(List<String> resourceBundles)
{
for (String resourceBundle : resourceBundles)
{
ResourceBundleWrapper.addResourceBundle(resourceBundle);
}
}
}

View File

@@ -25,7 +25,9 @@
package org.alfresco.web.app; package org.alfresco.web.app;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@@ -52,58 +54,118 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
public final class ResourceBundleWrapper extends ResourceBundle implements Serializable public final class ResourceBundleWrapper extends ResourceBundle implements Serializable
{ {
private static final long serialVersionUID = -3230653664902689948L; private static final long serialVersionUID = -3230653664902689948L;
private static Log logger = LogFactory.getLog(ResourceBundleWrapper.class); private static Log logger = LogFactory.getLog(ResourceBundleWrapper.class);
private String name; /** List of custom bundle names */
private Locale locale; private static List<String> addedBundleNames = new ArrayList<String>(10);
transient private ResourceBundle delegate; /** List of delegate resource bundles */
transient private ResourceBundle delegateCustom; transient private List<ResourceBundle> delegates;
private MessageService messageService;
public static final String BEAN_RESOURCE_BUNDLE_WRAPPER = "resourceBundleWrapper";
public static final String BEAN_RESOURCE_MESSAGE_SERVICE = "messageService";
public static final String PATH = "app:company_home/app:dictionary/app:webclient_extension"; public static final String PATH = "app:company_home/app:dictionary/app:webclient_extension";
public ResourceBundleWrapper(MessageService messageService)
{
this.messageService = messageService;
}
// Helper to get the ResourceBundleWrapper instance with access to the repository
public static ResourceBundleWrapper getResourceBundleWrapper(ServletContext context)
{
return (ResourceBundleWrapper)WebApplicationContextUtils.getRequiredWebApplicationContext(context).getBean(
BEAN_RESOURCE_BUNDLE_WRAPPER);
}
/** /**
* Constructor * Constructor
* *
* @param bundle The ResourceBundle to route calls too * @param bundles the resource bundles including the default, custom and any added
* @param customBundle A custom version of bundle to look in if the string is
* not found in bundle
*/ */
private ResourceBundleWrapper(String name, Locale locale) private ResourceBundleWrapper(List<ResourceBundle> bundles)
{ {
this.name = name; this.delegates = bundles;
this.locale = locale;
retreiveBundles();
} }
private void retreiveBundles() /**
* @see java.util.ResourceBundle#getKeys()
*/
public Enumeration<String> getKeys()
{ {
if (this.delegates.size() == 1)
{
return this.delegates.get(0).getKeys();
}
else
{
Vector<String> allKeys = new Vector<String>(100, 2);
for (ResourceBundle delegate : this.delegates)
{
Enumeration<String> keys = delegate.getKeys();
while(keys.hasMoreElements() == true)
{
allKeys.add(keys.nextElement());
}
}
return allKeys.elements();
}
}
/**
* @see java.util.ResourceBundle#handleGetObject(java.lang.String)
*/
protected Object handleGetObject(String key)
{
Object result = null;
for (ResourceBundle delegate : this.delegates)
{
try
{
// Try and lookup the key from the resource bundle
result = delegate.getObject(key);
if (result != null)
{
break;
}
}
catch (MissingResourceException mre)
{
// ignore as this means the key was not present
}
}
// if the key was not found return a default string
if (result == null)
{
if (logger.isWarnEnabled() == true)
{
logger.warn("Failed to find I18N message string key: " + key);
}
result = "$$" + key + "$$";
}
return result;
}
/**
* Factory method to get a named wrapped resource bundle for a particular locale.
*
* @param servletContext ServletContext
* @param name Bundle name
* @param locale Locale to retrieve bundle for
*
* @return Wrapped ResourceBundle instance for specified locale
*/
public static ResourceBundle getResourceBundle(ServletContext servletContext, String name, Locale locale)
{
List<ResourceBundle> bundles = new ArrayList<ResourceBundle>(ResourceBundleWrapper.addedBundleNames.size() + 2);
// Load the default bundle
ResourceBundle bundle = ResourceBundle.getBundle(name, locale); ResourceBundle bundle = ResourceBundle.getBundle(name, locale);
if (bundle == null) if (bundle == null)
{ {
throw new AlfrescoRuntimeException("Unable to load Alfresco messages bundle: " + name); throw new AlfrescoRuntimeException("Unable to load Alfresco messages bundle: " + name);
} }
bundles.add(bundle);
// also look up the custom version of the bundle in the extension package // also look up the custom version of the bundle in the extension package
ResourceBundle customBundle = null; ResourceBundle customBundle = null;
if (servletContext != null)
{
MessageService messageService = (MessageService)WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).getBean(BEAN_RESOURCE_MESSAGE_SERVICE);
// first try in the repo otherwise try the classpath // first try in the repo otherwise try the classpath
StoreRef storeRef = null; StoreRef storeRef = null;
String path = null; String path = null;
@@ -133,122 +195,69 @@ public final class ResourceBundleWrapper extends ResourceBundle implements Seria
// for now ... ignore the error, cannot be found or read from repo // for now ... ignore the error, cannot be found or read from repo
logger.debug("Custom Web Client properties not found: " + storeRef + path); logger.debug("Custom Web Client properties not found: " + storeRef + path);
} }
}
if (customBundle == null) if (customBundle == null)
{ {
// classpath // also look up the custom version of the bundle in the extension package
String customName = determineCustomBundleName(name); String customName = determineCustomBundleName(name);
try try
{ {
customBundle = ResourceBundle.getBundle(customName, locale); customBundle = ResourceBundle.getBundle(customName, locale);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled()== true)
{
logger.debug("Located and loaded custom bundle: " + customName); logger.debug("Located and loaded custom bundle: " + customName);
} }
}
catch (MissingResourceException mre) catch (MissingResourceException mre)
{ {
// ignore the error, just leave custom bundle as null // ignore the error, just leave custom bundle as null
} }
} }
this.delegate = bundle; // Add the custom bundle to the list
this.delegateCustom = customBundle; if (customBundle != null)
{
bundles.add(customBundle);
} }
/** // Add any additional bundles
* @see java.util.ResourceBundle#getKeys() for (String bundleName : ResourceBundleWrapper.addedBundleNames)
*/
public Enumeration<String> getKeys()
{ {
if (this.delegate == null)
{
// restore if the session was [de]serialised - as bundles themselves are not serialised
retreiveBundles();
}
if (this.delegateCustom == null)
{
return this.delegate.getKeys();
}
else
{
// get existing keys
Enumeration<String> keys = this.delegate.getKeys();
Enumeration<String> customKeys = this.delegateCustom.getKeys();
// combine keys into one list
Vector<String> allKeys = new Vector<String>(100, 2);
while (keys.hasMoreElements())
{
allKeys.add(keys.nextElement());
}
while (customKeys.hasMoreElements())
{
allKeys.add(customKeys.nextElement());
}
return allKeys.elements();
}
}
/**
* @see java.util.ResourceBundle#handleGetObject(java.lang.String)
*/
protected Object handleGetObject(String key)
{
Object result = null;
if (this.delegate == null)
{
// restore if the session was [de]serialised - as bundles themselves are not serialised
retreiveBundles();
}
try try
{ {
result = this.delegate.getObject(key); // Load the added bundle
} ResourceBundle addedBundle = ResourceBundle.getBundle(bundleName, locale);
catch (MissingResourceException err) bundles.add(addedBundle);
if (logger.isDebugEnabled())
{ {
// if the string wasn't found in the normal bundle logger.debug("Located and loaded added bundle: " + bundleName);
// try the custom bundle if there is one
try
{
if (this.delegateCustom != null)
{
result = this.delegateCustom.getObject(key);
} }
} }
catch (MissingResourceException mre) catch (MissingResourceException mre)
{ {
// don't do anything here, dealt with below // ignore the error, just log some debug info
} if (logger.isDebugEnabled())
// if the key was not found return a default string
if (result == null)
{ {
if (logger.isWarnEnabled()) logger.debug("Unable to load added bundle: " + bundleName);
logger.warn("Failed to find I18N message string key: " + key); }
result = "$$" + key + "$$";
} }
} }
return result; // apply our wrapper to catch MissingResourceException
return new ResourceBundleWrapper(bundles);
} }
/** /**
* Factory method to get a named wrapped resource bundle for a particular locale. * Adds a resource bundle to the collection of custom bundles available
* *
* @param name Bundle name * @param name the name of the resource bundle
* @param locale Locale to retrieve bundle for
*
* @return Wrapped ResourceBundle instance for specified locale
*/ */
public static ResourceBundle getResourceBundle(String name, Locale locale) public static void addResourceBundle(String name)
{ {
// apply our wrapper to catch MissingResourceException ResourceBundleWrapper.addedBundleNames.add(name);
return new ResourceBundleWrapper(name, locale);
} }
/** /**

View File

@@ -0,0 +1,101 @@
/**
*
*/
package org.alfresco.web.app;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import junit.framework.TestCase;
/**
* Unit test for resource bundle wrapper
*
* @author Roy Wetherall
*/
public class ResourceBundleWrapperTest extends TestCase
{
private static final String BUNDLE_NAME = "org.alfresco.web.app.resourceBundleWrapperTest";
private static final String KEY_1 = "test_key_one";
private static final String KEY_2 = "test_key_two";
private static final String MSG_1 = "Test Key One";
private static final String MSG_2 = "Test Key Two";
/**
* Test adding the bundles
*/
public void testAddingBundles()
{
// Check that the string's are not added to the bundle
ResourceBundle before = ResourceBundleWrapper.getResourceBundle(null, "alfresco.messages.webclient", Locale.US);
Enumeration<String> keys = before.getKeys();
assertFalse(containsValue(keys, KEY_1));
assertFalse(containsValue(keys, KEY_2));
try
{
before.getString(KEY_1);
fail("Not expecting the key to be there");
}
catch (Throwable exception){};
try
{
before.getString(KEY_2);
fail("Not expecting the key to be there");
}
catch (Throwable exception){};
// Add an additional resource bundle
ResourceBundleWrapper.addResourceBundle(BUNDLE_NAME);
// Check that the string's are now added to the bundle
ResourceBundle after = ResourceBundleWrapper.getResourceBundle(null, "alfresco.messages.webclient", Locale.US);
Enumeration<String> keys2 = after.getKeys();
assertTrue(containsValue(keys2, KEY_1));
assertEquals(after.getString(KEY_1), MSG_1);
assertEquals(after.getString(KEY_2), MSG_2);
}
/**
* Test the bootstrap bean
*/
public void testBootstrap()
{
// Use the bootstrap bean to add the bundles
List<String> bundles = new ArrayList<String>(1);
bundles.add(BUNDLE_NAME);
ResourceBundleBootstrap bootstrap = new ResourceBundleBootstrap();
bootstrap.setResourceBundles(bundles);
// Check that the string's are now added to the bundle
ResourceBundle after = ResourceBundleWrapper.getResourceBundle(null, "alfresco.messages.webclient", Locale.US);
Enumeration<String> keys2 = after.getKeys();
assertTrue(containsValue(keys2, KEY_1));
assertTrue(containsValue(keys2, KEY_2));
assertEquals(after.getString(KEY_1), MSG_1);
assertEquals(after.getString(KEY_2), MSG_2);
}
/**
* Check whether the list contains the values
*
* @param values list of values to check
* @param value value to look for
* @return boolean true if value contained, false otherwise
*/
private boolean containsValue(Enumeration<String> values, String value)
{
boolean result = false;
while (values.hasMoreElements() == true)
{
if (values.nextElement().equals(value) == true)
{
result = true;
break;
}
}
return result;
}
}

View File

@@ -0,0 +1,3 @@
test_key_one=Test Key One
test_key_two=Test Key Two
test_key_three=Test Key Three