harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ton...@apache.org
Subject svn commit: r548943 - in /harmony/enhanced/classlib/branches/java6/modules/luni/src: main/java/java/util/ResourceBundle.java test/api/common/tests/api/java/util/ResourceBundleTest.java
Date Wed, 20 Jun 2007 05:51:51 GMT
Author: tonywu
Date: Tue Jun 19 22:51:50 2007
New Revision: 548943

URL: http://svn.apache.org/viewvc?view=rev&rev=548943
Log:
Apply patch HARMONY-4209 ([classlib][luni][java6] New feature of java.util.ResourceBundle for java6)

Modified:
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/ResourceBundle.java
    harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/ResourceBundleTest.java

Modified: harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/ResourceBundle.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/ResourceBundle.java?view=diff&rev=548943&r1=548942&r2=548943
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/ResourceBundle.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/ResourceBundle.java Tue Jun 19 22:51:50 2007
@@ -17,8 +17,11 @@
 
 package java.util;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
@@ -37,6 +40,10 @@
  */
 public abstract class ResourceBundle {
 
+    private static final String UNDER_SCORE = "_"; //$NON-NLS-1$
+
+    private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
     /**
      * The parent of this ResourceBundle.
      */
@@ -44,6 +51,8 @@
 
     private Locale locale;
 
+    private long lastLoadTime = 0;
+
     static class MissingBundle extends ResourceBundle {
         @Override
         public Enumeration<String> getKeys() {
@@ -125,21 +134,198 @@
         if (bundleName != null) {
             ResourceBundle bundle;
             if (!locale.equals(Locale.getDefault())) {
-                if ((bundle = handleGetBundle(bundleName, "_" + locale, false, //$NON-NLS-1$
-                        loader)) != null) {
+                if ((bundle = handleGetBundle(bundleName, UNDER_SCORE + locale,
+                        false, loader)) != null) {
                     return bundle;
                 }
             }
-            if ((bundle = handleGetBundle(bundleName,
-                    "_" + Locale.getDefault(), true, loader)) != null) { //$NON-NLS-1$
+            if ((bundle = handleGetBundle(bundleName, UNDER_SCORE
+                    + Locale.getDefault(), true, loader)) != null) {
                 return bundle;
             }
             throw new MissingResourceException(null, bundleName + '_' + locale,
-                    ""); //$NON-NLS-1$
+                    EMPTY_STRING);
         }
         throw new NullPointerException();
     }
 
+    /**
+     * Finds the named resource bundle for the specified base name and control.
+     * 
+     * @param baseName
+     *            the base name of a resource bundle
+     * @param control
+     *            the control that control the access sequence
+     * @return the named resource bundle
+     * 
+     * @since 1.6
+     */
+    public static final ResourceBundle getBundle(String baseName,
+            ResourceBundle.Control control) {
+        return getBundle(baseName, Locale.getDefault(), getLoader(), control);
+    }
+
+    /**
+     * Finds the named resource bundle for the specified base name and control.
+     * 
+     * @param baseName
+     *            the base name of a resource bundle
+     * @param targetLocale
+     *            the target locale of the resource bundle
+     * @param control
+     *            the control that control the access sequence
+     * @return the named resource bundle
+     * 
+     * @since 1.6
+     */
+    public static final ResourceBundle getBundle(String baseName,
+            Locale targetLocale, ResourceBundle.Control control) {
+        return getBundle(baseName, targetLocale, getLoader(), control);
+    }
+
+    private static ClassLoader getLoader() {
+        return AccessController
+                .doPrivileged(new PrivilegedAction<ClassLoader>() {
+                    public ClassLoader run() {
+                        ClassLoader cl = this.getClass().getClassLoader();
+                        if (null == cl) {
+                            cl = ClassLoader.getSystemClassLoader();
+                        }
+                        return cl;
+                    }
+                });
+    }
+
+    /**
+     * Finds the named resource bundle for the specified base name and control.
+     * 
+     * @param baseName
+     *            the base name of a resource bundle
+     * @param targetLocale
+     *            the target locale of the resource bundle
+     * @param loader
+     *            the class loader to load resource
+     * @param control
+     *            the control that control the access sequence
+     * @return the named resource bundle
+     * 
+     * @since 1.6
+     */
+    public static ResourceBundle getBundle(String baseName,
+            Locale targetLocale, ClassLoader loader,
+            ResourceBundle.Control control) {
+        boolean expired = false;
+        String bundleName = control.toBundleName(baseName, targetLocale);
+        Object cacheKey = loader != null ? (Object) loader : (Object) "null"; //$NON-NLS-1$
+        Hashtable<String, ResourceBundle> loaderCache;
+        // try to find in cache
+        synchronized (cache) {
+            loaderCache = cache.get(cacheKey);
+            if (loaderCache == null) {
+                loaderCache = new Hashtable<String, ResourceBundle>();
+                cache.put(cacheKey, loaderCache);
+            }
+        }
+        ResourceBundle result = loaderCache.get(bundleName);
+        if (result != null) {
+            long time = control.getTimeToLive(baseName, targetLocale);
+            if (time == 0 || time == Control.TTL_NO_EXPIRATION_CONTROL
+                    || time + result.lastLoadTime < System.currentTimeMillis()) {
+                if (MISSING == result) {
+                    throw new MissingResourceException(null, bundleName + '_'
+                            + targetLocale, EMPTY_STRING);
+                }
+                return result;
+            }
+            expired = true;
+        }
+        // try to load
+        ResourceBundle ret = processGetBundle(baseName, targetLocale, loader,
+                control, expired, result);
+
+        if (null != ret) {
+            loaderCache.put(bundleName, ret);
+            ret.lastLoadTime = System.currentTimeMillis();
+            return ret;
+        }
+        loaderCache.put(bundleName, MISSING);
+        throw new MissingResourceException(null, bundleName + '_'
+                + targetLocale, EMPTY_STRING);
+    }
+
+    private static ResourceBundle processGetBundle(String baseName,
+            Locale targetLocale, ClassLoader loader,
+            ResourceBundle.Control control, boolean expired,
+            ResourceBundle result) {
+        List<Locale> locales = control.getCandidateLocales(baseName,
+                targetLocale);
+        if (null == locales) {
+            throw new IllegalArgumentException();
+        }
+        List<String> formats = control.getFormats(baseName);
+        if (Control.FORMAT_CLASS == formats
+                || Control.FORMAT_PROPERTIES == formats
+                || Control.FORMAT_DEFAULT == formats) {
+            throw new IllegalArgumentException();
+        }
+        ResourceBundle ret = null;
+        ResourceBundle currentBundle = null;
+        ResourceBundle bundle = null;
+        for (Locale locale : locales) {
+            for (String format : formats) {
+                try {
+                    if (expired) {
+                        bundle = control.newBundle(baseName, locale, format,
+                                loader, control.needsReload(baseName, locale,
+                                        format, loader, result, System
+                                                .currentTimeMillis()));
+
+                    } else {
+                        try {
+                            bundle = control.newBundle(baseName, locale,
+                                    format, loader, false);
+                        } catch (IllegalArgumentException e) {
+                            // do nothing
+                        }
+                    }
+                } catch (IllegalAccessException e) {
+                    // do nothing
+                } catch (InstantiationException e) {
+                    // do nothing
+                } catch (IOException e) {
+                    // do nothing
+                }
+                if (null != bundle) {
+                    if (null != currentBundle) {
+                        currentBundle.setParent(bundle);
+                        currentBundle = bundle;
+                    } else {
+                        if (null == ret) {
+                            ret = bundle;
+                            currentBundle = ret;
+                        }
+                    }
+                }
+                if (null != bundle) {
+                    break;
+                }
+            }
+        }
+
+        if ((null == ret)
+                || (Locale.ROOT.equals(ret.getLocale()) && (!(locales.size() == 1 && locales
+                        .contains(Locale.ROOT))))) {
+            Locale nextLocale = control.getFallbackLocale(baseName,
+                    targetLocale);
+            if (null != nextLocale) {
+                ret = processGetBundle(baseName, nextLocale, loader, control,
+                        expired, result);
+            }
+        }
+
+        return ret;
+    }
+
     private static ResourceBundle getBundleImpl(String bundleName,
             Locale locale, ClassLoader loader) throws MissingResourceException {
         if (bundleName != null) {
@@ -147,7 +333,7 @@
             if (!locale.equals(Locale.getDefault())) {
                 String localeName = locale.toString();
                 if (localeName.length() > 0) {
-                    localeName = "_" + localeName; //$NON-NLS-1$
+                    localeName = UNDER_SCORE + localeName;
                 }
                 if ((bundle = handleGetBundle(bundleName, localeName, false,
                         loader)) != null) {
@@ -156,13 +342,13 @@
             }
             String localeName = Locale.getDefault().toString();
             if (localeName.length() > 0) {
-                localeName = "_" + localeName; //$NON-NLS-1$
+                localeName = UNDER_SCORE + localeName;
             }
             if ((bundle = handleGetBundle(bundleName, localeName, true, loader)) != null) {
                 return bundle;
             }
             throw new MissingResourceException(null, bundleName + '_' + locale,
-                    ""); //$NON-NLS-1$
+                    EMPTY_STRING);
         }
         throw new NullPointerException();
     }
@@ -243,7 +429,7 @@
         synchronized (cache) {
             loaderCache = cache.get(cacheKey);
             if (loaderCache == null) {
-                loaderCache = new Hashtable<String, ResourceBundle>(13);
+                loaderCache = new Hashtable<String, ResourceBundle>();
                 cache.put(cacheKey, loaderCache);
             }
         }
@@ -298,6 +484,7 @@
                     }
                     bundle.setLocale(locale);
                 } catch (IOException e) {
+                    // do nothing
                 }
             }
         }
