Anonymous avatar Anonymous committed dc4046e

Fixed XW-377 and polished javadoc

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@989 e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (3)

src/java/com/opensymphony/xwork/util/LocalizedTextUtil.java

     }
 
 
+    /**
+     * Clears the internal list of resource bundles.
+     */
     public static void clearDefaultResourceBundles() {
+    	if (DEFAULT_RESOURCE_BUNDLES != null) {
+    		DEFAULT_RESOURCE_BUNDLES.clear();
+    	}
         DEFAULT_RESOURCE_BUNDLES = Collections.synchronizedList(new ArrayList());
         DEFAULT_RESOURCE_BUNDLES.add("com/opensymphony/xwork/xwork-messages");
     }
 
+    /**
+     * Should resorce bundles be reloaded.
+     * <p/>
+     * In WW see <code>webwork.i18n.reload</code> property.
+     * @param reloadBundles  reload bundles?  
+     */
     public static void setReloadBundles(boolean reloadBundles) {
         LocalizedTextUtil.reloadBundles = reloadBundles;
     }
 
+    /**
+     * Add's the bundle to the internal list of default bundles.
+     * <p/>
+     * If the bundle already exists in the list it will be readded.
+     * 
+     * @param resourceBundleName   the name of the bundle to add.
+     */
     public static void addDefaultResourceBundle(String resourceBundleName) {
         //make sure this doesn't get added more than once
         DEFAULT_RESOURCE_BUNDLES.remove(resourceBundleName);
         DEFAULT_RESOURCE_BUNDLES.add(0, resourceBundleName);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("Added default resource bundle " + resourceBundleName + ", default resource bundles = " + DEFAULT_RESOURCE_BUNDLES);
+            LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles = " + DEFAULT_RESOURCE_BUNDLES);
         }
     }
 
      * @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 = new ArrayList(DEFAULT_RESOURCE_BUNDLES);
         List localList = DEFAULT_RESOURCE_BUNDLES; // it isn't sync'd, but this is so rare, let's do it anyway
 
         for (Iterator iterator = localList.iterator(); iterator.hasNext();) {
      * @return A formatted 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, Object[] params) {
-
         String defaultText = findDefaultText(aTextName, locale);
         if (defaultText != null) {
             MessageFormat mf = buildMessageFormat(defaultText, locale);
         return null;
     }
 
+    /**
+     * Finds the given resorce bundle by it's name.
+     * <p/>
+     * Will use <code>Thread.currentThread().getContextClassLoader()</code> as the classloader.
+     * 
+     * @param aBundleName  the name of the bundle (usually it's FQN classname).
+     * @param locale       the locale.
+     * @return  the bundle, <tt>null</tt> if not found.
+     */
     public static ResourceBundle findResourceBundle(String aBundleName, Locale locale) {
         synchronized (misses) {
             try {
      * <p/>
      * If a message is found, it will also be interpolated.  Anything within <code>${...}</code>
      * will be treated as an OGNL expression and evaluated as such.
+     * <p/>
+     * If a message is <b>not</b> found a WARN log will be logged.
      *
      * @param aClass         the class whose name to use as the start point for the search
      * @param aTextName      the key to find the text message for
             }
         }
 
-        String result = null;
         // get default
+        GetDefaultMessageReturnArg result = null;
         if (indexedTextName == null) {
             result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage);
         } else {
-            msg = getDefaultMessage(aTextName, locale, valueStack, args, null);
-
-            if (msg != null) {
-                return msg;
+            result = getDefaultMessage(aTextName, locale, valueStack, args, null);
+            if (result.message != null) {
+                return result.message;
             }
-
             result = getDefaultMessage(indexedTextName, locale, valueStack, args, defaultMessage);
         }
-        if ( result != null && result.equals(defaultMessage)) {
-            LOG.warn("Unable to find text for key '" + aTextName + "' in '" + aClass + "' and locale '" + locale + "'");
-        }
-        return result;
+        
+        // could we find the text, if not log a warn
+        if (unableToFindTextForKey(result)) {
+        	String warn = "Unable to find text for key '" + aTextName + "' ";
+        	if (indexedTextName != null) {
+        		warn += " or indexed key '" + indexedTextName + "' ";
+        	}
+        	warn += "in class '" + aClass.getName() + "' and locale '" + locale + "'";
+            LOG.warn(warn);
+        }
+        
+        return result != null ? result.message : null;
+    }
+    
+    /**
+     * Determines if we found the text in the bundles.
+     * 
+     * @param result   the result so far
+     * @param locale   the locale
+     * @param key1     the first key used for lookup
+     * @param key2     the second key (indexed) used for kookup
+     * @param defaultMessage  the provided default message
+     * @return  <tt>true</tt> if we could <b>not</b> find the text, <tt>false</tt> if the text was found (=success). 
+     */
+    private static boolean unableToFindTextForKey(GetDefaultMessageReturnArg result) {
+    	if (result == null || result.message == null) {
+    		return true;
+    	}
+    	
+		// did we find it in the bundle, then no problem?
+    	if (result.foundInBundle) {
+			return false;
+		}
+    	
+    	// not found in bundle
+    	return true;
     }
 
     /**
      * <p/>
      * If a message is found, it will also be interpolated.  Anything within <code>${...}</code>
      * will be treated as an OGNL expression and evaluated as such.
+     * <p/>
+     * If a message is <b>not</b> found a WARN log will be logged.
+     * 
+     * @param bundle     the bundle
+     * @param aTextName  the key
+     * @param locale     the locale
+     * @param defaultMessage  the default message to use if no message was found in the bundle
+     * @param args       arguments for the message formatter.
      */
     public static String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args) {
         OgnlValueStack valueStack = ActionContext.getContext().getValueStack();
-
         return findText(bundle, aTextName, locale, defaultMessage, args, valueStack);
-
     }
 
