package org.jboss.seam.core; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.concurrent.ConcurrentHashMap; import org.jboss.seam.Seam; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.contexts.Lifecycle; import org.jboss.seam.navigation.Pages; import org.jboss.seam.util.EnumerationEnumeration; /** * The Seam resource bundle which searches for resources in delegate resource * bundles specified in pages.xml, and a configurable list of delegate resource * bundles specified in components.xml. * * @see ResourceLoader * @author Gavin King * */ public class SeamResourceBundle extends java.util.ResourceBundle { private Map<Init,Map<Locale, List<ResourceBundle>>> bundleCache = new ConcurrentHashMap<Init,Map<Locale, List<ResourceBundle>>>(); private Map<Locale, List<ResourceBundle>> getCachedBundle() { Init init; if(Contexts.isApplicationContextActive()) { init = (Init)Contexts.getApplicationContext().get(Seam.getComponentName(Init.class)); } else { //not sure if this is nessesary init = (Init)Lifecycle.getApplication().get(Seam.getComponentName(Init.class)); } if(!bundleCache.containsKey(init)) { bundleCache.put(init, new ConcurrentHashMap<Locale, List<ResourceBundle>>()); } return bundleCache.get(init); } /** * Get an instance for the current Seam Locale * * @see Locale * * @return a SeamResourceBundle */ public static java.util.ResourceBundle getBundle() { return java.util.ResourceBundle.getBundle(SeamResourceBundle.class.getName(), org.jboss.seam.core.Locale.instance()); //note: it does not really matter what we pass here } public static java.util.ResourceBundle getBundleNamed(String bundleName) { return java.util.ResourceBundle.getBundle(bundleName, org.jboss.seam.core.Locale.instance()); } private List<java.util.ResourceBundle> getBundlesForCurrentLocale() { Locale instance = org.jboss.seam.core.Locale.instance(); List<ResourceBundle> bundles = getCachedBundle().get(instance); if ( bundles==null ) { bundles = loadBundlesForCurrentLocale(); getCachedBundle().put(instance, bundles); } return bundles; } private List<ResourceBundle> loadBundlesForCurrentLocale() { List<ResourceBundle> bundles = new ArrayList<ResourceBundle>(); ResourceLoader resourceLoader = ResourceLoader.instance(); for (String bundleName : resourceLoader.getBundleNames()) { ResourceBundle bundle = resourceLoader.loadBundle(bundleName); if (bundle != null) bundles.add(bundle); } ResourceBundle bundle = resourceLoader.loadBundle("ValidatorMessages"); if (bundle != null) { bundles.add(bundle); } bundle = resourceLoader.loadBundle("org/hibernate/validator/ValidationMessages"); if (bundle != null) bundles.add(bundle); bundle = resourceLoader.loadBundle("javax.faces.Messages"); if (bundle != null) bundles.add(bundle); return Collections.unmodifiableList(bundles); } @Override public Enumeration<String> getKeys() { List<java.util.ResourceBundle> pageBundles = getPageResourceBundles(); List<ResourceBundle> bundles = getBundlesForCurrentLocale(); Enumeration<String>[] enumerations = new Enumeration[bundles.size() + pageBundles.size()]; int i = 0; for (java.util.ResourceBundle bundle: pageBundles) { enumerations[i++] = bundle.getKeys(); } for (ResourceBundle bundle: bundles) { enumerations[i++] = bundle.getKeys(); } return new EnumerationEnumeration<String>(enumerations); } @Override protected Object handleGetObject(String key) { if (!Contexts.isApplicationContextActive()) { return null; } List<java.util.ResourceBundle> pageBundles = getPageResourceBundles(); for (java.util.ResourceBundle pageBundle : pageBundles) { try { return interpolate(pageBundle.getObject(key)); } catch (MissingResourceException mre) {} } for (java.util.ResourceBundle littleBundle : getBundlesForCurrentLocale()) { try { return interpolate( littleBundle.getObject(key) ); } catch (MissingResourceException mre) {} } return null; // superclass is responsible for throwing MRE } private Object interpolate(Object message) { return message!=null && message instanceof String ? Interpolator.instance().interpolate( (String) message ) : message; } private List<java.util.ResourceBundle> getPageResourceBundles() { // TODO: oops! A hard dependency to JSF! String viewId = Pages.getCurrentViewId(); if (viewId != null) { // we can't cache these bundles, since the viewId // may change in the middle of a request return Pages.instance().getResourceBundles(viewId); } else { return Collections.EMPTY_LIST; } } @Override public Locale getLocale() { return org.jboss.seam.core.Locale.instance(); } }