Java tutorial
/* * 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); } } }