/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.platform.exception; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.MessageFormat; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.Properties; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; import org.geoserver.platform.GeoServerExtensions; public class GeoServerExceptions { private static final Logger LOGGER = Logger.getLogger("org.geoserver.platform.exception"); static Control control = new Control(); /** * Returns a localized message for the specific exception for the default system locale. * * @see #localize(IGeoServerException, Locale) */ public static String localize(IGeoServerException e) { return localize(e, Locale.getDefault()); } /** * Returns a localized message for the specific exception, given the specified * locale. * <p> * This method processes the {@link ResourceBundle} extension point to find the * appropriate {@link ResourceBundle} containing the localized message. The base name used * to look up the message is the name of the exception class. First the fully qualified * exception name is used, and if no bundle found, the non qualified name is used. * </p> * @param e The exception whose message to localize. * @param locale The locale to use. * * @return The localized message, or <code>null</code> if none could be found. */ public static String localize(IGeoServerException e, Locale locale) { Class<? extends IGeoServerException> clazz = e.getClass(); while(clazz != null) { String localized = doLocalize(e.getId(), e.getArgs(), clazz, locale); if (localized != null) { return localized; } //could not find string, if the exception parent class is also a geoserver exception // move up the hierarchy and try that if (IGeoServerException.class.isAssignableFrom(clazz.getSuperclass()) ) { clazz = (Class<? extends IGeoServerException>) clazz.getSuperclass(); } else { clazz = null; } } return null; } static String doLocalize(String id, Object[] args, Class<? extends IGeoServerException> clazz, Locale locale) { ResourceBundle bundle = null; try { bundle = ResourceBundle.getBundle("GeoServerException", locale, control); //bundle = ResourceBundle.getBundle(clazz.getCanonicalName(), locale, control); } catch(MissingResourceException ex) {} if (bundle == null) { //could not locate a bundle return null; } //get the message String localized = null; try { //first try with the qualified class name localized = bundle.getString(clazz.getCanonicalName() + "." + id); } catch(MissingResourceException ex) { //next try with the non qualifiied try { localized = bundle.getString(clazz.getSimpleName() + "." + id); } catch(MissingResourceException ex2) {} } if (localized == null) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("Resource lookup failed for key" + id + ", class = " + clazz); } return null; } //if there are arguments, format the message accordingly if (args != null && args.length > 0) { localized = MessageFormat.format(localized, args); } return localized; } static class Control extends ResourceBundle.Control { static final List<String> FORMATS = Arrays.asList("java.properties"); @Override public List<String> getFormats(String baseName) { if (baseName == null) { throw new NullPointerException(); } return FORMATS; } @Override public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { //look for properties file String lang = locale.getLanguage(); String filename = baseName; if (lang != null && !"".equals(lang)) { filename += "_" + lang; } filename += ".properties"; Enumeration<URL> e = loader.getResources(filename); Properties props = null; while (e.hasMoreElements()) { if (props == null) { props = new Properties(); } URL url = e.nextElement(); InputStream in = url.openStream(); try { props.load(in); } catch(Exception ex) { LOGGER.log(Level.WARNING, "Error loading properties from: ", url); } finally { if (in != null) { try { in.close(); } catch(Exception ex2) { LOGGER.log(Level.FINEST, ex2.getMessage(), ex2); } } } } return props != null ? new PropResourceBundle(props) : null; } } static class PropResourceBundle extends ResourceBundle { Properties props; PropResourceBundle(Properties props) { this.props = props; } @Override protected Object handleGetObject(String key) { return props.get(key); } @Override public Enumeration<String> getKeys() { return (Enumeration) props.keys(); } } }