You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by rs...@apache.org on 2002/09/20 17:19:25 UTC

cvs commit: xml-axis/java/src/org/apache/axis/i18n MessagesConstants.java RB.java ExtendMessages.java ProjectResourceBundle.java Messages.java

rsitze      2002/09/20 08:19:25

  Modified:    java/src/org/apache/axis/utils Messages.java
  Added:       java/src/org/apache/axis/i18n MessagesConstants.java RB.java
                        ExtendMessages.java ProjectResourceBundle.java
                        Messages.java
  Removed:     java/src/org/apache/axis/utils RB.java
  Log:
  Initial drop of hierarchical messaging.  I'm still testing new features, but it passes regression.
  
  To extend the messages to a new package
  - introduce a new message file (currently axisNLS.properties) to that package (or a parent package)
  - Copy o.a.a.i18n.Messages (all static methods) to the package containing the new message file
  - Replace any occurances of ''import o.a.a.utils.Messages' with 'import yourPackage.Messages'
    in all java files in 'myPackage' and all subpackages.
  - You may put sub-messages files and copies of Messages in subpackages to further extend
    Messages will look up the hierarchy (but not beyond org.apache.axis) for messages
    if they cannot be found by the referenced Messages class.
  - yourPackage.Messages will, as a last effort, link back to o.a.a.utils.axisNLS
  
  Revision  Changes    Path
  1.4       +148 -80   xml-axis/java/src/org/apache/axis/utils/Messages.java
  
  Index: Messages.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/Messages.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Messages.java	18 Sep 2002 16:10:41 -0000	1.3
  +++ Messages.java	20 Sep 2002 15:19:24 -0000	1.4
  @@ -55,94 +55,162 @@
   
   package org.apache.axis.utils;
   
  -import java.text.MessageFormat;
  +import java.util.Locale;
   import java.util.MissingResourceException;
   import java.util.ResourceBundle;
   
  +import org.apache.axis.i18n.MessagesConstants;
  +import org.apache.axis.i18n.ExtendMessages;
   
   /**
  - * Class to facilitate i18n (NLS) message translation for
  - * axis components.
  - *
  - * @author Richard A. Sitze
  + * Root Messages classes.
  + * 
  + * Copy this template to your package, edit the following attributes
  + * as/if necessary:
  + * 
  + *   projectName
  + *   packageName
  + *   resourceName
  + *   classLoader
  + *   locale
  + *   parent   - The ROOT Messages resource bundle should not define this..
  + *              For all other bundles in AXIS, this should point to the root.
  + * 
  + * @author Richard A. Sitze (rsitze@us.ibm.com)
  + * @author Karl Moss (kmoss@macromedia.com)
    * @author Glen Daniels (gdaniels@macromedia.com)
    */
  -public final class Messages {
  -    public static final String DEFAULT_PROPERTIES_RESOURCE_NAME =
  -        "org.apache.axis.utils.axisNLS";
  -
  -    // Message resource bundle.
  -    private static ResourceBundle _messageBundle = null;
  -
  +public class Messages {
  +    private static final Class  thisClass = Messages.class;
  +    private static final String projectName = MessagesConstants.projectName;
  +    private static final String packageName = getPackage(thisClass.getName());
  +    private static final String resourceName = MessagesConstants.resourceName;
  +    private static final Locale locale = MessagesConstants.locale;
  +    private static final ClassLoader classLoader = thisClass.getClassLoader();
  +    private static final ResourceBundle parent = null;
  +
  +
  +    /***** NO NEED TO CHANGE ANYTHING BELOW *****/
  +
  +    private static final ExtendMessages rb = new ExtendMessages(resourceName, parent) {
  +            protected String getPackageName() { return packageName; }
  +            protected String getProjectName() { return projectName; }
  +            protected ClassLoader getClassLoader() { return classLoader; }
  +            protected Locale getLocale() { return locale; }
  +        };
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param arg0 The argument to place in variable {0}
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String arg0)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, arg0);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param arg0 The argument to place in variable {0}
  +      * @param arg1 The argument to place in variable {1}
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String arg0, String arg1)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, arg0, arg1);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param arg0 The argument to place in variable {0}
  +      * @param arg1 The argument to place in variable {1}
  +      * @param arg2 The argument to place in variable {2}
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String arg0, String arg1, String arg2)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, arg0, arg1, arg2);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param arg0 The argument to place in variable {0}
  +      * @param arg1 The argument to place in variable {1}
  +      * @param arg2 The argument to place in variable {2}
  +      * @param arg3 The argument to place in variable {3}
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String arg0, String arg1, String arg2, String arg3)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, arg0, arg1, arg2, arg3);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param arg0 The argument to place in variable {0}
  +      * @param arg1 The argument to place in variable {1}
  +      * @param arg2 The argument to place in variable {2}
  +      * @param arg3 The argument to place in variable {3}
  +      * @param arg4 The argument to place in variable {4}
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String arg0, String arg1, String arg2, String arg3, String arg4)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, arg0, arg1, arg2, arg3, arg4);
  +    }
  +
  +    /**
  +      * Get a message from resource.properties from the package of the given object.
  +      * @param caller The calling object, used to get the package name and class loader
  +      * @param locale The locale
  +      * @param key The resource key
  +      * @param array An array of objects to place in corresponding variables
  +      * @return The formatted message
  +      */
  +    public static String getMessage(String key, String[] args)
  +        throws MissingResourceException
  +    {
  +        return rb.getMessage(key, args);
  +    }
       
  -    /**
  -     * Get the resource bundle that contains AXIS translatable messages.
  -     * 
  -     * This is ONLY done when it is needed.  If no messages are printed
  -     * (for example, only WSDL2java is being run in non-verbose mode)
  -     * then there is no need to read the properties file.
  -     */
       public static ResourceBundle getMessageBundle() {
  -        if (_messageBundle == null) {
  -            _messageBundle = ResourceBundle.getBundle(DEFAULT_PROPERTIES_RESOURCE_NAME);
  -        }
  -        return _messageBundle;
  -    } // getMessageBundle
  -
  -    /**
  -     * Get the message with the given key.
  -     * There are no arguments for this message.
  -     */
  -    public static String getMessage(String key)
  -            throws MissingResourceException {
  -        return getMessageBundle().getString(key);
  -    } // getMessage
  -
  -
  -    /**
  -     * Get the message with the given key.  If an argument is specified
  -     * in the message (in the format of "{0}") then fill in that argument
  -     * with the value of var.
  -     */
  -    public static String getMessage(String key, String var)
  -            throws MissingResourceException {
  -        String[] args = {var};
  -        return MessageFormat.format(getMessage(key), args);
  -    } // getMessage
  -
  -
  -    /**
  -     * Get the message with the given key.  If arguments are specified
  -     * in the message (in the format of "{0} {1}") then fill them in
  -     * with the values of var1 and var2, respectively.
  -     */
  -    public static String getMessage(String key, String var1, String var2)
  -            throws MissingResourceException {
  -        String[] args = {var1, var2};
  -        return MessageFormat.format(getMessage(key), args);
  -    } // getMessage
  -
  +        return rb.getMessageBundle();
  +    }
   
  -    /**
  -     * Get the message with the given key.  If arguments are specified
  -     * in the message (in the format of "{0} {1}") then fill them in
  -     * with the values of var1 and var2, respectively.
  -     */
  -    public static String getMessage(String key, String var1, String var2, String var3)
  -            throws MissingResourceException {
  -        return MessageFormat.format(getMessage(key), new String[]{var1, var2, var3});
  -    } // getMessage
  -
  -
  -    /**
  -     * Get the message with the given key.  Replace each "{X}" in the
  -     * message with vars[X].  If there are more vars than {X}'s, then
  -     * the extra vars are ignored.  If there are more {X}'s than vars,
  -     * then a java.text.ParseException (subclass of RuntimeException)
  -     * is thrown.
  -     */
  -    public static String getMessage(String key, String[] vars)
  -            throws MissingResourceException {
  -        return MessageFormat.format(getMessage(key), vars);
  -    } // getMessage
  +    private static final String getPackage(String name) {
  +        return name.substring(0, name.lastIndexOf('.')).intern();
  +    }
   }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/i18n/MessagesConstants.java
  
  Index: MessagesConstants.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.i18n;
  
  import java.util.Locale;
  import java.util.ResourceBundle;
  
  /**
   * @author Richard A. Sitze (rsitze@us.ibm.com)
   */
  public class MessagesConstants {
      public static final String projectName = "org.apache.axis";
      public static final String resourceName = "axisNLS";
      public static final Locale locale = null;
      
      public static final String rootPackageName = "org.apache.axis.utils";
  
      public static final ResourceBundle rootBundle =
          org.apache.axis.utils.Messages.getMessageBundle();
  //        
  //        ProjectResourceBundle.getBundle(projectName,
  //                                        rootPackageName,
  //                                        resourceName,
  //                                        locale,
  //                                        MessagesConstants.class.getClassLoader(),
  //                                        null);
  }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/i18n/RB.java
  
  Index: RB.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.i18n;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.text.MessageFormat;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Locale;
  import java.util.MissingResourceException;
  import java.util.Properties;
  
  /**
   * CURRENTLY NOT USED
   * KEEPING FOR REFERENCE  9/19/2002
   * 
   * <p>Wrapper class for resource bundles. Property files are used to store
   * resource strings, which are the only types of resources available.
   * Property files can inherit properties from other files so that
   * a base property file can be used and a small number of properties
   * can be over-ridden by another property file. For example you may
   * create an english version of a resource file named "resource.properties".
   * You then decide that the British English version of all of the properties
   * except one are the same, so there is no need to redefine all of the
   * properties in "resource_en_GB", just the one that is different.</p>
   * <p>The property file lookup searches for classes with various suffixes
   * on the basis if the desired local and the current default local
   * (as returned by Local.getDefault()). As property files are found the
   * property values are merged so that inheritance is preserved.</p>
   * <p>The order of searching is:</p>
   * <dir>
   * basename + "_" + langage + "_" + country + "_" + variant
   * basename + "_" + langage + "_" + country
   * basename + "_" + langage
   * basename + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant
   * basename + "_" + defaultLanguage + "_" + defaultCountry
   * basename + "_" + defaultLanguage
   * basename
   * </dir>
   * <p>The basename is the name of the property file without the ".properties"
   * extension.</p>
   * <p>Properties will be cached for performance.<p>
   * <p>Property values stored in the property files can also contain dynamic
   * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
   * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
   * Argument values are specified in the various overloaded getString() methods.</p>
   * 
   * @author Karl Moss (kmoss@macromedia.com)
   * @author Glen Daniels (gdaniels@macromedia.com)
   */
  public class RB {
      // The static cache of properties. The key is the basename + the local +
      // the default local and the element is the Properties object containing
      // the resources
      static Hashtable propertyCache = new Hashtable();
  
      // The default base name
      public static final String BASE_NAME = "resource";
  
      // The property file extension
      public static final String PROPERTY_EXT = ".properties";
  
      // The name of the current base property file (with extension)
      protected String basePropertyFileName;
  
      // The properties for the current resource bundle
      protected Properties resourceProperties;
  
      /**
        * Construct a new RB
        * @param name The name of the property file without the ".properties" extension
        */
      public RB(String name) throws MissingResourceException
      {
          this(null, name, null);
      }
  
      /**
        * Construct a new RB
        * @param caller The calling object. This is used to get the package name
        * to further construct the basename as well as to get the proper ClassLoader
        * @param name The name of the property file without the ".properties" extension
        */
      public RB(Object caller, String name) throws MissingResourceException
      {
          this(caller, name, null);
      }
  
      /**
        * Construct a new RB
        * @param caller The calling object. This is used to get the package name
        * to further construct the basename as well as to get the proper ClassLoader
        * @param name The name of the property file without the ".properties" extension
        * @param local The local
        */
      public RB(Object caller, String name, Locale locale) throws MissingResourceException
      {
          ClassLoader cl = null;
  
          if (caller != null) {
  
              Class c;
              if (caller instanceof Class) {
                  c = (Class) caller;
              }
              else {
                  c = caller.getClass();
              }
  
              // Get the appropriate class loader
              cl = c.getClassLoader();
  
              if (name.indexOf("/") == -1) {
  
                  // Create the full basename only if not given
                  String fullName = c.getName();
  
                  int pos = fullName.lastIndexOf(".");
                  if (pos > 0) {
                      name = fullName.substring(0, pos + 1).replace('.', '/') + name;
                  }
              }
          } else {
              // Try the shared default properties file...
              if (name.indexOf("/") == -1) {
                  name = "org/apache/axis/default-resource";
              }
          }
  
          Locale defaultLocale = Locale.getDefault();
  
          // If the locale given is the same as the default locale, ignore it
          if (locale != null) {
              if (locale.equals(defaultLocale)) {
                  locale = null;
              }
          }
  
          // Load the properties. If no property files exist then a
          // MissingResourceException will be thrown
          loadProperties(name, cl, locale, defaultLocale);
      }
  
      /**
        * Gets a string message from the resource bundle for the given key
        * @param key The resource key
        * @return The message
        */
      public String getString(String key) throws MissingResourceException
      {
          return getString(key, (Object[]) null);
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @return The message
        */
      public String getString(String key, Object arg0) throws MissingResourceException
      {
          Object[] o = new Object[1];
          o[0] = arg0;
          return getString(key, o);
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @return The message
        */
      public String getString(String key, Object arg0, Object arg1) throws MissingResourceException
      {
          Object[] o = new Object[2];
          o[0] = arg0;
          o[1] = arg1;
          return getString(key, o);
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {1}
        * @return The message
        */
      public String getString(String key, Object arg0, Object arg1, Object arg2) throws MissingResourceException
      {
          Object[] o = new Object[3];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          return getString(key, o);
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param array An array of objects to place in corresponding variables
        * @return The message
        */
      public String getString(String key, Object[] array) throws MissingResourceException
      {
          String msg = null;
          if (resourceProperties != null) {
              msg = resourceProperties.getProperty(key);
          }
  
          if (msg == null) {
              throw new MissingResourceException("Cannot find resource key \"" + key +
                                                 "\" in base name " + basePropertyFileName,
                                                 basePropertyFileName, key);
          }
  
          msg = MessageFormat.format(msg, array);
          return msg;
      }
  
      protected void loadProperties(String basename, ClassLoader loader, Locale locale,
                                    Locale defaultLocale)
          throws MissingResourceException
      {
          // Check the cache first
          String loaderName = "";
          if (loader != null) {
              loaderName = ":" + loader.hashCode();
          }
          String cacheKey = basename + ":" + locale + ":" + defaultLocale + loaderName;
          Properties p = (Properties) propertyCache.get(cacheKey);
          basePropertyFileName = basename + PROPERTY_EXT;
  
          if (p == null) {
              // The properties were not found in the cache. Search the given locale
              // first
              if (locale != null) {
                  p = loadProperties(basename, loader, locale, p);
              }
  
              // Search the default locale
              if (defaultLocale != null) {
                  p = loadProperties(basename, loader, defaultLocale, p);
              }
  
              // Search for the basename
              p = merge(p, loadProperties(basePropertyFileName, loader));
  
              if (p == null) {
                  throw new MissingResourceException("Cannot find resource for base name " +
                                                     basePropertyFileName, basePropertyFileName, "");
              }
  
              // Cache the properties
              propertyCache.put(cacheKey, p);
  
          }
  
          resourceProperties = p;
      }
  
      protected Properties loadProperties(String basename, ClassLoader loader, Locale locale,
                                          Properties props)
      {
  
          String language = locale.getLanguage();
          String country = locale.getCountry();
          String variant = locale.getVariant();
          if (variant != null) {
              if (variant.trim().length() == 0) {
                  variant = null;
              }
          }
  
          if (language != null) {
  
              if (country != null) {
  
                  if (variant != null) {
                      props = merge(props, loadProperties(basename + "_" + language +"_" + country + "_" + variant +
                                                          PROPERTY_EXT, loader));
                  }
                  props = merge(props, loadProperties(basename + "_" + language +"_" + country +
                                                      PROPERTY_EXT, loader));
              }
              props = merge(props, loadProperties(basename + "_" + language + PROPERTY_EXT, loader));
          }
          return props;
      }
  
      protected Properties loadProperties(String resname, ClassLoader loader)
      {
          Properties props = null;
  
          // Attempt to open and load the properties
          InputStream in = null;
          try {
              if (loader != null) {
                  in = loader.getResourceAsStream(resname);
              }
  
              // Either we're using the system class loader or we didn't find the
              // resource using the given class loader
              if (in == null) {
                  in = ClassLoader.getSystemResourceAsStream(resname);
              }
              if (in != null) {
                  props = new Properties();
                  try {
                      props.load(in);
                  }
                  catch (IOException ex) {
                      // On error, clear the props
                      props = null;
                  }
              }
          }
          finally {
              if (in != null) {
                  try {
                      in.close();
                  }
                  catch (Exception ex) {
                      // Ignore error on close
                  }
              }
          }
          return props;
      }
  
      /**
        * Merge two Properties objects
        */
      protected Properties merge(Properties p1, Properties p2)
      {
          if ((p1 == null) &&
              (p2 == null)) {
              return null;
          }
          else if (p1 == null) {
              return p2;
          }
          else if (p2 == null) {
              return p1;
          }
  
          // Now merge. p1 takes precedence
          Enumeration enum = p2.keys();
          while (enum.hasMoreElements()) {
              String key = (String) enum.nextElement();
              if (p1.getProperty(key) == null) {
                  p1.put(key, p2.getProperty(key));
              }
          }
  
          return p1;
      }
  
      /**
        * Get the underlying properties
        */
      public Properties getProperties()
      {
          return resourceProperties;
      }
  
      // STATIC ACCESSORS
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @return The formatted message
        */
      public static String getString(Object caller, String key)
          throws MissingResourceException
      {
          return getMessage(caller, BASE_NAME, null, key, null);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object arg0)
          throws MissingResourceException
      {
          Object[] o = new Object[1];
          o[0] = arg0;
          return getMessage(caller, BASE_NAME, null, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object arg0, Object arg1)
          throws MissingResourceException
      {
          Object[] o = new Object[2];
          o[0] = arg0;
          o[1] = arg1;
          return getMessage(caller, BASE_NAME, null, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2)
          throws MissingResourceException
      {
          Object[] o = new Object[3];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          return getMessage(caller, BASE_NAME, null, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3)
          throws MissingResourceException
      {
          Object[] o = new Object[4];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          o[3] = arg3;
          return getMessage(caller, BASE_NAME, null, key, o);
      }
  
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @param arg4 The argument to place in variable {4}
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4)
          throws MissingResourceException
      {
          Object[] o = new Object[5];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          o[3] = arg3;
          o[4] = arg4;
          return getMessage(caller, BASE_NAME, null, key, o);
      }
  
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param key The resource key
        * @param array An array of objects to place in corresponding variables
        * @return The formatted message
        */
      public static String getString(Object caller, String key, Object[] args)
          throws MissingResourceException
      {
          return getMessage(caller, BASE_NAME, null, key, args);
      }
  
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key)
          throws MissingResourceException
      {
          return getMessage(caller, BASE_NAME, locale, key, null);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object arg0)
          throws MissingResourceException
      {
          Object[] o = new Object[1];
          o[0] = arg0;
          return getMessage(caller, BASE_NAME, locale, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1)
          throws MissingResourceException
      {
          Object[] o = new Object[2];
          o[0] = arg0;
          o[1] = arg1;
          return getMessage(caller, BASE_NAME, locale, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2)
          throws MissingResourceException
      {
          Object[] o = new Object[3];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          return getMessage(caller, BASE_NAME, locale, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2, Object arg3)
          throws MissingResourceException
      {
          Object[] o = new Object[4];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          o[3] = arg3;
          return getMessage(caller, BASE_NAME, locale, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4)
          throws MissingResourceException
      {
          Object[] o = new Object[5];
          o[0] = arg0;
          o[1] = arg1;
          o[2] = arg2;
          o[3] = arg3;
          o[4] = arg4;
          return getMessage(caller, BASE_NAME, locale, key, o);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param array An array of objects to place in corresponding variables
        * @return The formatted message
        */
      public static String getString(Object caller, Locale locale, String key, Object[] args)
          throws MissingResourceException
      {
          return getMessage(caller, BASE_NAME, locale, key, args);
      }
  
      // Workhorse that does the resource loading and key lookup
      public static String getMessage(Object caller, String basename, Locale locale, String key,
                                         Object[] args)
          throws MissingResourceException
      {
          String msg = null;
          MissingResourceException firstEx = null;
          String fullName = null;
          Class curClass = null;
          boolean didNull = false;
          
          if (caller != null) {
              if(caller instanceof Class)
                  curClass = (Class) caller;
              else
                  curClass = caller.getClass();
          }
  
          while (msg == null) {
  
              // Get the full name of the resource
              if (curClass != null) {
  
                  // Create the full basename
                  String pkgName = curClass.getName();
  
                  int pos = pkgName.lastIndexOf(".");
                  if (pos > 0) {
                      fullName = pkgName.substring(0, pos + 1).replace('.', '/') + basename;
                  }
                  else {
                      fullName = basename;
                  }
              }
              else {
                  fullName = basename;
              }
  
              try {
                  RB rb = new RB(caller, fullName, locale);
                  msg = rb.getString(key, args);
              }
              catch (MissingResourceException ex) {
                  if (curClass == null) {
                      throw ex;
                  }
  
                  // Save the first exception
                  if (firstEx == null) {
                      firstEx = ex;
                  }
  
                  // Get the superclass
                  curClass = curClass.getSuperclass();
                  if (curClass == null) {
                      if (didNull)
                          throw firstEx;
                      didNull = true;
                      caller = null;
                  } else {
                      String cname = curClass.getName();
                      if (cname.startsWith("java.") ||
                          cname.startsWith("javax.")) {
                          if (didNull)
                              throw firstEx;
                          didNull = true;
                          caller = null;
                          curClass = null;
                      }
                  }
              }
  
          }
          return msg;
      }
  
      /**
        * Clears the internal cache
        */
      public static void clearCache()
      {
          propertyCache.clear();
      }
  }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/i18n/ExtendMessages.java
  
  Index: ExtendMessages.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.i18n;
  
  import java.text.MessageFormat;
  import java.util.Locale;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  
  /**
   * <p>Wrapper class for resource bundles. Property files are used to store
   * resource strings, which are the only types of resources available.
   * Property files can inherit properties from other files so that
   * a base property file can be used and a small number of properties
   * can be over-ridden by another property file. For example you may
   * create an english version of a resource file named "resource.properties".
   * You then decide that the British English version of all of the properties
   * except one are the same, so there is no need to redefine all of the
   * properties in "resource_en_GB", just the one that is different.</p>
   * <p>The basename is the name of the property file without the ".properties"
   * extension.</p>
   * <p>Properties will be cached for performance.<p>
   * <p>Property values stored in the property files can also contain dynamic
   * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
   * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
   * Argument values are specified in the various overloaded getString() methods.</p>
   * 
   * @author Richard A. Sitze (rsitze@us.ibm.com)
   * @author Karl Moss (kmoss@macromedia.com)
   * @author Glen Daniels (gdaniels@macromedia.com)
   */
  public abstract class ExtendMessages {
      public static final String BASE_NAME = MessagesConstants.resourceName;
      
      private boolean loaded = false;
      private ProjectResourceBundle _resourceBundle = null;
      private final String resourceName;
      private final ResourceBundle parent;
      
  
      protected abstract String getPackageName();
      protected abstract String getProjectName();
      protected abstract ClassLoader getClassLoader();
      protected abstract Locale getLocale();
  
  
      public final ProjectResourceBundle getMessageBundle() {
          if (!loaded) {
              _resourceBundle = ProjectResourceBundle.getBundle(getProjectName(),
                                                                getPackageName(),
                                                                resourceName,
                                                                getLocale(),
                                                                getClassLoader(),
                                                                parent);
              loaded = true;
          }
          return _resourceBundle;
      }
  
  
      /**
       * Construct a new ExtendMessages
       */
      protected ExtendMessages()
          throws MissingResourceException
      {
          this(BASE_NAME, null);
      }
  
      /**
       * Construct a new ExtendMessages
       */
      protected ExtendMessages(String resourceName)
          throws MissingResourceException
      {
          this(resourceName, null);
      }
  
      protected ExtendMessages(String resourceName, ResourceBundle parent)
          throws MissingResourceException
      {
          this.resourceName = resourceName;
          this.parent = parent;
      }
  
      /**
        * Gets a string message from the resource bundle for the given key
        * @param key The resource key
        * @return The message
        */
      public String getMessage(String key) throws MissingResourceException
      {
          return getMessage(key, (String[]) null);
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @return The message
        */
      public String getMessage(String key, String arg0) throws MissingResourceException
      {
          return getMessage(key, new String[] { arg0 });
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @return The message
        */
      public String getMessage(String key, String arg0, String arg1) throws MissingResourceException
      {
          return getMessage(key, new String[] { arg0, arg1 });
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @return The message
        */
      public String getMessage(String key, String arg0, String arg1, String arg2) throws MissingResourceException
      {
          return getMessage(key, new String[] { arg0, arg1, arg2 });
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @return The message
        */
      public String getMessage(String key, String arg0, String arg1, String arg2, String arg3) throws MissingResourceException
      {
          return getMessage(key, new String[] { arg0, arg1, arg2, arg3 });
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @param arg4 The argument to place in variable {4}
        * @return The message
        */
      public String getMessage(String key, String arg0, String arg1, String arg2, String arg3, String arg4) throws MissingResourceException
      {
          return getMessage(key, new String[] { arg0, arg1, arg2, arg3, arg4 });
      }
  
      /**
        * <p>Gets a string message from the resource bundle for the given key. The
        * message may contain variables that will be substituted with the given
        * arguments. Variables have the format:</p>
        * <dir>
        * This message has two variables: {0} and {1}
        * </dir>
        * @param key The resource key
        * @param array An array of objects to place in corresponding variables
        * @return The message
        */
      public String getMessage(String key, String[] array) throws MissingResourceException
      {
          String msg = null;
          if (getMessageBundle() != null) {
              msg = getMessageBundle().getString(key);
          }
  
          if (msg == null) {
              throw new MissingResourceException("Cannot find resource key \"" + key +
                                                 "\" in base name " +
                                                 getMessageBundle().getResourceName(),
                                                 getMessageBundle().getResourceName(), key);
          }
  
          return MessageFormat.format(msg, array);
      }
  }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/i18n/ProjectResourceBundle.java
  
  Index: ProjectResourceBundle.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.i18n;
  
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Locale;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  
  import org.apache.axis.components.logger.LogFactory;
  import org.apache.commons.logging.Log;
  
  /**
   * <p>Wrapper class for resource bundles. Property files are used to store
   * resource strings, which are the only types of resources available.
   * Property files can inherit properties from other files so that
   * a base property file can be used and a small number of properties
   * can be over-ridden by another property file. For example you may
   * create an english version of a resource file named "resource.properties".
   * You then decide that the British English version of all of the properties
   * except one are the same, so there is no need to redefine all of the
   * properties in "resource_en_GB", just the one that is different.</p>
   * <p>The basename is the name of the property file without the ".properties"
   * extension.</p>
   * <p>Properties will be cached for performance.<p>
   * <p>Property values stored in the property files can also contain dynamic
   * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
   * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
   * Argument values are specified in the various overloaded getString() methods.</p>
   * 
   * @author Richard A. Sitze (rsitze@us.ibm.com)
   * @author Karl Moss (kmoss@macromedia.com)
   * @author Glen Daniels (gdaniels@macromedia.com)
   */
  public class ProjectResourceBundle extends ResourceBundle {
      protected static Log log =
          LogFactory.getLog(ProjectResourceBundle.class.getName());
  
  
      // The static cache of ResourceBundles.
      // The key is the 'basename + locale + default locale'
      // The element is a ResourceBundle object
      private static final Hashtable bundleCache = new Hashtable();
  
      private static final Locale defaultLocale = Locale.getDefault();
  
      private final ResourceBundle resourceBundle;
      private final String resourceName;
  
      
      protected Object handleGetObject(String key)
          throws MissingResourceException
      {
          return resourceBundle.getObject(key);
      }
      
      public Enumeration getKeys() {
          return resourceBundle.getKeys();
      }
      
  
      /**
       * Construct a new ProjectResourceBundle
       * 
       * @param projectName The name of the project to which the class belongs.
       *        It must be a proper prefix of the caller's package.
       * 
       * @param caller The calling class.
       *        This is used to get the package name to further construct
       *        the basename as well as to get the proper ClassLoader.
       * 
       * @param resourceName The name of the resource without the
       *        ".properties" extension
       * 
       * @throws MissingResourceException if projectName is not a prefix of
       *         the caller's package name, or if the resource could not be
       *         found/loaded.
       */
      public static ProjectResourceBundle getBundle(String projectName,
                                                    String packageName,
                                                    String resourceName)
          throws MissingResourceException
      {
          return getBundle(projectName, packageName, resourceName, null, null, null);
      }
  
      /**
       * Construct a new ProjectResourceBundle
       * 
       * @param projectName The name of the project to which the class belongs.
       *        It must be a proper prefix of the caller's package.
       * 
       * @param caller The calling class.
       *        This is used to get the package name to further construct
       *        the basename as well as to get the proper ClassLoader.
       * 
       * @param resourceName The name of the resource without the
       *        ".properties" extension
       * 
       * @throws MissingResourceException if projectName is not a prefix of
       *         the caller's package name, or if the resource could not be
       *         found/loaded.
       */
      public static ProjectResourceBundle getBundle(String projectName,
                                                    Class  caller,
                                                    String resourceName,
                                                    Locale locale)
          throws MissingResourceException
      {
          return getBundle(projectName,
                           caller,
                           resourceName,
                           locale,
                           null);
      }
  
      /**
       * Construct a new ProjectResourceBundle
       * 
       * @param projectName The name of the project to which the class belongs.
       *        It must be a proper prefix of the caller's package.
       * 
       * @param caller The calling class.
       *        This is used to get the package name to further construct
       *        the basename as well as to get the proper ClassLoader.
       * 
       * @param resourceName The name of the resource without the
       *        ".properties" extension
       * 
       * @param locale The locale
       * 
       * @throws MissingResourceException if projectName is not a prefix of
       *         the caller's package name, or if the resource could not be
       *         found/loaded.
       */
      public static ProjectResourceBundle getBundle(String projectName,
                                                    String packageName,
                                                    String resourceName,
                                                    Locale locale,
                                                    ClassLoader loader)
          throws MissingResourceException
      {
          return getBundle(projectName, packageName, resourceName, locale, loader, null);
      }
  
      /**
       * Construct a new ProjectResourceBundle
       * 
       * @param projectName The name of the project to which the class belongs.
       *        It must be a proper prefix of the caller's package.
       * 
       * @param caller The calling class.
       *        This is used to get the package name to further construct
       *        the basename as well as to get the proper ClassLoader.
       * 
       * @param resourceName The name of the resource without the
       *        ".properties" extension
       * 
       * @param locale The locale
       * 
       * @param extendsBundle If non-null, then this ExtendMessages will
       *         default to extendsBundle.
       * 
       * @throws MissingResourceException if projectName is not a prefix of
       *         the caller's package name, or if the resource could not be
       *         found/loaded.
       */
      public static ProjectResourceBundle getBundle(String projectName,
                                                    Class  caller,
                                                    String resourceName,
                                                    Locale locale,
                                                    ResourceBundle extendsBundle)
          throws MissingResourceException
      {
          return getBundle(projectName,
                           getPackage(caller.getClass().getName()),
                           resourceName,
                           locale,
                           caller.getClass().getClassLoader(),
                           extendsBundle);
      }
  
      /**
       * Construct a new ProjectResourceBundle
       * 
       * @param projectName The name of the project to which the class belongs.
       *        It must be a proper prefix of the caller's package.
       * 
       * @param caller The calling class.
       *        This is used to get the package name to further construct
       *        the basename as well as to get the proper ClassLoader.
       * 
       * @param resourceName The name of the resource without the
       *        ".properties" extension
       * 
       * @param locale The locale
       * 
       * @param extendsBundle If non-null, then this ExtendMessages will
       *         default to extendsBundle.
       * 
       * @throws MissingResourceException if projectName is not a prefix of
       *         the caller's package name, or if the resource could not be
       *         found/loaded.
       */
      public static ProjectResourceBundle getBundle(String projectName,
                                                    String packageName,
                                                    String resourceName,
                                                    Locale locale,
                                                    ClassLoader loader,
                                                    ResourceBundle extendsBundle)
          throws MissingResourceException
      {
          if (log.isDebugEnabled()) {
              log.debug("ProjectResourceBundle::getBundle(" + projectName + ","
                                                            + packageName + ","
                                                            + resourceName + ","
                                                            + String.valueOf(locale) + ",...)");
          }
          
          Context context = new Context();
          context.setLocale(locale);
          context.setLoader(loader);
          context.setProjectName(projectName);
          context.setResourceName(resourceName);
          context.setParentBundle(extendsBundle);
  
          packageName = context.validate(packageName);
  
          ProjectResourceBundle bundle = null;
          try {
              bundle = getBundle(context, packageName);
          } catch (RuntimeException e) {
              log.debug("Exception: ", e);
              throw e;
          }
          
          if (bundle == null) {
              throw new MissingResourceException("Cannot find resource " + resourceName,
                                                 resourceName, "");
          }
          
          return bundle;
      }
  
      /**
       * get bundle...
       * - check cache
       * - try up hierarchy
       * - if at top of hierarchy, use (link to) context.getParentBundle()
       */
      private static synchronized ProjectResourceBundle getBundle(Context context, String packageName)
          throws MissingResourceException
      {
          String cacheKey = context.getCacheKey(packageName);
          
          ProjectResourceBundle prb = (ProjectResourceBundle)bundleCache.get(cacheKey);
  
          if (prb == null) {
              String name = packageName + '.' + context.getResourceName();
              ResourceBundle rb = context.loadBundle(packageName);
              ResourceBundle parent = context.getParentBundle(packageName);
              
              if (rb != null) {
                  prb = new ProjectResourceBundle(name, rb);
                  prb.setParent(parent);
              } else {
                  if (parent != null) {
                      if (parent instanceof ProjectResourceBundle) {
                          prb = (ProjectResourceBundle)parent;
                      } else {
                          prb = new ProjectResourceBundle(name, parent);
                      }
                  }
              }
  
              if (prb != null) {
                  // Cache the resource
                  bundleCache.put(cacheKey, prb);
              }
          }
  
          return prb;
      }
  
      private static final String getPackage(String name) {
          return name.substring(0, name.lastIndexOf('.')).intern();
      }
      
      /**
        * Construct a new ProjectResourceBundle
        */
      private ProjectResourceBundle(String name, ResourceBundle bundle)
          throws MissingResourceException
      {
          this.resourceBundle = bundle;
          this.resourceName = name;
      }
      
      public String getResourceName() {
          return resourceName;
      }
  
      /**
       * Clears the internal cache
       */
      public static void clearCache()
      {
          bundleCache.clear();
      }
  
  
      private static class Context {
          private Locale _locale;
          private ClassLoader _loader;
          private String _projectName;
          private String _resourceName;
          private ResourceBundle _parent;
          
          void setLocale(Locale l) {
              /* 1. Docs indicate that if locale is not specified,
               *    then the default local is used in it's place.
               * 2. A null value for locale is invalid.
               * 
               * Therefore, default...
               */
              _locale = (l == null) ? defaultLocale : l;
          }
  
          void setLoader(ClassLoader l) {
              _loader = (l != null) ? l : this.getClass().getClassLoader();
          }
          
          void setProjectName(String name) { _projectName = name.intern(); }
          void setResourceName(String name) { _resourceName = name.intern(); }
          void setParentBundle(ResourceBundle b) { _parent = b; }
          
          Locale getLocale() { return _locale; }
          ClassLoader getLoader() { return _loader; }
          String getProjectName() { return _projectName; }
          String getResourceName() { return _resourceName; }
          ResourceBundle getParentBundle() { return _parent; }
      
          String getCacheKey(String packageName)
          {
              String loaderName = (_loader == null) ? "" : (":" + _loader.hashCode());
              return packageName + "." + _resourceName + ":" + _locale + ":" + defaultLocale + loaderName;
          }
  
          ResourceBundle loadBundle(String packageName)
          {
              try {
                  return ResourceBundle.getBundle(packageName + '.' + _resourceName,
                                                  _locale,
                                                  _loader);
              } catch (MissingResourceException e) {
                  log.debug("loadBundle: Ignoring MissingResourceException", e);
              }
              return null;
          }
      
          ResourceBundle getParentBundle(String packageName)
          {
              ResourceBundle p;
              if (packageName != _projectName) {
                  p = getBundle(this, getPackage(packageName));
              } else {
                  p = _parent;
                  _parent = null;
              }
              return p;
          }
          
          String validate(String packageName)
              throws MissingResourceException
          {
              if (_projectName == null  ||  _projectName.length() == 0) {
                  log.debug("Project name not specified");
                  throw new MissingResourceException("Project name not specified",
                                                     "", "");
              }
  
              if (packageName == null  ||  packageName.length() == 0) {
                  log.debug("Package name not specified");
                  throw new MissingResourceException("Package not specified",
                                                     packageName, "");
              }
              packageName = packageName.intern();
      
              /* Ensure that project is a proper prefix of class.
               * Terminate project name with '.' to ensure proper match.
               */
              if (packageName != _projectName  &&  !packageName.startsWith(_projectName + '.')) {
                  log.debug("Project not a prefix of Package");
                  throw new MissingResourceException("Project '" + _projectName
                                   + "' must be a prefix of Package '"
                                   + packageName + "'",
                                   packageName + '.' + _resourceName, "");
              }
                  
              return packageName;
          }
      }
  }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/i18n/Messages.java
  
  Index: Messages.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.i18n;
  
  import java.util.Locale;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  
  /**
   * FUNCTIONAL TEMPLATE for Messages classes.
   * 
   * Copy this template to your package, edit the following attributes
   * as/if necessary:
   * 
   *   projectName
   *   packageName
   *   resourceName
   *   classLoader
   *   locale
   *   parent   - The ROOT Messages resource bundle should not define this..
   *              For all other bundles in AXIS, this should point to the root.
   * 
   * @author Richard A. Sitze (rsitze@us.ibm.com)
   * @author Karl Moss (kmoss@macromedia.com)
   * @author Glen Daniels (gdaniels@macromedia.com)
   */
  public class Messages {
      private static final Class  thisClass = Messages.class;
      private static final String projectName = MessagesConstants.projectName;
      private static final String packageName = getPackage(thisClass.getName());
      private static final String resourceName = MessagesConstants.resourceName;
      private static final Locale locale = MessagesConstants.locale;
      private static final ClassLoader classLoader = thisClass.getClassLoader();
      private static final ResourceBundle parent = MessagesConstants.rootBundle;
  
  
      /***** NO NEED TO CHANGE ANYTHING BELOW *****/
  
      private static final ExtendMessages rb = new ExtendMessages(resourceName, parent) {
              protected String getPackageName() { return packageName; }
              protected String getProjectName() { return projectName; }
              protected ClassLoader getClassLoader() { return classLoader; }
              protected Locale getLocale() { return locale; }
          };
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @return The formatted message
        */
      public static String getMessage(String key)
          throws MissingResourceException
      {
          return rb.getMessage(key);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @return The formatted message
        */
      public static String getMessage(String key, String arg0)
          throws MissingResourceException
      {
          return rb.getMessage(key, arg0);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @return The formatted message
        */
      public static String getMessage(String key, String arg0, String arg1)
          throws MissingResourceException
      {
          return rb.getMessage(key, arg0, arg1);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @return The formatted message
        */
      public static String getMessage(String key, String arg0, String arg1, String arg2)
          throws MissingResourceException
      {
          return rb.getMessage(key, arg0, arg1, arg2);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @return The formatted message
        */
      public static String getMessage(String key, String arg0, String arg1, String arg2, String arg3)
          throws MissingResourceException
      {
          return rb.getMessage(key, arg0, arg1, arg2, arg3);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param arg0 The argument to place in variable {0}
        * @param arg1 The argument to place in variable {1}
        * @param arg2 The argument to place in variable {2}
        * @param arg3 The argument to place in variable {3}
        * @param arg4 The argument to place in variable {4}
        * @return The formatted message
        */
      public static String getMessage(String key, String arg0, String arg1, String arg2, String arg3, String arg4)
          throws MissingResourceException
      {
          return rb.getMessage(key, arg0, arg1, arg2, arg3, arg4);
      }
  
      /**
        * Get a message from resource.properties from the package of the given object.
        * @param caller The calling object, used to get the package name and class loader
        * @param locale The locale
        * @param key The resource key
        * @param array An array of objects to place in corresponding variables
        * @return The formatted message
        */
      public static String getMessage(String key, String[] args)
          throws MissingResourceException
      {
          return rb.getMessage(key, args);
      }
      
      public static ResourceBundle getMessageBundle() {
          return rb.getMessageBundle();
      }
  
      private static final String getPackage(String name) {
          return name.substring(0, name.lastIndexOf('.')).intern();
      }
  }