+    /**
+     * Finds a localized text message for the given key, aTextName, in the specified resource
+     * bundle.
+     * <p/>
+     * If a message is found, it will also be interpolated.  Anything within <code>${...}</code>
+     * will be treated as an OGNL expression and evaluated as such.
+     * <p/>
+     * If a message is <b>not</b> found a WARN log will be logged.
+     * 
+     * @param bundle     the bundle
+     * @param aTextName  the key
+     * @param locale     the locale
+     * @param defaultMessage  the default message to use if no message was found in the bundle
+     * @param args       arguments for the message formatter.
+     * @param valueStack the OGNL value stack.
+     */
     public static String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args, OgnlValueStack valueStack) {
         try {
             reloadBundles();
 
             return mf.format(args);
         } catch (MissingResourceException ex) {
+        	// ignore
         }
 
-        String result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage);
-        if ( result != null && result.equals(defaultMessage)) {
+        GetDefaultMessageReturnArg result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage);
+        if (unableToFindTextForKey(result)) {
             LOG.warn("Unable to find text for key '" + aTextName + "' in ResourceBundles for locale '" + locale + "'");
         }
-        return result;
+        return result.message;
     }
 
     /**
      * Gets the default message.
      */
-    private static String getDefaultMessage(String key, Locale locale, OgnlValueStack valueStack, Object[] args, String defaultMessage) {
+    private static GetDefaultMessageReturnArg getDefaultMessage(String key, Locale locale, OgnlValueStack valueStack, Object[] args, String defaultMessage) {
+        GetDefaultMessageReturnArg result = null;
+    	boolean found = true;
+    	
         if (key != null) {
             String message = findDefaultText(key, locale);
 
             if (message == null) {
                 message = defaultMessage;
+                found = false; // not found in bundles
             }
 
             // defaultMessage may be null
             if (message != null) {
                 MessageFormat mf = buildMessageFormat(TextParseUtil.translateVariables(message, valueStack), locale);
 
-                return mf.format(args);
+                String msg = mf.format(args);
+                result = new GetDefaultMessageReturnArg(msg, found);
             }
         }
 
-        return null;
+        return result;
     }
 
     /**
 
     }
 
-
+    /**
+     * Clears all the internal lists. 
+     */
     public static void reset() {
         clearDefaultResourceBundles();
 
             return result;
         }
     }
