    001/* ========================================================================
    002 * JCommon : a free general purpose class library for the Java(tm) platform
    003 * ========================================================================
    004 *
    005 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
    006 *
    007 * Project Info:  http://www.jfree.org/jcommon/index.html
    008 *
    009 * This library is free software; you can redistribute it and/or modify it
    010 * under the terms of the GNU Lesser General Public License as published by
    011 * the Free Software Foundation; either version 2.1 of the License, or
    012 * (at your option) any later version.
    013 *
    014 * This library is distributed in the hope that it will be useful, but
    015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017 * License for more details.
    018 *
    019 * You should have received a copy of the GNU Lesser General Public
    020 * License along with this library; if not, write to the Free Software
    021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022 * USA.
    023 *
    024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025 * in the United States and other countries.]
    026 *
    027 * --------------------------
    028 * ResourceBundleWrapper.java
    029 * --------------------------
    030 * (C)opyright 2008, by Jess Thrysoee and Contributors.
    031 *
    032 * Original Author:  Jess Thrysoee;
    033 * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034 *
    035 * Changes
    036 * -------
    037 * 18-Dec-2008 : Version 1 (JT);
    038 *
    039 */
    040
    041package org.jfree.util;
    042
    043import java.net.URL;
    044import java.net.URLClassLoader;
    045import java.util.ArrayList;
    046import java.util.List;
    047import java.util.Locale;
    048import java.util.ResourceBundle;
    049
    050/**
    051 * Wrapper of ResourceBundle.getBundle() methods. This wrapper is introduced to
    052 * avoid a dramatic performance penalty by superfluous resource (and classes
    053 * loaded by Class.forName) lookups on web server in applets.
    054 *
    055 * <pre>
    056 * public class AppletC extends javax.swing.JApplet {
    057 *    public void init() {
    058 *       ResourceBundleWrapper.removeCodeBase(getCodeBase(),
    059 *               (URLClassLoader) getClass().getClassLoader());
    060 *    ...
    061 * </pre>
    062 *
    063 * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4243379">
    064 *               Bug ID: 4243379</a>
    065 * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4668479">
    066 *               Bug ID: 4668479</a>
    067 *
    068 * @since 1.0.15
    069 */
    070public class ResourceBundleWrapper {
    071
    072    /**
    073     * A special class loader with no code base lookup.  This field may be
    074     * <code>null</code> (the field is only initialised if removeCodeBase() is
    075     * called from an applet.
    076     */
    077    private static URLClassLoader noCodeBaseClassLoader;
    078
    079    /**
    080     * Private constructor.
    081     */
    082    private ResourceBundleWrapper() {
    083        // all methods are static, no need to instantiate
    084    }
    085
    086    /**
    087     * Instantiate a {@link URLClassLoader} for resource lookups where the
    088     * codeBase URL is removed.  This method is typically called from an
    089     * applet's init() method.  If this method is never called, the
    090     * <code>getBundle()</code> methods map to the standard
    091     * {@link ResourceBundle} lookup methods.
    092     *
    093     * @param codeBase  the codeBase URL.
    094     * @param urlClassLoader  the class loader.
    095     */
    096    public static void removeCodeBase(URL codeBase,
    097            URLClassLoader urlClassLoader) {
    098        List urlsNoBase = new ArrayList();
    099
    100        URL[] urls = urlClassLoader.getURLs();
    101        for (int i = 0; i < urls.length; i++) {
    102            if (! urls[i].sameFile(codeBase)) {
    103                urlsNoBase.add(urls[i]);
    104            }
    105        }
    106        // substitute the filtered URL list
    107        URL[] urlsNoBaseArray = (URL[]) urlsNoBase.toArray(new URL[0]);
    108        noCodeBaseClassLoader = URLClassLoader.newInstance(urlsNoBaseArray);
    109    }
    110
    111    /**
    112     * Finds and returns the specified resource bundle.
    113     *
    114     * @param baseName  the base name.
    115     *
    116     * @return The resource bundle.
    117     */
    118    public static final ResourceBundle getBundle(String baseName) {
    119        // the noCodeBaseClassLoader is configured by a call to the
    120        // removeCodeBase() method, typically in the init() method of an
    121        // applet...
    122        if (noCodeBaseClassLoader != null) {
    123            return ResourceBundle.getBundle(baseName, Locale.getDefault(),
    124                    noCodeBaseClassLoader);
    125        }
    126        else {
    127            // standard ResourceBundle behaviour
    128            return ResourceBundle.getBundle(baseName);
    129        }
    130    }
    131
    132    /**
    133     * Finds and returns the specified resource bundle.
    134     *
    135     * @param baseName  the base name.
    136     * @param locale  the locale.
    137     *
    138     * @return The resource bundle.
    139     */
    140    public static final ResourceBundle getBundle(String baseName,
    141            Locale locale) {
    142
    143        // the noCodeBaseClassLoader is configured by a call to the
    144        // removeCodeBase() method, typically in the init() method of an
    145        // applet...
    146        if (noCodeBaseClassLoader != null) {
    147            return ResourceBundle.getBundle(baseName, locale,
    148                    noCodeBaseClassLoader);
    149        }
    150        else {
    151            // standard ResourceBundle behaviour
    152            return ResourceBundle.getBundle(baseName, locale);
    153        }
    154    }
    155
    156    /**
    157     * Maps directly to <code>ResourceBundle.getBundle(baseName, locale,
    158     * loader)</code>.
    159     *
    160     * @param baseName  the base name.
    161     * @param locale  the locale.
    162     * @param loader  the class loader.
    163     *
    164     * @return The resource bundle.
    165     */
    166    public static ResourceBundle getBundle(String baseName, Locale locale,
    167            ClassLoader loader) {
    168        return ResourceBundle.getBundle(baseName, locale, loader);
    169    }
    170
    171}