@@ -355,8 +542,12 @@
         return null;
     }
 
+    private void setLocale(Locale locale) {
+        this.locale = locale;
+    }
+
     private void setLocale(String name) {
-        String language = "", country = "", variant = ""; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+        String language = EMPTY_STRING, country = EMPTY_STRING, variant = EMPTY_STRING;
         if (name.length() > 1) {
             int nextIndex = name.indexOf('_', 1);
             if (nextIndex == -1) {
@@ -376,5 +567,502 @@
             }
         }
         locale = new Locale(language, country, variant);
+    }
+
+    public static final void clearCache() {
+        cache.remove(ClassLoader.getSystemClassLoader());
+    }
+
+    public static final void clearCache(ClassLoader loader) {
+        if (null == loader) {
+            throw new NullPointerException();
+        }
+        cache.remove(loader);
+    }
+
+    public boolean containsKey(String key) {
+        if (null == key) {
+            throw new NullPointerException();
+        }
+        return keySet().contains(key);
+    }
+
+    public Set<String> keySet() {
+        Set<String> ret = new HashSet<String>();
+        Enumeration<String> keys = getKeys();
+        while (keys.hasMoreElements()) {
+            ret.add(keys.nextElement());
+        }
+        return ret;
+    }
+
+    protected Set<String> handleKeySet() {
+        Set<String> set = keySet();
+        Set<String> ret = new HashSet<String>();
+        for (String key : set) {
+            if (null != handleGetObject(key)) {
+                ret.add(key);
+            }
+        }
+        return ret;
+    }
+
+    private static class NoFallbackControl extends Control {
+
+        static final Control NOFALLBACK_FORMAT_PROPERTIES_CONTROL = new NoFallbackControl(
+                JAVAPROPERTIES);
+
+        static final Control NOFALLBACK_FORMAT_CLASS_CONTROL = new NoFallbackControl(
+                JAVACLASS);
+
+        static final Control NOFALLBACK_FORMAT_DEFAULT_CONTROL = new NoFallbackControl(
+                listDefault);
+
+        public NoFallbackControl(String format) {
+            super();
+            listClass = new ArrayList<String>();
+            listClass.add(format);
+            super.format = Collections.unmodifiableList(listClass);
+        }
+
+        public NoFallbackControl(List<String> list) {
+            super();
+            super.format = list;
+        }
+
+        @Override
+        public Locale getFallbackLocale(String baseName, Locale locale) {
+            if (null == baseName || null == locale) {
+                throw new NullPointerException();
+            }
+            return null;
+        }
+    }
+
+    private static class SimpleControl extends Control {
+        public SimpleControl(String format) {
+            super();
+            listClass = new ArrayList<String>();
+            listClass.add(format);
+            super.format = Collections.unmodifiableList(listClass);
+        }
+    }
+
+    @SuppressWarnings("nls")
+    /**
+     * ResourceBundle.Control is a static utility class defines ResourceBundle
+     * load access methods, its default access order is as the same as before.
+     * However users can implement their own control.
+     * 
+     * @since 1.6
+     */
+    public static class Control {
+        static List<String> listDefault = new ArrayList<String>();
+
+        static List<String> listClass = new ArrayList<String>();
+
+        static List<String> listProperties = new ArrayList<String>();
+
+        static String JAVACLASS = "java.class";
+
+        static String JAVAPROPERTIES = "java.properties";
+
+        static {
+            listDefault.add(JAVACLASS);
+            listDefault.add(JAVAPROPERTIES);
+            listClass.add(JAVACLASS);
+            listProperties.add(JAVAPROPERTIES);
+        }
+
+        /**
+         * a list defines default format
+         */
+        public static final List<String> FORMAT_DEFAULT = Collections
+                .unmodifiableList(listDefault);
+
+        /**
+         * a list defines java class format
+         */
+        public static final List<String> FORMAT_CLASS = Collections
+                .unmodifiableList(listClass);
+
+        /**
+         * a list defines property format
+         */
+        public static final List<String> FORMAT_PROPERTIES = Collections
+                .unmodifiableList(listProperties);
+
+        /**
+         * a constant that indicates cache will not be used.
+         */
+        public static final long TTL_DONT_CACHE = -1L;
+
+        /**
+         * a constant that indicates cache will not be expired.
+         */
+        public static final long TTL_NO_EXPIRATION_CONTROL = -2L;
+
+        private static final Control FORMAT_PROPERTIES_CONTROL = new SimpleControl(
+                JAVAPROPERTIES);
+
+        private static final Control FORMAT_CLASS_CONTROL = new SimpleControl(
+                JAVACLASS);
+
+        private static final Control FORMAT_DEFAULT_CONTROL = new Control();
+
+        List<String> format;
+
+        /**
+         * default constructor
+         * 
+         */
+        protected Control() {
+            super();
+            listClass = new ArrayList<String>();
+            listClass.add(JAVACLASS);
+            listClass.add(JAVAPROPERTIES);
+            format = Collections.unmodifiableList(listClass);
+        }
+
+        /**
+         * Answers a control according to the given format list
+         * 
+         * @param formats
+         *            a format to use
+         * @return a control according to the given format list
+         */
+        public static final Control getControl(List<String> formats) {
+            switch (formats.size()) {
+            case 1:
+                if (formats.contains(JAVACLASS)) {
+                    return FORMAT_CLASS_CONTROL;
+                }
+                if (formats.contains(JAVAPROPERTIES)) {
+                    return FORMAT_PROPERTIES_CONTROL;
+                }
+                break;
+            case 2:
+                if (formats.equals(FORMAT_DEFAULT)) {
+                    return FORMAT_DEFAULT_CONTROL;
+                }
+                break;
+            }
+            throw new IllegalArgumentException();
+        }
+
+        /**
+         * Answers a control according to the given format list whose fallback
+         * locale is null
+         * 
+         * @param formats
+         *            a format to use
+         * @return a control according to the given format list whose fallback
+         *         locale is null
+         */
+        public static final Control getNoFallbackControl(List<String> formats) {
+            switch (formats.size()) {
+            case 1:
+                if (formats.contains(JAVACLASS)) {
+                    return NoFallbackControl.NOFALLBACK_FORMAT_CLASS_CONTROL;
+                }
+                if (formats.contains(JAVAPROPERTIES)) {
+                    return NoFallbackControl.NOFALLBACK_FORMAT_PROPERTIES_CONTROL;
+                }
+                break;
+            case 2:
+                if (formats.equals(FORMAT_DEFAULT)) {
+                    return NoFallbackControl.NOFALLBACK_FORMAT_DEFAULT_CONTROL;
+                }
+                break;
+            }
+            throw new IllegalArgumentException();
+        }
+
+        /**
+         * Answers a list of candidate locales according to the base name and
+         * locale
+         * 
+         * @param baseName
+         *            the base name to use
+         * @param locale
+         *            the locale
+         * @return the candidate locales according to the base name and locale
+         */
+        public List<Locale> getCandidateLocales(String baseName, Locale locale) {
+            if (null == baseName || null == locale) {
+                throw new NullPointerException();
+            }
+            List<Locale> retList = new ArrayList<Locale>();
+            String language = locale.getLanguage();
+            String country = locale.getCountry();
+            String variant = locale.getVariant();
+            if (!EMPTY_STRING.equals(variant)) {
+                retList.add(new Locale(language, country, variant));
+            }
+            if (!EMPTY_STRING.equals(country)) {
+                retList.add(new Locale(language, country));
+            }
+            if (!EMPTY_STRING.equals(language)) {
+                retList.add(new Locale(language));
+            }
+            retList.add(Locale.ROOT);
+            return retList;
+        }
+
+        /**
+         * Answers a list of strings of formats according to the base name
+         * 
+         * @param baseName
+         *            the base name to use
+         * @return a list of strings of formats according to the base name
+         */
+        public List<String> getFormats(String baseName) {
+            if (null == baseName) {
+                throw new NullPointerException();
+            }
+            return format;
+        }
+
+        /**
+         * Answers a list of strings of locales according to the base name
+         * 
+         * @param baseName
+         *            the base name to use
+         * @return a list of strings of locales according to the base name
+         */
+        public Locale getFallbackLocale(String baseName, Locale locale) {
+            if (null == baseName || null == locale) {
+                throw new NullPointerException();
+            }
+            if (Locale.getDefault() != locale) {
+                return Locale.getDefault();
+            }
+            return null;
+        }
+
+        /**
+         * Answers a new ResourceBundle according to the give parameters
+         * 
+         * @param baseName
+         *            the base name to use
+         * @param locale
+         *            the given locale
+         * @param format
+         *            the format, default is "java.class" or "java.properities"
+         * @param loader
+         *            the classloader to use
+         * @param reload
+         *            if reload the resource
+         * @return a new ResourceBundle according to the give parameters
+         * @throws IllegalAccessException
+         *             if can not access resources
+         * @throws InstantiationException
+         *             if can not instante a resource class
+         * @throws IOException
+         *             if other I/O exception happens
+         */
+        public ResourceBundle newBundle(String baseName, Locale locale,
+                String format, ClassLoader loader, boolean reload)
+                throws IllegalAccessException, InstantiationException,
+                IOException {
+            if (null == format || null == loader) {
+                throw new NullPointerException();
+            }
+            InputStream streams = null;
+            final String bundleName = toBundleName(baseName, locale);
+            final ClassLoader clsloader = loader;
+            ResourceBundle ret;
+            Class<?> cls = null;
+            if (JAVACLASS == format) {
+                cls = AccessController
+                        .doPrivileged(new PrivilegedAction<Class<?>>() {
+                            public Class<?> run() {
+                                try {
+                                    return clsloader.loadClass(bundleName);
+                                } catch (Exception e) {
+                                    return null;
+                                } catch (NoClassDefFoundError e) {
+                                    return null;
+                                }
+                            }
+                        });
+                if (null == cls) {
+                    return null;
+                }
+                try {
+                    ResourceBundle bundle = (ResourceBundle) cls.newInstance();
+                    bundle.setLocale(locale);
+                    return bundle;
+                } catch (NullPointerException e) {
+                    return null;
+                }
+            }
+            if (JAVAPROPERTIES == format) {
+                final String resourceName = toResourceName(bundleName,
+                        "properties");
+                if (reload) {
+                    URL url = null;
+                    try {
+                        url = loader.getResource(resourceName);
+                    } catch (NullPointerException e) {
+                        // do nothing
+                    }
+                    if (null != url) {
+                        URLConnection con = url.openConnection();
+                        con.setUseCaches(false);
+                        streams = con.getInputStream();
+                    }
+                } else {
+                    try {
+                        streams = AccessController
+                                .doPrivileged(new PrivilegedAction<InputStream>() {
+                                    public InputStream run() {
+                                        return clsloader
+                                                .getResourceAsStream(resourceName);
+                                    }
+                                });
+                    } catch (NullPointerException e) {
+                        // do nothing
+                    }
+                }
+                if (streams != null) {
+                    try {
+                        ret = new PropertyResourceBundle(streams);
+                        ret.setLocale(locale);
+                        streams.close();
+                    } catch (IOException e) {
+                        return null;
+                    }
+                    return ret;
+                }
+                return null;
+            }
+            throw new IllegalArgumentException();
+        }
+
+        /**
+         * Answers the time to live of the ResourceBundle, default is
+         * TTL_NO_EXPIRATION_CONTROL
+         * 
+         * @param baseName
+         *            the base name to use
+         * @param locale
+         *            the locale to use
+         * @return TTL_NO_EXPIRATION_CONTROL
+         */
+        public long getTimeToLive(String baseName, Locale locale) {
+            if (null == baseName || null == locale) {
+                throw new NullPointerException();
+            }
+            return TTL_NO_EXPIRATION_CONTROL;
+        }
+
+        /**
+         * Answers if the ResourceBundle needs to reload
+         * 
+         * @param baseName
+         *            the base name of the ResourceBundle
+         * @param locale
+         *            the locale of the ResourceBundle
+         * @param format
+         *            the format to load
+         * @param loader
+         *            the ClassLoader to load resource
+         * @param bundle
+         *            the ResourceBundle
+         * @param loadTime
+         *            the expired time
+         * @return if the ResourceBundle needs to reload
+         */
+        public boolean needsReload(String baseName, Locale locale,
+                String format, ClassLoader loader, ResourceBundle bundle,
+                long loadTime) {
+            if (null == bundle) {
+                // FIXME what's the use of bundle?
+                throw new NullPointerException();
+            }
+            String bundleName = toBundleName(baseName, locale);
+            String suffix = format;
+            if (JAVACLASS == format) {
+                suffix = "class";
+            }
+            if (JAVAPROPERTIES == format) {
+                suffix = "properties";
+            }
+            String urlname = toResourceName(bundleName, suffix);
+            URL url = loader.getResource(urlname);
+            if (null != url) {
+                String fileName = url.getFile();
+                long lastModified = new File(fileName).lastModified();
+                if (lastModified > loadTime) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * a utility method to answer the name of a resource bundle according to
+         * the given base name and locale
+         * 
+         * @param baseName
+         *            the given base name
+         * @param locale
+         *            the locale to use
+         * @return the name of a resource bundle according to the given base
+         *         name and locale
+         */
+        public String toBundleName(String baseName, Locale locale) {
+            final String emptyString = EMPTY_STRING;
+            final String preString = UNDER_SCORE;
+            final String underline = UNDER_SCORE;
+            if (null == baseName) {
+                throw new NullPointerException();
+            }
+            StringBuilder ret = new StringBuilder();
+            StringBuilder prefix = new StringBuilder();
+            ret.append(baseName);
+            if (!locale.getLanguage().equals(emptyString)) {
+                ret.append(underline);
+                ret.append(locale.getLanguage());
+            } else {
+                prefix.append(preString);
+            }
+            if (!locale.getCountry().equals(emptyString)) {
+                ret.append((CharSequence) prefix);
+                ret.append(underline);
+                ret.append(locale.getCountry());
+                prefix = new StringBuilder();
+            } else {
+                prefix.append(preString);
+            }
+            if (!locale.getVariant().equals(emptyString)) {
+                ret.append((CharSequence) prefix);
+                ret.append(underline);
+                ret.append(locale.getVariant());
+            }
+            return ret.toString();
+        }
+
+        /**
+         * a utility method to answer the name of a resource according to the
+         * given bundleName and suffix
+         * 
+         * @param baseName
+         *            the given base name
+         * @param suffix
+         *            the suffix
+         * @return the name of a resource according to the given bundleName and
+         *         suffix
+         */
+        public final String toResourceName(String bundleName, String suffix) {
+            if (null == suffix) {
+                throw new NullPointerException();
+            }
+            StringBuilder ret = new StringBuilder(bundleName.replace('.', '/'));
+            ret.append('.');
+            ret.append(suffix);
+            return ret.toString();
+        }
     }
 }

Modified: harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/ResourceBundleTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/ResourceBundleTest.java?view=diff&rev=548943&r1=548942&r2=548943
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/ResourceBundleTest.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/ResourceBundleTest.java Tue Jun 19 22:51:50 2007
@@ -17,148 +17,221 @@
 
 package tests.api.java.util;
 
+import static java.util.ResourceBundle.Control.FORMAT_CLASS;
+import static java.util.ResourceBundle.Control.FORMAT_DEFAULT;
+import static java.util.ResourceBundle.Control.FORMAT_PROPERTIES;
+
 import java.io.File;
+import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.Vector;
+import java.util.ResourceBundle.Control;
 
+import tests.api.java.util.ControlTest.CanSetSM;
 import tests.support.resource.Support_Resources;
 import tests.api.java.util.support.B;
 
+/**
+ * Test cases for java.util.ResourceBundle.
+ */
 public class ResourceBundleTest extends junit.framework.TestCase {
 
-	/**
-	 * @tests java.util.ResourceBundle#getBundle(java.lang.String,
-	 *        java.util.Locale)
-	 */
-	public void test_getBundleLjava_lang_StringLjava_util_Locale() {
-		ResourceBundle bundle;
-		String name = "tests.support.Support_TestResource";
-		Locale defLocale = Locale.getDefault();
-
-		Locale.setDefault(new Locale("en", "US"));
-		bundle = ResourceBundle.getBundle(name, new Locale("fr", "FR", "VAR"));
-		assertEquals("Wrong bundle fr_FR_VAR", "frFRVARValue4", bundle.getString("parent4")
-				);
-		bundle = ResourceBundle.getBundle(name, new Locale("fr", "FR", "v1"));
-		assertEquals("Wrong bundle fr_FR_v1", 
-				"frFRValue4", bundle.getString("parent4"));
-		bundle = ResourceBundle.getBundle(name, new Locale("fr", "US", "VAR"));
-		assertEquals("Wrong bundle fr_US_var", "frValue4", bundle.getString("parent4")
-				);
-		bundle = ResourceBundle.getBundle(name, new Locale("de", "FR", "VAR"));
-		assertEquals("Wrong bundle de_FR_var", "enUSValue4", bundle.getString("parent4")
-				);
-
-		Locale.setDefault(new Locale("fr", "FR", "VAR"));
-		bundle = ResourceBundle.getBundle(name, new Locale("de", "FR", "v1"));
-		assertEquals("Wrong bundle de_FR_var 2", "frFRVARValue4", bundle.getString("parent4")
-				);
-
-		Locale.setDefault(new Locale("de", "US"));
-		bundle = ResourceBundle.getBundle(name, new Locale("de", "FR", "var"));
-		assertEquals("Wrong bundle de_FR_var 2", "parentValue4", bundle.getString("parent4")
-				);
-
-		// Test with a security manager
-		Locale.setDefault(new Locale("en", "US"));
-		System.setSecurityManager(new SecurityManager());
-		try {
-			bundle = ResourceBundle.getBundle(name, new Locale("fr", "FR",
-					"VAR"));
-			assertEquals("Security: Wrong bundle fr_FR_VAR", "frFRVARValue4", bundle.getString(
-					"parent4"));
-			bundle = ResourceBundle.getBundle(name,
-					new Locale("fr", "FR", "v1"));
-			assertEquals("Security: Wrong bundle fr_FR_v1", "frFRValue4", bundle.getString(
-					"parent4"));
-			bundle = ResourceBundle.getBundle(name, new Locale("fr", "US",
-					"VAR"));
-			assertEquals("Security: Wrong bundle fr_US_var", "frValue4", bundle.getString(
-					"parent4"));
-			bundle = ResourceBundle.getBundle(name, new Locale("de", "FR",
-					"VAR"));
-			assertTrue("Security: Wrong bundle de_FR_var: "
-					+ bundle.getString("parent4"), bundle.getString("parent4")
-					.equals("enUSValue4"));
-		} finally {
-			System.setSecurityManager(null);
-		}
-
-		Locale.setDefault(defLocale);
-	}
-
-	/**
-	 * @tests java.util.ResourceBundle#getBundle(java.lang.String,
-	 *        java.util.Locale, java.lang.ClassLoader)
-	 */
-	public void test_getBundleLjava_lang_StringLjava_util_LocaleLjava_lang_ClassLoader() {
-		String classPath = System.getProperty("java.class.path");
-		StringTokenizer tok = new StringTokenizer(classPath, File.pathSeparator);
-		Vector urlVec = new Vector();
-		String resPackage = Support_Resources.RESOURCE_PACKAGE;
-		try {
-			while (tok.hasMoreTokens()) {
-				String path = (String) tok.nextToken();
-				String url;
-				if (new File(path).isDirectory())
-					url = "file:" + path + resPackage + "subfolder/";
-				else
-					url = "jar:file:" + path + "!" + resPackage + "subfolder/";
-				urlVec.addElement(new URL(url));
-			}
-		} catch (MalformedURLException e) {
-		}
-		URL[] urls = new URL[urlVec.size()];
-		for (int i = 0; i < urlVec.size(); i++)
-			urls[i] = (URL) urlVec.elementAt(i);
-		URLClassLoader loader = new URLClassLoader(urls, null);
-
-		String name = Support_Resources.RESOURCE_PACKAGE_NAME
-				+ ".hyts_resource";
-		ResourceBundle bundle = ResourceBundle.getBundle(name, Locale
-				.getDefault());
-            assertEquals("Wrong value read", "parent", bundle.getString("property"));
-		bundle = ResourceBundle.getBundle(name, Locale.getDefault(), loader);
-		assertEquals("Wrong cached value", 
-				"resource", bundle.getString("property"));
-
-		// Regression test for Harmony-3823
-		B bb = new B();
-		String s = bb.find("nonexistent");
-		s = bb.find("name");
-		assertEquals("Wrong property got", "Name", s);
-	}
-
-	/**
-	 * @tests java.util.ResourceBundle#getString(java.lang.String)
-	 */
-	public void test_getStringLjava_lang_String() {
-		ResourceBundle bundle;
-		String name = "tests.support.Support_TestResource";
-		Locale.setDefault(new Locale("en", "US"));
-		bundle = ResourceBundle.getBundle(name, new Locale("fr", "FR", "VAR"));
-		assertEquals("Wrong value parent4", 
-				"frFRVARValue4", bundle.getString("parent4"));
-		assertEquals("Wrong value parent3", 
-				"frFRValue3", bundle.getString("parent3"));
-		assertEquals("Wrong value parent2", 
-				"frValue2", bundle.getString("parent2"));
-		assertEquals("Wrong value parent1", 
-				"parentValue1", bundle.getString("parent1"));
-		assertEquals("Wrong value child3", 
-				"frFRVARChildValue3", bundle.getString("child3"));
-		assertEquals("Wrong value child2", 
-				"frFRVARChildValue2", bundle.getString("child2"));
-		assertEquals("Wrong value child1", 
-				"frFRVARChildValue1", bundle.getString("child1"));
-	}
+    private static final String PROPERTIES_NAME = Support_Resources.RESOURCE_PACKAGE_NAME
+            + ".hyts_resource"; //$NON-NLS-1$
+
+    private static final String SUBFOLDER_PROPERTIES_NAME = "tests.resources.subfolder.tests.resources.hyts_resource"; //$NON-NLS-1$
+
+    private static final String SUBFOLDER_NOROOT_NAME = "tests.resources.subfolder.tests.norootresources.hyts_resource"; //$NON-NLS-1$
+
+    private static final String CLASS_NAME = "tests.support.Support_TestResource"; //$NON-NLS-1$
+
+    private static final String PROPERTIES_NAME_COPY = "hyts_resource_copy"; //$NON-NLS-1$
+
+    private static final ClassLoader URL_LOADER = getURLClassLoader();
+
+    private static final ClassLoader SYSTEM_LOADER = ClassLoader
+            .getSystemClassLoader();
+
+    private static final Control CLASS_CONTROL = Control
+            .getControl(FORMAT_CLASS);
+
+    private static final Control PROPERTIES_CONTROL = Control
+            .getControl(FORMAT_PROPERTIES);
+
+    private static final Control DEFAULT_CONTROL = Control
+            .getControl(FORMAT_DEFAULT);
+
+    @SuppressWarnings("nls")
+    private static final Locale LOCALE_FRFR = new Locale("fr", "FR");
+
+    @SuppressWarnings("nls")
+    private static final Locale LOCALE_FR = new Locale("fr");
+
+    @SuppressWarnings("nls")
+    private static final Locale LOCALE_EN = new Locale("en");
+
+    @SuppressWarnings("nls")
+    private static final Locale LOCALE_ENUSVAR = new Locale("en", "US", "VAR");
 
+    private ResourceBundle bundle;
+
+    private Locale defLocale = null;
+
+    /**
+     * @tests java.util.ResourceBundle#getBundle(java.lang.String,
+     *        java.util.Locale)
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundleLjava_lang_StringLjava_util_Locale() {
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr", "FR",
+                "VAR"));
+        assertEquals("Wrong bundle fr_FR_VAR", "frFRVARValue4", bundle
+                .getString("parent4"));
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr", "FR",
+                "v1"));
+        assertEquals("Wrong bundle fr_FR_v1", "frFRValue4", bundle
+                .getString("parent4"));
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr", "US",
+                "VAR"));
+        assertEquals("Wrong bundle fr_US_var", "frValue4", bundle
+                .getString("parent4"));
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("de", "FR",
+                "VAR"));
+        assertEquals("Wrong bundle de_FR_var", "enUSValue4", bundle
+                .getString("parent4"));
+
+        Locale.setDefault(new Locale("fr", "FR", "VAR"));
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("de", "FR",
+                "v1"));
+        assertEquals("Wrong bundle de_FR_var 2", "frFRVARValue4", bundle
+                .getString("parent4"));
+
+        Locale.setDefault(new Locale("de", "US"));
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("de", "FR",
+                "var"));
+        assertEquals("Wrong bundle de_FR_var 2", "parentValue4", bundle
+                .getString("parent4"));
+
+        // Test with a security manager
+        Locale.setDefault(new Locale("en", "US"));
+        System.setSecurityManager(new SecurityManager());
+        try {
+            bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr",
+                    "FR", "VAR"));
+            assertEquals("Security: Wrong bundle fr_FR_VAR", "frFRVARValue4",
+                    bundle.getString("parent4"));
+            bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr",
+                    "FR", "v1"));
+            assertEquals("Security: Wrong bundle fr_FR_v1", "frFRValue4",
+                    bundle.getString("parent4"));
+            bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr",
+                    "US", "VAR"));
+            assertEquals("Security: Wrong bundle fr_US_var", "frValue4", bundle
+                    .getString("parent4"));
+            bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("de",
+                    "FR", "VAR"));
+            assertTrue("Security: Wrong bundle de_FR_var: "
+                    + bundle.getString("parent4"), bundle.getString("parent4")
+                    .equals("enUSValue4"));
+        } finally {
+            System.setSecurityManager(null);
+        }
+    }
+
+    /**
+     * @tests java.util.ResourceBundle#getBundle(java.lang.String,
+     *        java.util.Locale, java.lang.ClassLoader)
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundleLjava_lang_StringLjava_util_LocaleLjava_lang_ClassLoader() {
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_EN);
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_EN,
+                URL_LOADER);
+        assertEquals("Wrong cached value", "en_resource", bundle
+                .getString("property"));
+
+        // Regression test for Harmony-3823
+        B bb = new B();
+        String s = bb.find("nonexistent");
+        s = bb.find("name");
+        assertEquals("Wrong property got", "Name", s);
+    }
+
+    @SuppressWarnings("nls")
+    static URLClassLoader getURLClassLoader() {
+        String classPath = System.getProperty("java.class.path");
+        StringTokenizer tok = new StringTokenizer(classPath, File.pathSeparator);
+        Vector<URL> urlVec = new Vector<URL>();
+        String resPackage = Support_Resources.RESOURCE_PACKAGE;
+        try {
+            while (tok.hasMoreTokens()) {
+                String path = tok.nextToken();
+                String url;
+                if (new File(path).isDirectory()) {
+                    url = "file:" + path + resPackage + "subfolder/";
+                } else {
+                    url = "jar:file:" + path + "!" + resPackage + "subfolder/";
+                }
+                urlVec.addElement(new URL(url));
+            }
+        } catch (MalformedURLException e) {
+            // ignore
+        }
+        // add temp path if possible
+        String tmpdir = System.getProperty("java.io.tmpdir");
+        if (null != tmpdir) {
+            try {
+                urlVec.add(new URL("file:" + tmpdir));
+            } catch (MalformedURLException e) {
+                // ignore
+            }
+        }
+        URL[] urls = new URL[urlVec.size()];
+        for (int i = 0; i < urlVec.size(); i++) {
+            urls[i] = urlVec.elementAt(i);
+        }
+        URLClassLoader loader = new URLClassLoader(urls, null);
+        return loader;
+    }
+
+    /**
+     * @tests java.util.ResourceBundle#getString(java.lang.String)
+     */
+    @SuppressWarnings("nls")
+    public void test_getStringLjava_lang_String() {
+        bundle = ResourceBundle.getBundle(CLASS_NAME, new Locale("fr", "FR",
+                "VAR"));
+        assertEquals("Wrong value parent4", "frFRVARValue4", bundle
+                .getString("parent4"));
+        assertEquals("Wrong value parent3", "frFRValue3", bundle
+                .getString("parent3"));
+        assertEquals("Wrong value parent2", "frValue2", bundle
+                .getString("parent2"));
+        assertEquals("Wrong value parent1", "parentValue1", bundle
+                .getString("parent1"));
+        assertEquals("Wrong value child3", "frFRVARChildValue3", bundle
+                .getString("child3"));
+        assertEquals("Wrong value child2", "frFRVARChildValue2", bundle
+                .getString("child2"));
+        assertEquals("Wrong value child1", "frFRVARChildValue1", bundle
+                .getString("child1"));
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)}
+     */
+    @SuppressWarnings("nls")
     public void test_getBundle_getClassName() {
         // Regression test for Harmony-1759
         Locale locale = Locale.GERMAN;
@@ -170,7 +243,7 @@
         } catch (MissingResourceException e) {
             assertEquals(nonExistentBundle + "_" + locale, e.getClassName());
         }
-        
+
         try {
             ResourceBundle.getBundle(nonExistentBundle, locale);
             fail("MissingResourceException expected!");
@@ -185,12 +258,979 @@
         } catch (MissingResourceException e) {
             assertEquals(nonExistentBundle + "_" + locale, e.getClassName());
         }
+    }
+
+    /**
+     * Can cause {@link IllegalArgumentException} in getBundle method
+     */
+    static class NullCandidateLocalesControl extends Control {
+        /**
+         * @see java.util.ResourceBundle.Control#getCandidateLocales(java.lang.String,
+         *      java.util.Locale)
+         */
+        @Override
+        public List<Locale> getCandidateLocales(@SuppressWarnings("unused")
+        String baseName, @SuppressWarnings("unused")
+        Locale locale) {
+            return null;
+        }
+    }
+
+    /**
+     * The control with given formats.
+     */
+    static class GivenFormatsControl extends Control {
+        List<String> formats;
+
+        GivenFormatsControl(List<String> theFormats) {
+            super();
+            formats = theFormats;
+        }
+
+        /**
+         * @see java.util.ResourceBundle.Control#getFormats(java.lang.String)
+         */
+        @SuppressWarnings("nls")
+        @Override
+        public List<String> getFormats(@SuppressWarnings("unused")
+        String baseName) {
+            return formats;
+        }
+    }
+
+    /**
+     * The control with reverse formats with default Control and no fallback
+     * locale.
+     */
+    static class ReverseNoFallbackLocaleControl extends Control {
+        /**
+         * @see java.util.ResourceBundle.Control#getFormats(java.lang.String)
+         */
+        @SuppressWarnings("nls")
+        @Override
+        public List<String> getFormats(@SuppressWarnings("unused")
+        String baseName) {
+            return Arrays
+                    .asList(new String[] { "java.properties", "java.class" });
+        }
+
+        /**
+         * @see java.util.ResourceBundle.Control#getFallbackLocale(java.lang.String,
+         *      java.util.Locale)
+         */
+        @Override
+        public Locale getFallbackLocale(@SuppressWarnings("unused")
+        String baseName, @SuppressWarnings("unused")
+        Locale locale) {
+            return null;
+        }
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#getBundle(String, java.util.ResourceBundle.Control)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundle_LStringLControl() {
+        Locale.setDefault(LOCALE_FRFR);
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                DEFAULT_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle("wrongName", DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(null, DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, (Control) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        // illegal control causes IllegalArgumentException
+        Control otherControl = new NullCandidateLocalesControl();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, otherControl);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
 
+    /**
+     * @tests {@link java.util.ResourceBundle#getBundle(String, Locale, java.util.ResourceBundle.Control)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundle_LStringLLocaleLControl() {
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, DEFAULT_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle("wrongName", LOCALE_FRFR, DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(null, LOCALE_FRFR, DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, null,
+                    DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    (Control) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        // illegal control causes IllegalArgumentException
+        Control otherControl = new NullCandidateLocalesControl();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    otherControl);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#getBundle(String, Locale, ClassLoader, java.util.ResourceBundle.Control)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundle_LStringLLocaleLClassLoaderLControl() {
+        getBundleWithControlTester();
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#getBundle(String, Locale, ClassLoader, java.util.ResourceBundle.Control)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_getBundle_LStringLLocaleLClassLoaderLControl_WithSecurityManager() {
+        SecurityManager sm = System.getSecurityManager();
+        try {
+            System.setSecurityManager(new CanSetSM());
+            getBundleWithControlTester();
+        } finally {
+            System.setSecurityManager(sm);
+        }
     }
 
-	protected void setUp() {
-	}
+    @SuppressWarnings("nls")
+    private void getBundleWithControlTester() {
+        // 1. cache feature: is tested in other methods
+        // 2. Formats/Locale
+        // the "reverse" control that take java.properties first
+        Control reverseControl = new GivenFormatsControl(Arrays
+                .asList(new String[] { "java.properties", "java.class" }));
+        // locale that has both class file and properties file support.
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertFalse(bundle.containsKey("subParent1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, reverseControl);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertFalse(bundle.containsKey("subParent1"));
+
+        // locale that has only properties file support.
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_EN,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(5, bundle.keySet().size());
+        assertEquals("en_resource", bundle.getString("property"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("subChild1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_EN,
+                SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue2", bundle.getString("subParent2"));
+        assertEquals("enUSValue3", bundle.getString("subParent3"));
+        assertEquals("enUSValue4", bundle.getString("subParent4"));
+        assertEquals("enUSChildValue1", bundle.getString("subChild1"));
+        assertEquals("enUSChildValue2", bundle.getString("subChild2"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_EN,
+                SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("en_resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_EN,
+                SYSTEM_LOADER, reverseControl);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("en_resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+
+        // locale that has only class file support.
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_ENUSVAR, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(8, bundle.keySet().size());
+        assertEquals("enUSVARChildValue3", bundle.getString("subChild3"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("en_resource", bundle.getString("property"));
+        assertEquals("enUSVARValue4", bundle.getString("subParent4"));
+        assertEquals("enUSValue3", bundle.getString("subParent3"));
+        assertEquals("subParentValue2", bundle.getString("subParent2"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_ENUSVAR, SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(7, bundle.keySet().size());
+        assertEquals("enUSVARChildValue3", bundle.getString("subChild3"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("enUSVARValue4", bundle.getString("subParent4"));
+        assertEquals("enUSValue3", bundle.getString("subParent3"));
+        assertEquals("subParentValue2", bundle.getString("subParent2"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_ENUSVAR, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("en_US_resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_ENUSVAR, SYSTEM_LOADER, reverseControl);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("en_US_resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("enUSVARChildValue1", bundle.getString("subChild1"));
+        assertEquals("enUSVARChildValue2", bundle.getString("subChild2"));
+        assertEquals("enUSVARChildValue3", bundle.getString("subChild3"));
+        assertEquals("enUSVARValue4", bundle.getString("subParent4"));
+
+        // root locale
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ROOT, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("subChild1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ROOT, SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("subChild1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ROOT, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ROOT, SYSTEM_LOADER, reverseControl);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("resource", bundle.getString("property"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+
+        // 3.use the FallbackLocale
+        Locale.setDefault(LOCALE_FRFR);
+        // no resource for Locale.ITALY
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue1", bundle.getString("subChild1"));
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue1", bundle.getString("subChild1"));
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, reverseControl);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+
+        // with NoFallbackControl
+        Control noFallbackControl = Control
+                .getNoFallbackControl(FORMAT_DEFAULT);
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, noFallbackControl);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        noFallbackControl = Control.getNoFallbackControl(FORMAT_CLASS);
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, noFallbackControl);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        noFallbackControl = Control.getNoFallbackControl(FORMAT_PROPERTIES);
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, noFallbackControl);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("resource", bundle.getString("property"));
+
+        noFallbackControl = new ReverseNoFallbackLocaleControl();
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, noFallbackControl);
+        assertEquals(2, bundle.keySet().size());
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("resource", bundle.getString("property"));
+
+        // locale is equal to the default locale
+        Locale.setDefault(Locale.ITALY);
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                Locale.ITALY, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("subParentValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("subChild1"));
+
+        // 4.test the resources without a root resource
+        // locale that has both class file and properties file support.
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, LOCALE_FRFR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(5, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("subParent1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, LOCALE_FRFR,
+                SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(5, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("subParent1"));
 
-	protected void tearDown() {
-	}
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, LOCALE_FRFR,
+                SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(3, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, LOCALE_FRFR,
+                SYSTEM_LOADER, reverseControl);
+        assertEquals(3, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+
+        // root locale
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ROOT,
+                    SYSTEM_LOADER, DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ROOT,
+                    SYSTEM_LOADER, CLASS_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ROOT,
+                    SYSTEM_LOADER, PROPERTIES_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ROOT,
+                    SYSTEM_LOADER, reverseControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        // fall back locale
+        Locale.setDefault(LOCALE_FRFR);
+        // no resource for Locale.ITALY
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(5, bundle.keySet().size());
+        assertEquals("frFRChildValue1", bundle.getString("subChild1"));
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("frValue2", bundle.getString("subParent2"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertEquals("frFRValue3", bundle.getString("subParent3"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                SYSTEM_LOADER, CLASS_CONTROL);
+        assertEquals(5, bundle.keySet().size());
+        assertEquals("frFRChildValue1", bundle.getString("subChild1"));
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("frValue2", bundle.getString("subParent2"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertEquals("frFRValue3", bundle.getString("subParent3"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(3, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                SYSTEM_LOADER, reverseControl);
+        assertEquals(3, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+
+        // with NoFallbackControl
+        noFallbackControl = Control.getNoFallbackControl(FORMAT_DEFAULT);
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                    SYSTEM_LOADER, noFallbackControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        noFallbackControl = Control.getNoFallbackControl(FORMAT_CLASS);
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                    SYSTEM_LOADER, noFallbackControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        noFallbackControl = Control.getNoFallbackControl(FORMAT_PROPERTIES);
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                    SYSTEM_LOADER, noFallbackControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        noFallbackControl = new ReverseNoFallbackLocaleControl();
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                    SYSTEM_LOADER, noFallbackControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        // locale is equal to the default locale
+        Locale.setDefault(Locale.ITALY);
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_NOROOT_NAME, Locale.ITALY,
+                    SYSTEM_LOADER, noFallbackControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        // 5.simple exceptions
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle("wrongName", LOCALE_FRFR, SYSTEM_LOADER,
+                    DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    URL_LOADER, DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(null, LOCALE_FRFR, SYSTEM_LOADER,
+                    DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, null,
+                    SYSTEM_LOADER, DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    null, DEFAULT_CONTROL);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    SYSTEM_LOADER, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        // 6. exceptions caused by control
+        // illegal control causes IllegalArgumentException
+        Control otherControl = new NullCandidateLocalesControl();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    SYSTEM_LOADER, otherControl);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // illegal control with illegal format
+        otherControl = new GivenFormatsControl(Arrays
+                .asList(new String[] { "java.test" }));
+        illegalFormatControlTester(otherControl);
+
+        // illegal control with other format
+        otherControl = new GivenFormatsControl(Arrays
+                .asList(new String[] { "other.format" }));
+        illegalFormatControlTester(otherControl);
+    }
+
+    @SuppressWarnings("nls")
+    private void illegalFormatControlTester(Control otherControl) {
+        ResourceBundle.clearCache();
+        ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        // cache can ignore the illegal control
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, otherControl);
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    SYSTEM_LOADER, otherControl);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        // cache can also ignore the legal control
+        try {
+            ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FRFR,
+                    SYSTEM_LOADER, DEFAULT_CONTROL);
+            fail("Should throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#clearCache()}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_clearCache() {
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        // the cache used
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache(URL_LOADER);
+        // system loader's cache is still there
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(6, bundle.keySet().size());
+        assertEquals("frFRChildValue2", bundle.getString("subChild2"));
+        assertEquals("subParentValue1", bundle.getString("subParent1"));
+        assertEquals("frFRValue4", bundle.getString("subParent4"));
+        assertFalse(bundle.containsKey("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME,
+                LOCALE_FRFR, SYSTEM_LOADER, PROPERTIES_CONTROL);
+        assertEquals(4, bundle.keySet().size());
+        assertEquals("valueInFRFR", bundle.getString("propertyInFRFR"));
+        assertEquals("valueInURLParent", bundle
+                .getString("propertyInURLParent"));
+        assertEquals("fr_FR_resource", bundle.getString("property"));
+        assertEquals("valueInFR", bundle.getString("propertyInFR"));
+        assertFalse(bundle.containsKey("subParent1"));
+    }
+
+    /**
+     * @throws IOException
+     * @tests {@link java.util.ResourceBundle#clearCache(ClassLoader)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_clearCacheLjava_lang_ClassLoader() throws IOException {
+        // copy the file to test
+        URL srcFile = URL_LOADER.getResource(DEFAULT_CONTROL.toResourceName(
+                DEFAULT_CONTROL.toBundleName(PROPERTIES_NAME, LOCALE_FRFR),
+                "properties"));
+        File copyFile = ControlTest.copyFile(srcFile);
+        if (null != URL_LOADER
+                .getResourceAsStream("hyts_resource_copy_fr_FR.properties")) {
+            // load first time
+            bundle = ResourceBundle.getBundle(PROPERTIES_NAME_COPY,
+                    LOCALE_FRFR, URL_LOADER, DEFAULT_CONTROL);
+            assertEquals("fr_FR_resource", bundle.getString("property"));
+            ControlTest.changeProperties(copyFile);
+            bundle = ResourceBundle.getBundle(PROPERTIES_NAME_COPY,
+                    LOCALE_FRFR, URL_LOADER, DEFAULT_CONTROL);
+            // value from cache, unchanged
+            assertEquals("fr_FR_resource", bundle.getString("property"));
+            ResourceBundle.clearCache();
+            bundle = ResourceBundle.getBundle(PROPERTIES_NAME_COPY,
+                    LOCALE_FRFR, URL_LOADER, DEFAULT_CONTROL);
+            // value from cache, unchanged
+            assertEquals("fr_FR_resource", bundle.getString("property"));
+            ResourceBundle.clearCache(URL_LOADER);
+            bundle = ResourceBundle.getBundle(PROPERTIES_NAME_COPY,
+                    LOCALE_FRFR, URL_LOADER, DEFAULT_CONTROL);
+            // value changed
+            assertEquals("changedValue", bundle.getString("property"));
+        } else {
+            System.err
+                    .println("Can not find the test file, some code of this test 'test_clearCacheLjava_lang_ClassLoader' did not run.");
+        }
+
+        try {
+            ResourceBundle.clearCache(null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#containsKey(String)}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_containsKeyLjava_lang_String() {
+        ResourceBundle.clearCache(URL_LOADER);
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FRFR,
+                URL_LOADER, DEFAULT_CONTROL);
+        assertTrue(bundle.containsKey("property"));
+        assertTrue(bundle.containsKey("propertyInFRFR"));
+        assertTrue(bundle.containsKey("propertyInURLParent"));
+        assertFalse(bundle.containsKey("propertyInSystemParent"));
+        assertTrue(bundle.containsKey("propertyInFR"));
+
+        ResourceBundle.clearCache(URL_LOADER);
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FR,
+                URL_LOADER, DEFAULT_CONTROL);
+        assertTrue(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("propertyInFRFR"));
+        assertTrue(bundle.containsKey("propertyInFR"));
+        assertTrue(bundle.containsKey("propertyInURLParent"));
+        assertFalse(bundle.containsKey("propertyInSystemParent"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertTrue(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("propertyInURLParent"));
+        assertTrue(bundle.containsKey("propertyInSystemParent"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(CLASS_NAME, LOCALE_FR, SYSTEM_LOADER,
+                DEFAULT_CONTROL);
+        assertTrue(bundle.containsKey("parent2"));
+        assertTrue(bundle.containsKey("parent1"));
+        assertTrue(bundle.containsKey("child1"));
+        assertFalse(bundle.containsKey("child2"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        assertTrue(bundle.containsKey("subParent1"));
+        assertTrue(bundle.containsKey("subParent2"));
+        assertTrue(bundle.containsKey("subParent3"));
+        assertTrue(bundle.containsKey("subParent4"));
+        assertTrue(bundle.containsKey("subChild1"));
+        assertFalse(bundle.containsKey("subChild2"));
+        assertFalse(bundle.containsKey("subChild3"));
+
+        assertNotNull(bundle);
+        try {
+            bundle.containsKey(null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#keySet()}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_keySet() {
+        ResourceBundle.clearCache(URL_LOADER);
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FRFR,
+                URL_LOADER, DEFAULT_CONTROL);
+        Set<String> keys = bundle.keySet();
+        assertEquals(4, keys.size());
+        assertNotSame(keys, bundle.keySet());
+        keys.add("wrongKey");
+        keys = bundle.keySet();
+        assertEquals(4, keys.size());
+        assertTrue(keys.getClass() == HashSet.class);
+        assertTrue(keys.contains("propertyInFRFR"));
+        assertTrue(keys.contains("propertyInURLParent"));
+        assertTrue(keys.contains("propertyInFR"));
+        assertTrue(keys.contains("property"));
+
+        ResourceBundle.clearCache(URL_LOADER);
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FR,
+                URL_LOADER, DEFAULT_CONTROL);
+        keys = bundle.keySet();
+        assertEquals(3, keys.size());
+        assertTrue(keys.contains("propertyInURLParent"));
+        assertTrue(keys.contains("propertyInFR"));
+        assertTrue(keys.contains("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(PROPERTIES_NAME, LOCALE_FR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        keys = bundle.keySet();
+        assertEquals(2, keys.size());
+        assertTrue(keys.contains("propertyInSystemParent"));
+        assertTrue(keys.contains("property"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(CLASS_NAME, LOCALE_FR, SYSTEM_LOADER,
+                DEFAULT_CONTROL);
+        keys = bundle.keySet();
+        assertEquals(5, keys.size());
+        assertTrue(keys.contains("parent1"));
+        assertTrue(keys.contains("parent2"));
+        assertTrue(keys.contains("parent3"));
+        assertTrue(keys.contains("parent4"));
+        assertTrue(keys.contains("child1"));
+
+        ResourceBundle.clearCache();
+        bundle = ResourceBundle.getBundle(SUBFOLDER_PROPERTIES_NAME, LOCALE_FR,
+                SYSTEM_LOADER, DEFAULT_CONTROL);
+        keys = bundle.keySet();
+        assertEquals(5, keys.size());
+        assertTrue(keys.contains("subParent1"));
+        assertTrue(keys.contains("subParent2"));
+        assertTrue(keys.contains("subParent3"));
+        assertTrue(keys.contains("subParent4"));
+        assertTrue(keys.contains("subChild1"));
+    }
+
+    /**
+     * @tests {@link java.util.ResourceBundle#handleKeySet()}
+     * @since 1.6
+     */
+    @SuppressWarnings("nls")
+    public void test_handleKeySet() {
+        class SubBundle extends ResourceBundle {
+            public SubBundle() {
+                super();
+            }
+
+            @Override
+            public Set<String> handleKeySet() {
+                return super.handleKeySet();
+            }
+
+            @Override
+            public Enumeration<String> getKeys() {
+                Vector<String> keys = new Vector<String>();
+                keys.add("key1InThis");
+                keys.add("key2InThis");
+                keys.add("key1InParent");
+                keys.add("key2InParent");
+                return keys.elements();
+            }
+
+            @Override
+            protected Object handleGetObject(String key) {
+                if (key.equals("key1InParent") || key.equals("key2InParent")) {
+                    return null;
+                }
+                return new Object();
+            }
+        }
+        SubBundle subBundle = new SubBundle();
+        Set<String> keys = subBundle.handleKeySet();
+        assertEquals(2, keys.size());
+        assertTrue(keys.contains("key1InThis"));
+        assertTrue(keys.contains("key2InThis"));
+    }
+
+    /**
+     * @see junit.framework.TestCase#setUp()
+     */
+    @SuppressWarnings("nls")
+    @Override
+    protected void setUp() {
+        defLocale = Locale.getDefault();
+        Locale.setDefault(new Locale("en", "US"));
+    }
+
+    /**
+     * @see junit.framework.TestCase#tearDown()
+     */
+    @Override
+    protected void tearDown() {
+        Locale.setDefault(defLocale);
+    }
 }



Mime
View raw message