+    
+    static class GetDefaultMessageReturnArg {
+    	String message;
+    	boolean foundInBundle;
+		
+    	public GetDefaultMessageReturnArg(String message, boolean foundInBundle) {
+			this.message = message;
+			this.foundInBundle = foundInBundle;
+		}
+    }
 }

src/test/com/opensymphony/xwork/util/LocalizedTextUtilTest.java

 /*
- * Copyright (c) 2002-2003 by OpenSymphony
+ * Copyright (c) 2002-2006 by OpenSymphony
  * All rights reserved.
  */
 package com.opensymphony.xwork.util;
 import java.util.Collections;
 import java.util.Date;
 import java.util.Locale;
-import java.util.MissingResourceException;
 
 
 /**
- * LocalizedTextUtilTest
- *
- * @author Jason Carreira
- *         Created Apr 20, 2003 12:07:17 AM
+ * Unit test for {@link LocalizedTextUtil}.
+ * 
+ * @author jcarreira
  */
 public class LocalizedTextUtilTest extends TestCase {
 
-    public void testActionGetText() {
-        try {
-            ModelDrivenAction2 action = new ModelDrivenAction2();
-            TestBean2 bean = (TestBean2) action.getModel();
-            Bar bar = new Bar();
-            bean.setBarObj(bar);
+    public void testActionGetText() throws Exception {
+        ModelDrivenAction2 action = new ModelDrivenAction2();
+        TestBean2 bean = (TestBean2) action.getModel();
+        Bar bar = new Bar();
+        bean.setBarObj(bar);
 
-            Mock mockActionInvocation = new Mock(ActionInvocation.class);
-            mockActionInvocation.expectAndReturn("getAction", action);
-            ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
-            ActionContext.getContext().getValueStack().push(action);
-            ActionContext.getContext().getValueStack().push(action.getModel());
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("getAction", action);
+        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
+        ActionContext.getContext().getValueStack().push(action);
+        ActionContext.getContext().getValueStack().push(action.getModel());
 
-            String message = action.getText("barObj.title");
-            assertEquals("Title:", message);
-        } catch (MissingResourceException ex) {
-            ex.printStackTrace();
-            fail(ex.getMessage());
-        }
+        String message = action.getText("barObj.title");
+        assertEquals("Title:", message);
     }
 
     public void testNullKeys() {
         LocalizedTextUtil.findText(this.getClass(), null, Locale.getDefault());
     }
 
-    public void testActionGetTextXXX() {
-        try {
-            LocalizedTextUtil.addDefaultResourceBundle("com/opensymphony/xwork/util/FindMe");
+    public void testActionGetTextXXX() throws Exception {
+        LocalizedTextUtil.addDefaultResourceBundle("com/opensymphony/xwork/util/FindMe");
 
-            SimpleAction action = new SimpleAction();
+        SimpleAction action = new SimpleAction();
 
-            Mock mockActionInvocation = new Mock(ActionInvocation.class);
-            mockActionInvocation.expectAndReturn("getAction", action);
-            ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
-            ActionContext.getContext().getValueStack().push(action);
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("getAction", action);
+        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
+        ActionContext.getContext().getValueStack().push(action);
 
-            String message = action.getText("bean.name");
-            String foundBean2 = action.getText("bean2.name");
+        String message = action.getText("bean.name");
+        String foundBean2 = action.getText("bean2.name");
 
-            assertEquals("Okay! You found Me!", foundBean2);
-            assertEquals("Haha you cant FindMe!", message);
-        } catch (MissingResourceException ex) {
-            ex.printStackTrace();
-            fail(ex.getMessage());
-        }
+        assertEquals("Okay! You found Me!", foundBean2);
+        assertEquals("Haha you cant FindMe!", message);
     }
 
     public void testAddDefaultResourceBundle() {
         assertEquals("Foo Range Message", message);
     }
 
-    public void testAddDefaultResourceBundle2() {
+    public void testAddDefaultResourceBundle2() throws Exception {
         LocalizedTextUtil.addDefaultResourceBundle("com/opensymphony/xwork/SimpleAction");
 
-        try {
-            ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy("/", "packagelessAction", Collections.EMPTY_MAP, false, true);
-            proxy.execute();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testDefaultMessage() {
-        try {
-            String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
-            assertEquals("Error during Action invocation", message);
-        } catch (MissingResourceException e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testDefaultMessageOverride() {
-        try {
-            String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
-            assertEquals("Error during Action invocation", message);
-        } catch (MissingResourceException e) {
-            e.printStackTrace();
-            fail();
-        }
+        ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy("/", "packagelessAction", Collections.EMPTY_MAP, false, true);
+        proxy.execute();
+    }
+
+    public void testDefaultMessage() throws Exception {
+        String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
+        assertEquals("Error during Action invocation", message);
+    }
+
+    public void testDefaultMessageOverride() throws Exception {
+        String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
+        assertEquals("Error during Action invocation", message);
 
         LocalizedTextUtil.addDefaultResourceBundle("com/opensymphony/xwork/test");
 
-        try {
-            String message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
-            assertEquals("Testing resource bundle override", message);
-        } catch (MissingResourceException e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testFindTextInChildProperty() {
-        try {
-            ModelDriven action = new ModelDrivenAction2();
-            TestBean2 bean = (TestBean2) action.getModel();
-            Bar bar = new Bar();
-            bean.setBarObj(bar);
-
-            Mock mockActionInvocation = new Mock(ActionInvocation.class);
-            mockActionInvocation.expectAndReturn("hashCode", 0);
-            mockActionInvocation.expectAndReturn("getAction", action);
-            ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
-            ActionContext.getContext().getValueStack().push(action);
-            ActionContext.getContext().getValueStack().push(action.getModel());
-
-            String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "invalid.fieldvalue.barObj.title", Locale.getDefault());
-            assertEquals("Title is invalid!", message);
-        } catch (MissingResourceException ex) {
-            ex.printStackTrace();
-            fail(ex.getMessage());
-        }
-    }
-
-    public void testFindTextInInterface() {
-        try {
-            Action action = new ModelDrivenAction2();
-            Mock mockActionInvocation = new Mock(ActionInvocation.class);
-            mockActionInvocation.expectAndReturn("getAction", action);
-            ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
-
-            String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "test.foo", Locale.getDefault());
-            assertEquals("Foo!", message);
-        } catch (MissingResourceException ex) {
-            ex.printStackTrace();
-            fail(ex.getMessage());
-        }
-    }
-
-    public void testFindTextInPackage() {
-        try {
-            ModelDriven action = new ModelDrivenAction2();
-
-            Mock mockActionInvocation = new Mock(ActionInvocation.class);
-            mockActionInvocation.expectAndReturn("getAction", action);
-            ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
-
-            String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "package.properties", Locale.getDefault());
-            assertEquals("It works!", message);
-        } catch (MissingResourceException ex) {
-            ex.printStackTrace();
-            fail(ex.getMessage());
-        }
-    }
-
-    public void testParameterizedDefaultMessage() {
-        try {
-            String message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
-                    "AddUser"
-            });
-            assertEquals("There is no Action mapped for action name AddUser. Check if there is such an action name defined in xwork.xml and also if the such an action class exists. Check also the log to see if the action class is successfully loaded.", message);
-        } catch (MissingResourceException e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testParameterizedDefaultMessageWithPackage() {
-        try {
-            String message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
-                    "blah", "AddUser"
-            });
-            assertEquals("There is no Action mapped for namespace blah and action name AddUser. Check if there is such an action name with such namespace defined in the xwork.xml and also if such an action class exists. Check also the log to see if the action class is successfully loaded.", message);
-        } catch (MissingResourceException e) {
-            e.printStackTrace();
-            fail();
-        }
+        message = LocalizedTextUtil.findDefaultText(XWorkMessages.ACTION_EXECUTION_ERROR, Locale.getDefault());
+        assertEquals("Testing resource bundle override", message);
+    }
+
+    public void testFindTextInChildProperty() throws Exception {
+        ModelDriven action = new ModelDrivenAction2();
+        TestBean2 bean = (TestBean2) action.getModel();
+        Bar bar = new Bar();
+        bean.setBarObj(bar);
+
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("hashCode", 0);
+        mockActionInvocation.expectAndReturn("getAction", action);
+        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
+        ActionContext.getContext().getValueStack().push(action);
+        ActionContext.getContext().getValueStack().push(action.getModel());
+
+        String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "invalid.fieldvalue.barObj.title", Locale.getDefault());
+        assertEquals("Title is invalid!", message);
+    }
+
+    public void testFindTextInInterface() throws Exception {
+        Action action = new ModelDrivenAction2();
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("getAction", action);
+        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
+
+        String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "test.foo", Locale.getDefault());
+        assertEquals("Foo!", message);
+    }
+
+    public void testFindTextInPackage() throws Exception {
+        ModelDriven action = new ModelDrivenAction2();
+
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("getAction", action);
+        ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInvocation.proxy());
+
+        String message = LocalizedTextUtil.findText(ModelDrivenAction2.class, "package.properties", Locale.getDefault());
+        assertEquals("It works!", message);
+    }
+
+    public void testParameterizedDefaultMessage() throws Exception {
+        String message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION, Locale.getDefault(), new String[]{"AddUser"});
+        assertEquals("There is no Action mapped for action name AddUser. Check if there is such an action name defined in xwork.xml and also if the such an action class exists. Check also the log to see if the action class is successfully loaded.", message);
+    }
+
+    public void testParameterizedDefaultMessageWithPackage() throws Exception {
+        String message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[]{"blah", "AddUser"});
+        assertEquals("There is no Action mapped for namespace blah and action name AddUser. Check if there is such an action name with such namespace defined in the xwork.xml and also if such an action class exists. Check also the log to see if the action class is successfully loaded.", message);
     }
 
     public void testLocalizedDateFormatIsUsed() {
         String germanDate = LocalizedTextUtil.findDefaultText("test.format.date", Locale.GERMANY, params);
         assertFalse(usDate.equals(germanDate));
     }
