diff --git a/src/main/java/com/adobe/epubcheck/messages/LocalizedMessages.java b/src/main/java/com/adobe/epubcheck/messages/LocalizedMessages.java index 6e9fe69b4..bdf49fb8d 100644 --- a/src/main/java/com/adobe/epubcheck/messages/LocalizedMessages.java +++ b/src/main/java/com/adobe/epubcheck/messages/LocalizedMessages.java @@ -110,8 +110,12 @@ public Message getMessage(MessageId id) public LocalizedMessages(Locale locale) { this.locale = (locale != null) ? locale : Locale.getDefault(); - bundle = ResourceBundle.getBundle( - "com.adobe.epubcheck.messages.MessageBundle", this.locale, new LocalizedMessages.UTF8Control()); + try { + this.bundle = ResourceResolver.toResourceBundle(ResourceResolver.getInstance() + .resource2Url("com.adobe.epubcheck.messages.MessageBundle", locale)); + } catch (IOException e) { + throw new IllegalStateException(e); + } } private String getStringFromBundle(String id) @@ -170,54 +174,4 @@ public String getSuggestion(MessageId id, String key) : getSuggestion(id)); } - public static class UTF8Control extends ResourceBundle.Control - { - - @Override - public ResourceBundle newBundle( - String baseName, - Locale locale, - String format, - ClassLoader loader, - boolean reload) throws IllegalAccessException, - InstantiationException, - IOException - { - // The below is a copy of the default implementation. - String bundleName = toBundleName(baseName, locale); - String resourceName = toResourceName(bundleName, "properties"); //$NON-NLS-1$ - ResourceBundle bundle = null; - InputStream stream = null; - if (reload) - { - URL url = loader.getResource(resourceName); - if (url != null) - { - URLConnection connection = url.openConnection(); - if (connection != null) - { - connection.setUseCaches(false); - stream = connection.getInputStream(); - } - } - } else - { - stream = loader.getResourceAsStream(resourceName); - } - if (stream != null) - { - try - { - // Only this line is changed to make it to read properties files as - // UTF-8. - bundle = new PropertyResourceBundle( - new BufferedReader(new InputStreamReader(stream, Charsets.UTF_8))); - } finally - { - stream.close(); - } - } - return bundle; - } - } } diff --git a/src/main/java/com/adobe/epubcheck/messages/ResourceResolver.java b/src/main/java/com/adobe/epubcheck/messages/ResourceResolver.java new file mode 100644 index 000000000..83646b2db --- /dev/null +++ b/src/main/java/com/adobe/epubcheck/messages/ResourceResolver.java @@ -0,0 +1,110 @@ +package com.adobe.epubcheck.messages; + +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; + +import java.io.*; +import java.net.URL; +import java.util.*; + +public class ResourceResolver { + + private static class MyPropertyResourceBundle extends PropertyResourceBundle { + + MyPropertyResourceBundle(Reader reader) throws IOException { + super(reader); + } + + MyPropertyResourceBundle(URL url) throws IOException { + this(new BufferedReader( + new InputStreamReader(url.openStream(), Charsets.UTF_8))); + } + + void setMyParent(MyPropertyResourceBundle resourceBundle){ + setParent(resourceBundle); + } + + } + + private static final ResourceResolver INSTANCE = new ResourceResolver(); + + public static ResourceResolver getInstance() { + return INSTANCE; + } + + private ResourceResolver() { + } + + public List resource2Url(String resource, Locale locale) { + String path = resource.replaceAll("\\.", "/"); + List result = flatResource2Url(path, locale); + if (result.isEmpty()) { + result = flatResource2Url("/" + path, locale); + } + if (result.isEmpty()) { + result = flatResource2Url(resource, locale); + } + if (result.isEmpty()) { + throw new IllegalStateException("Can't find resource for " + resource + " and " + locale); + } + return result; + } + + private List flatResource2Url(String resource, Locale locale) { + final List result = new ArrayList<>(); + if (locale != null) { + if (!"".equals(locale.getCountry())) { + addTo(result, from(resource + "_" + locale.toString() + ".properties")); + } + final String lang = locale.getLanguage(); + if (!"".equals(lang)) { + addTo(result, from(resource + "_" + locale.getLanguage() + ".properties")); + } + } + // fallback to default locale (only if locale not found) + Locale dft = Locale.getDefault(); + if (result.isEmpty()) { + if (!"".equals(locale.getCountry())) { + addTo(result, from(resource + "_" + dft.toString() + ".properties")); + } + final String lang2 = dft.getLanguage(); + if (!"".equals(lang2)) { + addTo(result, from(resource + "_" + lang2 + ".properties")); + } + } + // fallback to default bundle (unconditionally) + addTo(result, from(resource + ".properties")); + return result; + } + + private static void addTo(List list, URL toAdd) { + if (toAdd != null) { + if (!list.contains(toAdd)) { + list.add(toAdd); + } + } + } + + private URL from(String resourceName) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) { + cl = ResourceResolver.class.getClassLoader(); + } + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } + return cl.getResource(resourceName); + } + + public static PropertyResourceBundle toResourceBundle(List list) throws IOException { + MyPropertyResourceBundle result = null; + for (URL url : Lists.reverse(list)) { + final MyPropertyResourceBundle last = result; + result = new MyPropertyResourceBundle(url); + if (last != null) { + result.setMyParent(last); + } + } + return result; + } +} diff --git a/src/main/java/com/adobe/epubcheck/util/Messages.java b/src/main/java/com/adobe/epubcheck/util/Messages.java index 687c6140a..e1af4a4a5 100644 --- a/src/main/java/com/adobe/epubcheck/util/Messages.java +++ b/src/main/java/com/adobe/epubcheck/util/Messages.java @@ -22,22 +22,15 @@ package com.adobe.epubcheck.util; -import java.io.BufferedReader; +import com.adobe.epubcheck.messages.ResourceResolver; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; -import java.util.PropertyResourceBundle; import java.util.ResourceBundle; -import java.util.ResourceBundle.Control; - -import com.google.common.base.Charsets; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Table; public class Messages { @@ -123,8 +116,13 @@ protected Messages(Locale locale) protected Messages(Locale locale, String bundleName) { - this.locale = (locale != null) ? locale : Locale.getDefault(); - this.bundle = ResourceBundle.getBundle(bundleName, this.locale, new UTF8Control()); + this.locale = (locale != null) ? locale : Locale.getDefault(); + try { + this.bundle = ResourceResolver.toResourceBundle( + ResourceResolver.getInstance().resource2Url(bundleName, this.locale)); + } catch (IOException e) { + throw new IllegalStateException(e); + } } public String get(String key) @@ -149,54 +147,4 @@ public Locale getLocale() return locale; } - private class UTF8Control extends Control - { - @Override - public ResourceBundle newBundle - (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) - throws - IllegalAccessException, - InstantiationException, - IOException - { - // The below is a copy of the default implementation. - String bundleName = toBundleName(baseName, locale); - String resourceName = toResourceName(bundleName, "properties"); //$NON-NLS-1$ - ResourceBundle bundle = null; - InputStream stream = null; - if (reload) - { - URL url = loader.getResource(resourceName); - if (url != null) - { - URLConnection connection = url.openConnection(); - if (connection != null) - { - connection.setUseCaches(false); - stream = connection.getInputStream(); - } - } - } - else - { - stream = loader.getResourceAsStream(resourceName); - } - if (stream != null) - { - try - { - // Only this line is changed to make it to read properties files as UTF-8. - bundle = new PropertyResourceBundle( - new BufferedReader( - new InputStreamReader(stream, Charsets.UTF_8))); - } - finally - { - stream.close(); - } - } - return bundle; - } - } - } diff --git a/src/main/java/com/thaiopensource/util/Localizer.java b/src/main/java/com/thaiopensource/util/Localizer.java index 6237dec30..c5154215b 100644 --- a/src/main/java/com/thaiopensource/util/Localizer.java +++ b/src/main/java/com/thaiopensource/util/Localizer.java @@ -1,5 +1,6 @@ package com.thaiopensource.util; +import java.io.IOException; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -7,6 +8,7 @@ import com.adobe.epubcheck.messages.LocaleHolder; import com.adobe.epubcheck.messages.LocalizedMessages; +import com.adobe.epubcheck.messages.ResourceResolver; import java.text.MessageFormat; @@ -56,11 +58,20 @@ private ResourceBundle getBundle() { String s = cls.getName(); int i = s.lastIndexOf('.'); - if (i > 0) s = s.substring(0, i + 1); + if (i > 0) { + s = s.substring(0, i + 1); + } else - s = ""; - bundles.put(locale, ResourceBundle.getBundle(s + "resources.Messages", LocaleHolder.get(), - new LocalizedMessages.UTF8Control())); + { + s = ""; + } + try { + bundles.put(locale, + ResourceResolver.toResourceBundle(ResourceResolver.getInstance() + .resource2Url(s + "resources.Messages", LocaleHolder.get()))); + } catch (IOException e) { + throw new IllegalStateException(e); + } } return bundles.get(locale); }