All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xnap.commons.i18n.I18nFactory Maven / Gradle / Ivy

Go to download

A library that supports gettext-based internationalization (i18n) of Java applications.

The newest version!
/*
 *  Gettext Commons
 *
 *  Copyright (C) 2005  Felix Berger
 *  Copyright (C) 2005  Steffen Pingel
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.xnap.commons.i18n;

import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;

/**
 * Factory class that creates and caches I18n instances.
 * 

* Given a {@link Class} object the factory looks up the resource bundle * responsible for handling message translations. The bundle is returned with an * {@link I18n} object wrapped around it, which provides the translation * methods. The lookup is described at {@link #getI18n(Class,String)}. *

* Use the factory for creating I18n objects to make sure no * extraneous objects are created. * * @author Felix Berger * @author Tammo van Lessen * @author Steffen Pingel * @since 0.9 */ public class I18nFactory { private static final String BASENAME_KEY = "basename"; /** * Use the default configuration. * * @since 0.9.1 */ public static final int DEFAULT = 0; /** * Fall back to a default resource bundle that returns the passed text if no * resource bundle can be located. * * @since 0.9.1 */ public static final int FALLBACK = 1 << 0; /** * Look for files named {@link #PROPS_FILENAME} to determine the basename. * * @since 0.9.1 */ public static final int READ_PROPERTIES = 2 << 0; /** * Do not cache {@link I18n} instance. * * @since 0.9.1 */ public static final int NO_CACHE = 4 << 0; /** * Default name for Message bundles, is "i18n.Messages". * * @since 0.9.1 */ public static final String DEFAULT_BASE_NAME = "i18n.Messages"; /** * Filename of the properties file that contains the i18n properties, is * "i18n.properties". * * @since 0.9 */ public static final String PROPS_FILENAME = "i18n.properties"; private static final I18nCache i18nCache = new I18nCache(); private I18nFactory() { } /** * Clears the cache of i18n objects. Used by the test classes. */ static void clearCache() { i18nCache.visit(new I18nCache.Visitor() { public void visit(I18n i18n) { I18nManager.getInstance().remove(i18n); } }); i18nCache.clear(); } /** * Calls {@link #getI18n(Class, Locale) getI18n(clazz, Locale.getDefault())}. */ public static I18n getI18n(final Class clazz) { return getI18n(clazz, Locale.getDefault()); } /** * Calls {@link #getI18n(Class, Locale, int) getI18n(clazz, locale, * READ_PROPERTIES)}. * * @since 0.9.1 */ public static I18n getI18n(final Class clazz, final Locale locale) { return getI18n(clazz, locale, READ_PROPERTIES); } /** * Returns the I18n instance responsible for translating messages in the * package specified by clazz. *

* Lookup works by iterating upwards in the package hierarchy: First the * internal cache is asked for an I18n object for a package, otherwise the * algorithm looks for an i18n.properties file in the * package. The properties file is queried for a key named * basename whose value should be the fully qualified * resource/class name of the resource bundle, e.g * org.xnap.commons.i18n.Messages. *

* If after the first iteration no I18n instance has been found, a second * search begins by looking for resource bundles having the name * baseName. * * @param clazz * the package hierarchy of the clazz and its class loader are * used for resolving and loading the resource bundle * @param locale * the locale of the underlying resource bundle * @param flags * a combination of these configuration flags: {@link #FALLBACK} * @return created or cached I18n instance * @throws MissingResourceException * if no resource bundle was found * @since 0.9.1 */ public static I18n getI18n(final Class clazz, final Locale locale, final int flags) { ClassLoader classLoader = getClassLoader(clazz.getClassLoader()); String bundleName = null; if (isReadPropertiesSet(flags)) { String path = clazz.getName(); int index; do { index = path.lastIndexOf('.'); path = (index != -1) ? path.substring(0, index) : ""; bundleName = readFromPropertiesFile(path, locale, classLoader); } while (bundleName == null && index != -1); } if (bundleName == null) { bundleName = DEFAULT_BASE_NAME; } return getI18n("", bundleName, classLoader, locale, flags); } /** * Calls * {@link #getI18n(Class, String, Locale) getI18n(clazz, bundleName, Locale.getDefault())}. * * @since 0.9 */ public static I18n getI18n(final Class clazz, final String bundleName) { return getI18n(clazz, bundleName, Locale.getDefault()); } /** * Calls * {@link #getI18n(Class, String, Locale, int) getI18n(clazz, bundleName, locale, DEFAULT)}. * * @since 0.9.1 */ public static I18n getI18n(final Class clazz, final String bundleName, final Locale locale) { return getI18n(clazz, bundleName, locale, DEFAULT); } /** * Calls * {@link #getI18n(Class, String, Locale) getI18n(getPackageName(clazz), bundleName, clazz.getClassLoader(), locale, DEFAULT)}. * * @since 0.9.1 */ public static I18n getI18n(final Class clazz, final String bundleName, final Locale locale, int flags) { return getI18n(clazz.getName(), bundleName, clazz.getClassLoader(), locale, flags); } /** * @since 0.9.1 */ public static I18n getI18n(final String path, final String bundleName, final ClassLoader classLoader, final Locale locale, final int flags) { int index; String prefix = path; do { // chop of last segment of path index = prefix.lastIndexOf('.'); prefix = (index != -1) ? prefix.substring(0, index) : ""; String name = prefix.length() == 0 ? bundleName : prefix + "." + bundleName; // check cache I18n i18n = i18nCache.get(name, locale); if (i18n != null) { return i18n; } // look for resource bundle in class path i18n = findByBaseName(name, locale, getClassLoader(classLoader), flags); if (i18n != null) { if ((flags & NO_CACHE) == 0) { i18nCache.put(name, i18n); } return i18n; } } while (index != -1); // fallback to default bundle if (isFallbackSet(flags)) { I18n i18n = i18nCache.get("", locale); if (i18n == null) { i18n = new I18n(new EmptyResourceBundle(locale)); i18nCache.put("", i18n); } return i18n; } throw new MissingResourceException("Resource bundle not found", path, bundleName); } static ClassLoader getClassLoader(ClassLoader classLoader) { return (classLoader != null) ? classLoader : ClassLoader.getSystemClassLoader(); } /** * Tries to create an I18n instance from a properties file. * * @param path * @param loader * @return null if no properties file was found * @throws MissingResourceException * if properties file was found but specified resource not */ static String readFromPropertiesFile(final String path, final Locale locale, final ClassLoader loader) { Properties props = new Properties(); String filename = path.length() == 0 ? PROPS_FILENAME : path.replace('.', '/') + "/" + PROPS_FILENAME; InputStream in = loader.getResourceAsStream(filename); if (in != null) { try { props.load(in); } catch (IOException e) { // XXX now what? } finally { try { in.close(); } catch (IOException e) { // this exception is lost } } return props.getProperty(BASENAME_KEY); } return null; } /** * Uses the class loader to look for a messages properties file. * * @param baseName * the base name of the resource bundle * @param path * the path that prefixes baseName * @param loader * the class loader used to look up the bundle * @param flags * @return the created instance */ static I18n findByBaseName(final String baseName, final Locale locale, final ClassLoader loader, int flags) { try { return createI18n(baseName, locale, loader, flags); } catch (MissingResourceException e) { return null; } } /** * Creates a new i18n instance and registers it with {@link I18nManager}. * * @param baseName * the base name of the resource bundle * @param locale * the locale * @param loader * the class loader used to look up the bundle * @return the created instance */ private static I18n createI18n(final String baseName, final Locale locale, final ClassLoader loader, final int flags) { I18n i18n = new I18n(baseName, locale, loader); if (!isNoCacheSet(flags)) { I18nManager.getInstance().add(i18n); } return i18n; } private static boolean isFallbackSet(final int flags) { return (flags & FALLBACK) != 0; } private static boolean isReadPropertiesSet(final int flags) { return (flags & READ_PROPERTIES) != 0; } private static boolean isNoCacheSet(final int flags) { return (flags & NO_CACHE) != 0; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy