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

org.apache.fulcrum.localization.SimpleLocalizationServiceImpl Maven / Gradle / Ivy

The newest version!
package org.apache.fulcrum.localization;

/*
 * 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.
 */

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.commons.lang3.StringUtils;

/**
 * 

* This class is the single point of access to all localization * resources. It caches different ResourceBundles for different * Locales. *

* *

Usage example:

* *
 * 
 * SimpleLocalizationService ls = (SimpleLocalizationService) TurbineServices
 *     .getInstance().getService(SimpleLocalizationService.SERVICE_NAME);
 * 
 * 
* *

* Then call {@link #getString(String, Locale, String)}, or one of * two methods to retrieve a ResourceBundle: *

* *
    *
  • getBundle("MyBundleName")
  • *
  • getBundle("MyBundleName", Locale)
  • *
  • etc.
  • *
* * @author Jonas Maurus * @author Jon S. Stevens * @author Frank Y. Kim * @author Daniel Rall * @author Leonard Richardson * @author Stephen McConnell * @author Thomas Vandahl * @version $Id: DefaultLocalizationService.java 535465 2007-05-05 06:58:06Z tv $ * * avalon.component name="localization" lifestyle="singleton" * avalon.service type="org.apache.fulcrum.localization.SimpleLocalizationService" */ public class SimpleLocalizationServiceImpl extends AbstractLogEnabled implements SimpleLocalizationService, Configurable, Initializable { /** Key Prefix for our bundles */ private static final String BUNDLES = "bundles"; /** * The value to pass to MessageFormat if a * null reference is passed to format(). */ private static final Object[] NO_ARGS = new Object[0]; /** * Bundle name keys a HashMap of the ResourceBundles in this * service (which is in turn keyed by Locale). */ private HashMap> bundles = null; /** * The list of default bundles to search. */ private String[] bundleNames = null; /** * The name of the default locale to use (includes language and * country). */ private Locale defaultLocale = null; /** The name of the default language to use. */ private String defaultLanguage = null; /** The name of the default country to use. */ private String defaultCountry = null; /** * Creates a new instance. */ public SimpleLocalizationServiceImpl() { bundles = new HashMap>(); } /** * Avalon lifecycle method * * {@link org.apache.avalon.framework.configuration.Configurable} * * @param conf the configuration * @throws ConfigurationException if failed to configure */ @Override public void configure(Configuration conf) throws ConfigurationException { Locale jvmDefault = Locale.getDefault(); defaultLanguage = conf .getAttribute( "locale-default-language", jvmDefault.getLanguage()) .trim(); defaultCountry = conf .getAttribute("locale-default-country", jvmDefault.getCountry()) .trim(); // FIXME! need to add bundle names getLogger().info( "initialized lang=" + defaultLanguage + " country=" + defaultCountry); final Configuration bundles = conf.getChild(BUNDLES, false); if (bundles != null) { Configuration[] nameVal = bundles.getChildren(); String bundleName[] = new String[nameVal.length]; for (int i = 0; i < nameVal.length; i++) { String val = nameVal[i].getValue(); getLogger().debug("Registered bundle " + val); bundleName[i] = val; } initBundleNames(bundleName); } } /** * Called the first time the Service is used. * * @throws Exception generic exception */ @Override public void initialize() throws Exception { defaultLocale = new Locale(defaultLanguage, defaultCountry); if (getLogger().isInfoEnabled()) { getLogger().info("Localization Service is Initialized now.."); } } /** * Initialize list of default bundle names. * * @param intBundleNames set bundle names */ protected void initBundleNames(String[] intBundleNames) { if (intBundleNames == null) bundleNames = new String[0]; else bundleNames = intBundleNames; } /** * Retrieves the default language (specified in the config file). * * @return the default language */ @Override public String getDefaultLanguage() { return defaultLanguage; } /** * Retrieves the default country (specified in the config file). * * @return the default country */ @Override public String getDefaultCountry() { return defaultCountry; } /** * Retrieves the default Locale (as created from default * language and default country). * * @return the default locale */ @Override public Locale getDefaultLocale() { return defaultLocale; } /** * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getDefaultBundleName()} * * @return the default bundle name */ @Override public String getDefaultBundleName() { return (bundleNames.length > 0 ? bundleNames[0] : ""); } /** * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getBundleNames()} * * @return list of bundle names available */ @Override public String[] getBundleNames() { return bundleNames.clone(); } /** * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle() * * @return the default resource bundle */ @Override public ResourceBundle getBundle() { return getBundle(getDefaultBundleName(), (Locale) null); } /** * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle(java.lang.String) * * @param bundleName the name of a bundle * @return the resource bundle */ @Override public ResourceBundle getBundle(String bundleName) { return getBundle(bundleName, (Locale) null); } /** * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle(java.lang.String, java.util.Locale) * * This method returns a ResourceBundle for the given bundle name * and the given Locale. * * @param bundleName Name of bundle (or null for the * default bundle). * @param locale The locale (or null for the locale * indicated by the default language and country). * @return A localized ResourceBundle. */ @Override public ResourceBundle getBundle(String bundleName, Locale locale) { // Assure usable inputs. bundleName = (bundleName == null ? getDefaultBundleName() : bundleName.trim()); if (locale == null) { locale = getDefaultLocale(); } // Find/retrieve/cache bundle. ResourceBundle rb = null; HashMap bundlesByLocale = (HashMap) bundles.get(bundleName); if (bundlesByLocale != null) { // Cache of bundles by locale for the named bundle exists. // Check the cache for a bundle corresponding to locale. rb = (ResourceBundle) bundlesByLocale.get(locale); if (rb == null) { // Not yet cached. rb = cacheBundle(bundleName, locale); } } else { rb = cacheBundle(bundleName, locale); } return rb; } /** * Caches the named bundle for fast lookups. This operation is * relatively expensive in terms of memory use, but is optimized * for run-time speed in the usual case. * * @param bundleName Name of bundle (or null for the * default bundle). * @param locale The locale (or null for the locale * indicated by the default language and country). * @throws MissingResourceException Bundle not found. * @return a localized resource bundle */ private synchronized ResourceBundle cacheBundle( String bundleName, Locale locale) throws MissingResourceException { HashMap bundlesByLocale = (HashMap) bundles.get(bundleName); ResourceBundle rb = (bundlesByLocale == null ? null : (ResourceBundle) bundlesByLocale.get(locale)); if (rb == null) { bundlesByLocale = (bundlesByLocale == null ? new HashMap(3) : new HashMap(bundlesByLocale)); try { rb = ResourceBundle.getBundle(bundleName, locale); } catch (MissingResourceException e) { rb = findBundleByLocale(bundleName, locale, bundlesByLocale); if (rb == null) { throw (MissingResourceException) e.fillInStackTrace(); } } if (rb != null) { // Cache bundle. bundlesByLocale.put(rb.getLocale(), rb); HashMap> bundlesByName = new HashMap>(bundles); bundlesByName.put(bundleName, bundlesByLocale); this.bundles = bundlesByName; } } return rb; } /** *

Retrieves the bundle most closely matching first against the * supplied inputs, then against the defaults.

* *

Use case: some clients send a HTTP Accept-Language header * with a value of only the language to use * (i.e. "Accept-Language: en"), and neglect to include a country. * When there is no bundle for the requested language, this method * can be called to try the default country (checking internally * to assure the requested criteria matches the default to avoid * disconnects between language and country).

* *

Since we're really just guessing at possible bundles to use, * we don't ever throw MissingResourceException.

* * @param bundleName Name of bundle (or null for the * default bundle). * @param locale The locale (or null for the locale * indicated by the default language and country). * @param bundleByLocale map of locales and resource bundles * @return a localized resource bundle * */ private ResourceBundle findBundleByLocale( String bundleName, Locale locale, Map bundlesByLocale) { ResourceBundle rb = null; if (StringUtils.isEmpty(locale.getCountry()) && defaultLanguage.equals(locale.getLanguage())) { /* * category.debug("Requested language '" + locale.getLanguage() + * "' matches default: Attempting to guess bundle " + * "using default country '" + defaultCountry + '\''); */ Locale withDefaultCountry = new Locale(locale.getLanguage(), defaultCountry); rb = (ResourceBundle) bundlesByLocale.get(withDefaultCountry); if (rb == null) { rb = getBundleIgnoreException(bundleName, withDefaultCountry); } } else if ( StringUtils.isEmpty(locale.getLanguage()) && defaultCountry.equals(locale.getCountry())) { Locale withDefaultLanguage = new Locale(defaultLanguage, locale.getCountry()); rb = (ResourceBundle) bundlesByLocale.get(withDefaultLanguage); if (rb == null) { rb = getBundleIgnoreException(bundleName, withDefaultLanguage); } } if (rb == null && !defaultLocale.equals(locale)) { rb = getBundleIgnoreException(bundleName, defaultLocale); } return rb; } /** * Retrieves the bundle using the * ResourceBundle.getBundle(String, Locale) method, * returning null instead of throwing * MissingResourceException. * * @param bundleName Name of bundle (or null for the * default bundle). * @param locale The locale (or null for the locale * indicated by the default language and country). */ private final ResourceBundle getBundleIgnoreException( String bundleName, Locale locale) { try { return ResourceBundle.getBundle(bundleName, locale); } catch (MissingResourceException ignored) { return null; } } /** * This method sets the name of the first bundle in the search * list (the "default" bundle). * * @param defaultBundle Name of default bundle. */ @Override public void setBundle(String defaultBundle) { if (bundleNames.length > 0) { bundleNames[0] = defaultBundle; } else { synchronized (this) { if (bundleNames.length <= 0) { bundleNames = new String[] { defaultBundle }; } } } } /** * * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getString(String, Locale, String)} * @throws MissingResourceException Specified key cannot be matched. */ @Override public String getString(String bundleName, Locale locale, String key) throws MissingResourceException { String value = null; if (locale == null) { locale = getDefaultLocale(); } // Look for text in requested bundle. ResourceBundle rb = getBundle(bundleName, locale); value = getStringOrNull(rb, key); // Look for text in list of default bundles. if (value == null && bundleNames.length > 0) { String name; for (int i = 0; i < bundleNames.length; i++) { name = bundleNames[i]; //System.out.println("getString(): name=" + name + // ", locale=" + locale + ", i=" + i); if (!name.equals(bundleName)) { rb = getBundle(name, locale); value = getStringOrNull(rb, key); if (value != null) { locale = rb.getLocale(); break; } } } } if (value == null) { String loc = locale.toString(); String mesg = LocalizationService.SERVICE_NAME + " noticed missing resource: " + "bundleName=" + bundleName + ", locale=" + loc + ", key=" + key; getLogger().debug(mesg); // Text not found in requested or default bundles. throw new MissingResourceException(mesg, bundleName, key); } return value; } /** * Returns the value for the key in the default bundle and the default locale. * * @param key The key to retrieve the value for. * @return The value mapped to the key. */ @Override public String getString(String key) { return getString(getDefaultBundleName(), getDefaultLocale(), key); } /** * Gets localized text from a bundle if it's there. Otherwise, * returns null (ignoring a possible * MissingResourceException). * * @param rb resource bundle * @param key The key to retrieve the value for. * @return name of resource */ protected final String getStringOrNull(ResourceBundle rb, String key) { if (rb != null) { try { return rb.getString(key); } catch (MissingResourceException ignored) { // ignore } } return null; } /** * {@link org.apache.fulcrum.localization.SimpleLocalizationService#format(String, Locale, String, Object)} * @param bundleName the bundle name * @param locale locale * @param key key to lookup * @param arg1 bundle arguments */ @Override public String format( String bundleName, Locale locale, String key, Object arg1) { return format(bundleName, locale, key, new Object[] { arg1 }); } /* (non-Javadoc) * @see org.apache.fulcrum.localization.SimpleLocalizationService#format(java.lang.String, java.util.Locale, java.lang.String, java.lang.Object, java.lang.Object) */ @Override public String format( String bundleName, Locale locale, String key, Object arg1, Object arg2) { return format(bundleName, locale, key, new Object[] { arg1, arg2 }); } /** * Looks up the value for key in the * ResourceBundle referenced by * bundleName, then formats that value for the * specified Locale using args. * * If locale is null, {@link #getDefaultLocale()} will be checked. * If bundleName is null, {@link #getDefaultBundleName()} will be checked (cft. {@link #getBundle(String, Locale)}. * * @return Localized, formatted text identified by * key. */ @Override public String format( String bundleName, Locale locale, String key, Object[] args) { // When formatting Date objects and such, MessageFormat // cannot have a null Locale. Locale formatLocale = (locale == null) ? getDefaultLocale() : locale; String value = getString(bundleName, locale, key); Object[] formatArgs = (args == null) ? NO_ARGS : args; MessageFormat messageFormat = new MessageFormat(value, formatLocale); return messageFormat.format(formatArgs); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy