org.apache.roller.weblogger.util.I18nMessages.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.roller.weblogger.util.I18nMessages.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A utility class for handling i18n messaging.
 */
public class I18nMessages {

    private static final Log log = LogFactory.getLog(I18nMessages.class);

    // locale and bundle we are using for messaging
    private final Locale locale;
    private final ResourceBundle bundle;

    // a map of cached messages instances, keyed by locale
    private static Map<Locale, I18nMessages> messagesMap = Collections.synchronizedMap(new HashMap());

    private I18nMessages(String locale) {
        Locale loc = I18nUtils.toLocale(locale);
        this.locale = loc;
        this.bundle = ResourceBundle.getBundle("ApplicationResources", loc);
    }

    private I18nMessages(Locale locale) {
        this.locale = locale;
        this.bundle = ResourceBundle.getBundle("ApplicationResources", locale);
    }

    /**
     * Get an instance for a given locale.
     */
    public static I18nMessages getMessages(String locale) {

        log.debug("request for messages in locale = " + locale);

        // check if we already have a message utils created for that locale
        I18nMessages messages = messagesMap.get(locale);

        // if no utils for that language yet then construct
        if (messages == null) {
            messages = new I18nMessages(locale);

            // keep a reference to it
            messagesMap.put(messages.getLocale(), messages);
        }

        return messages;
    }

    /**
     * Get an instance for a given locale.
     */
    public static I18nMessages getMessages(Locale locale) {

        log.debug("request for messages in locale = " + locale.toString());

        // check if we already have a message utils created for that locale
        I18nMessages messages = messagesMap.get(locale);

        // if no utils for that language yet then construct
        if (messages == null) {
            messages = new I18nMessages(locale);

            // keep a reference to it
            messagesMap.put(messages.getLocale(), messages);
        }

        return messages;
    }

    /**
     * The locale representing this message utils.
     */
    public final Locale getLocale() {
        return this.locale;
    }

    /**
     * Get a message from the bundle.
     */
    public final String getString(String key) {

        try {
            return bundle.getString(key);
        } catch (Exception e) {
            // send a warning in the logs
            log.warn("Error getting key " + key);
            return key;
        }
    }

    /**
     * Get a message from the bundle and substitute the given args into
     * the message contents.
     */
    public final String getString(String key, List args) {

        try {
            String msg = bundle.getString(key);
            return MessageFormat.format(msg, args.toArray());
        } catch (Exception e) {
            // send a warning in the logs
            log.warn("Error getting key " + key, e);
            return key;
        }
    }

    /**
     * Get a message from the bundle and substitute the given args into
     * the message contents.
     */
    public final String getString(String key, Object[] args) {

        try {
            String msg = bundle.getString(key);
            return MessageFormat.format(msg, args);
        } catch (Exception e) {
            // send a warning in the logs
            log.warn("Error getting key " + key, e);
            return key;
        }
    }

    /**
     * Reload bundle.
     * 
     * @param key
     *            the key
     */
    public static final void reloadBundle(Locale key) {

        try {

            Class type = ResourceBundle.class;
            Field cacheList = type.getDeclaredField("cacheList");

            synchronized (cacheList) {
                cacheList.setAccessible(true);
                ((Map) cacheList.get(ResourceBundle.class)).clear();
            }

            clearTomcatCache();

            // Remove cached bundle
            messagesMap.remove(key);

        } catch (Exception e) {
            log.error("Error clearing message resource bundles", e);
        }

    }

    /**
     * Clear tomcat cache.
     * 
     * @see com.opensymphony.xwork2.util.LocalizedTextUtil
     */
    private static void clearTomcatCache() {

        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        // no need for compilation here.
        Class cl = loader.getClass();

        try {
            if ("org.apache.catalina.loader.WebappClassLoader".equals(cl.getName())) {
                clearMap(cl, loader, "resourceEntries");
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("class loader " + cl.getName() + " is not tomcat loader.");
                }
            }
        } catch (Exception e) {
            log.warn("couldn't clear tomcat cache", e);
        }
    }

    private static void clearMap(Class cl, Object obj, String name)
            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Field field = cl.getDeclaredField(name);
        field.setAccessible(true);

        Object cache = field.get(obj);

        synchronized (cache) {
            Class ccl = cache.getClass();
            Method clearMethod = ccl.getMethod("clear");
            clearMethod.invoke(cache);
        }

    }
}