+    
+    public void testXW377() {
+        LocalizedTextUtil.addDefaultResourceBundle("com/opensymphony/xwork/util/LocalizedTextUtilTest");
+
+        String text = LocalizedTextUtil.findText(Bar.class, "xw377", ActionContext.getContext().getLocale(), "xw377", null, ActionContext.getContext().getValueStack());
+        assertEquals("xw377", text); // should not log
+
+        String text2 = LocalizedTextUtil.findText(LocalizedTextUtilTest.class, "notinbundle", ActionContext.getContext().getLocale(), "hello", null, ActionContext.getContext().getValueStack());
+        assertEquals("hello", text2); // should log WARN
+
+        String text3 = LocalizedTextUtil.findText(LocalizedTextUtilTest.class, "notinbundle.key", ActionContext.getContext().getLocale(), "notinbundle.key", null, ActionContext.getContext().getValueStack());
+        assertEquals("notinbundle.key", text3); // should log WARN
+
+        String text4 = LocalizedTextUtil.findText(LocalizedTextUtilTest.class, "xw377", ActionContext.getContext().getLocale(), "hello", null, ActionContext.getContext().getValueStack());
+        assertEquals("xw377", text4); // should not log
+
+        String text5 = LocalizedTextUtil.findText(LocalizedTextUtilTest.class, "username", ActionContext.getContext().getLocale(), null, null, ActionContext.getContext().getValueStack());
+        assertEquals("Santa", text5); // should not log
+    }
 
     protected void setUp() throws Exception {
         super.setUp();
 
     protected void tearDown() throws Exception {
         super.tearDown();
-
         LocalizedTextUtil.clearDefaultResourceBundles();
     }
+    
 }

src/test/com/opensymphony/xwork/util/LocalizedTextUtilTest.properties

 test.format.date={0,date,short}
+xw377=xw377
+username=Santa
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.