Java tutorial
/* $Id: Messages.java 1001023 2011-12-12 18:41:28Z hozawa $ */ /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * 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. */ package org.apache.manifoldcf.core.i18n; import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import java.util.HashSet; import java.util.Vector; import java.io.InputStream; import org.apache.manifoldcf.core.system.Logging; import org.apache.manifoldcf.core.interfaces.ManifoldCFException; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; public class Messages { // Keep track of messages and bundles we've already complained about. protected static Set<BundleKey> bundleSet = new HashSet<BundleKey>(); protected static Set<MessageKey> messageSet = new HashSet<MessageKey>(); protected static Set<ResourceKey> resourceSet = new HashSet<ResourceKey>(); /** Constructor - do no instantiate */ protected Messages() { } /** Create and initialize a velocity engine instance, given a class. */ public static VelocityEngine createVelocityEngine(Class classInstance) throws ManifoldCFException { VelocityEngine engine = new VelocityEngine(); // Now configure it org.apache.commons.collections.ExtendedProperties configuration = new org.apache.commons.collections.ExtendedProperties(); // This is the property that describes the id's of the resource loaders. configuration.setProperty(VelocityEngine.RESOURCE_LOADER, "mcf"); // This is the property which describes the resource loader itself configuration.setProperty("mcf." + VelocityEngine.RESOURCE_LOADER + ".instance", new MCFVelocityResourceLoader(classInstance)); engine.setExtendedProperties(configuration); engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute"); engine.setProperty("runtime.log.logsystem.log4j.logger", "velocity"); return engine; } /** Read a resource as an input stream, given a class, path, locale, and resource key. */ public static InputStream getResourceAsStream(Class classInstance, String pathName, Locale originalLocale, String resourceKey) throws ManifoldCFException { Locale locale = originalLocale; InputStream is = classInstance.getResourceAsStream(localizeResourceName(pathName, resourceKey, locale)); if (is == null) { complainMissingResource( "No resource in path '" + pathName + "' named '" + resourceKey + "' found for locale '" + locale.toString() + "'", new Exception("Resource not found"), pathName, locale, resourceKey); locale = new Locale(locale.getLanguage()); is = classInstance.getResourceAsStream(localizeResourceName(pathName, resourceKey, locale)); if (is == null) { complainMissingResource( "No resource in path '" + pathName + "' named '" + resourceKey + "' found for locale '" + locale.toString() + "'", new Exception("Resource not found"), pathName, locale, resourceKey); locale = Locale.US; is = classInstance.getResourceAsStream(localizeResourceName(pathName, resourceKey, locale)); if (is == null) { complainMissingResource( "No resource in path '" + pathName + "' named '" + resourceKey + "' found for locale '" + locale.toString() + "'", new Exception("Resource not found"), pathName, locale, resourceKey); locale = new Locale(locale.getLanguage()); is = classInstance.getResourceAsStream(localizeResourceName(pathName, resourceKey, locale)); if (is == null) { complainMissingResource( "No resource in path '" + pathName + "' named '" + resourceKey + "' found for locale '" + locale.toString() + "'", new Exception("Resource not found"), pathName, locale, resourceKey); is = classInstance.getResourceAsStream(localizeResourceName(pathName, resourceKey, null)); if (is == null) throw new ManifoldCFException( "No matching language resource in path '" + pathName + "' named '" + resourceKey + "' found for locale '" + originalLocale.toString() + "'"); } } } } return is; } private static String localizeResourceName(String pathName, String resourceName, Locale locale) { // Path names temporarily disabled, since they don't work. // MHL if (locale == null) return /*pathName + "." + */resourceName; int dotIndex = resourceName.lastIndexOf("."); if (dotIndex == -1) return /*pathName + "." + */resourceName + "_" + locale.toString(); return /*pathName + "." + */resourceName.substring(0, dotIndex) + "_" + locale.toString() + resourceName.substring(dotIndex); } /** Obtain a resource bundle given a class, bundle name, and locale. *@return null if the resource bundle could not be found. */ public static ResourceBundle getResourceBundle(Class clazz, String bundleName, Locale locale) { ResourceBundle resources; ClassLoader classLoader = clazz.getClassLoader(); try { resources = ResourceBundle.getBundle(bundleName, locale, classLoader); } catch (MissingResourceException e) { complainMissingBundle("Missing resource bundle '" + bundleName + "' for locale '" + locale.toString() + "': " + e.getMessage() + "; trying " + locale.getLanguage(), e, bundleName, locale); // Try plain language next locale = new Locale(locale.getLanguage()); try { resources = ResourceBundle.getBundle(bundleName, locale, classLoader); } catch (MissingResourceException e2) { // Use English if we don't have a bundle for the current locale complainMissingBundle("Missing resource bundle '" + bundleName + "' for locale '" + locale.toString() + "': " + e2.getMessage() + "; trying en_US", e2, bundleName, locale); locale = Locale.US; try { resources = ResourceBundle.getBundle(bundleName, locale, classLoader); } catch (MissingResourceException e3) { complainMissingBundle("No backup en_US bundle found! " + e3.getMessage(), e3, bundleName, locale); locale = new Locale(locale.getLanguage()); try { resources = ResourceBundle.getBundle(bundleName, locale, classLoader); } catch (MissingResourceException e4) { complainMissingBundle("No backup en bundle found! " + e4.getMessage(), e4, bundleName, locale); return null; } } } } return resources; } /** Obtain a message given a resource bundle and message key. *@return null if the message could not be found. */ public static String getMessage(Class clazz, String bundleName, Locale locale, String messageKey) { ResourceBundle resources = getResourceBundle(clazz, bundleName, locale); if (resources == null) return null; return getMessage(resources, bundleName, locale, messageKey); } /** Obtain a message given a resource bundle and message key. *@return null if the message could not be found. */ public static String getMessage(ResourceBundle resources, String bundleName, Locale locale, String messageKey) { String message; try { return resources.getString(messageKey); } catch (MissingResourceException e) { complainMissingMessage("Missing resource '" + messageKey + "' in bundle '" + bundleName + "' for locale '" + locale.toString() + "'", e, bundleName, locale, messageKey); return null; } } /** Obtain a string given a resource bundle and message key. */ public static String getString(ResourceBundle resourceBundle, String bundleName, Locale locale, String messageKey) { return getString(resourceBundle, bundleName, locale, messageKey, null); } /** Obtain a string given a class, bundle, locale, message key, and arguments. */ public static String getString(Class clazz, String bundleName, Locale locale, String messageKey, Object[] args) { String message = getMessage(clazz, bundleName, locale, messageKey); if (message == null) return messageKey; // Format the message String formatMessage; if (args != null) { MessageFormat fm = new MessageFormat(message); fm.setLocale(locale); formatMessage = fm.format(args); } else { formatMessage = message; } return formatMessage; } /** Obtain a string given a resource bundle, message key, and arguments. */ public static String getString(ResourceBundle resourceBundle, String bundleName, Locale locale, String messageKey, Object[] args) { String message = getMessage(resourceBundle, bundleName, locale, messageKey); if (message == null) return messageKey; // Format the message String formatMessage; if (args != null) { MessageFormat fm = new MessageFormat(message); fm.setLocale(locale); formatMessage = fm.format(args); } else { formatMessage = message; } return formatMessage; } protected static void complainMissingBundle(String errorMessage, Throwable exception, String bundleName, Locale locale) { String localeName = locale.toString(); BundleKey bk = new BundleKey(bundleName, localeName); synchronized (bundleSet) { if (bundleSet.contains(bk)) return; bundleSet.add(bk); } logError(errorMessage, exception); } protected static void complainMissingMessage(String errorMessage, Throwable exception, String bundleName, Locale locale, String messageKey) { String localeName = locale.toString(); MessageKey bk = new MessageKey(bundleName, localeName, messageKey); synchronized (messageSet) { if (messageSet.contains(bk)) return; messageSet.add(bk); } logError(errorMessage, exception); } protected static void complainMissingResource(String errorMessage, Throwable exception, String pathName, Locale locale, String resourceKey) { String localeName = locale.toString(); ResourceKey bk = new ResourceKey(pathName, localeName, resourceKey); synchronized (resourceSet) { if (resourceSet.contains(bk)) return; resourceSet.add(bk); } logError(errorMessage, exception); } protected static void logError(String errorMessage, Throwable exception) { if (Logging.misc == null) { System.err.println(errorMessage); exception.printStackTrace(System.err); } else Logging.misc.error(errorMessage, exception); } /** Class to help keep track of the missing resource bundles we've already complained about, * so we don't fill up the standard out log with repetitive stuff. */ protected static class BundleKey { protected String bundleName; protected String localeName; public BundleKey(String bundleName, String localeName) { this.bundleName = bundleName; this.localeName = localeName; } public int hashCode() { return bundleName.hashCode() + localeName.hashCode(); } public boolean equals(Object o) { if (!(o instanceof BundleKey)) return false; BundleKey b = (BundleKey) o; return b.bundleName.equals(bundleName) && b.localeName.equals(localeName); } } /** Class to help keep track of the missing messages we've already complained about, * so we don't fill up the standard out log with repetitive stuff. */ protected static class MessageKey { protected String bundleName; protected String localeName; protected String messageKey; public MessageKey(String bundleName, String localeName, String messageKey) { this.bundleName = bundleName; this.localeName = localeName; this.messageKey = messageKey; } public int hashCode() { return bundleName.hashCode() + localeName.hashCode() + messageKey.hashCode(); } public boolean equals(Object o) { if (!(o instanceof MessageKey)) return false; MessageKey b = (MessageKey) o; return b.bundleName.equals(bundleName) && b.localeName.equals(localeName) && b.messageKey.equals(messageKey); } } /** Class to help keep track of the missing resources we've already complained about, * so we don't fill up the standard out log with repetitive stuff. */ protected static class ResourceKey { protected String pathName; protected String localeName; protected String resourceKey; public ResourceKey(String pathName, String localeName, String resourceKey) { this.pathName = pathName; this.localeName = localeName; this.resourceKey = resourceKey; } public int hashCode() { return pathName.hashCode() + localeName.hashCode() + resourceKey.hashCode(); } public boolean equals(Object o) { if (!(o instanceof ResourceKey)) return false; ResourceKey b = (ResourceKey) o; return b.pathName.equals(pathName) && b.localeName.equals(localeName) && b.resourceKey.equals(resourceKey); } } }