From 8bc1734431e2fe93da57f1a168ec2dc7bd1a211a Mon Sep 17 00:00:00 2001 From: Milad Khajvi Date: Thu, 27 Aug 2015 16:26:45 +0430 Subject: [PATCH] bugfix(JstlLocalization): fix parsing utf8 strings --- .../caelum/vraptor/core/JstlLocalization.java | 20 ++--- .../com/caelum/vraptor/core/UTF8Control.java | 89 +++++++++++++++++++ 2 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 vraptor-core/src/main/java/br/com/caelum/vraptor/core/UTF8Control.java diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/JstlLocalization.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/JstlLocalization.java index 3e094886a..340b5cc14 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/JstlLocalization.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/JstlLocalization.java @@ -16,11 +16,10 @@ */ package br.com.caelum.vraptor.core; -import static com.google.common.base.Objects.firstNonNull; - -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import br.com.caelum.vraptor.util.EmptyBundle; +import br.com.caelum.vraptor.util.SafeResourceBundle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Produces; @@ -29,12 +28,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.jstl.core.Config; import javax.servlet.jsp.jstl.fmt.LocalizationContext; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import br.com.caelum.vraptor.util.EmptyBundle; -import br.com.caelum.vraptor.util.SafeResourceBundle; +import static com.google.common.base.Objects.firstNonNull; /** * The default implementation of bundle provider uses JSTL's api to access user information on the bundle to be used. @@ -75,7 +73,7 @@ private ResourceBundle extractUnsafeBundle(Object bundle, Locale locale) { String baseName = firstNonNull((String) bundle, DEFAULT_BUNDLE_NAME); try { - return ResourceBundle.getBundle(baseName, locale); + return ResourceBundle.getBundle(baseName, locale, new UTF8Control()); } catch (MissingResourceException e) { logger.warn("couldn't find message bundle, creating an empty one", e); return new EmptyBundle(); diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/UTF8Control.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/UTF8Control.java new file mode 100644 index 000000000..6f0f6b03e --- /dev/null +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/UTF8Control.java @@ -0,0 +1,89 @@ +/* + https://gist.github.com/Hasacz89/d93955ec91afc73a06e3 + */ + +package br.com.caelum.vraptor.core; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Locale; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +public class UTF8Control extends ResourceBundle.Control { + 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); + ResourceBundle bundle = null; + switch (format) { + case "java.class": + try { + @SuppressWarnings("unchecked") + Class bundleClass + = (Class) loader.loadClass(bundleName); + + // If the class isn't a ResourceBundle subclass, throw a + // ClassCastException. + if (ResourceBundle.class.isAssignableFrom(bundleClass)) { + bundle = bundleClass.newInstance(); + } else { + throw new ClassCastException(bundleClass.getName() + + " cannot be cast to ResourceBundle"); + } + } catch (ClassNotFoundException e) { + } + + break; + case "java.properties": + final String resourceName = toResourceName(bundleName, "properties"); + final ClassLoader classLoader = loader; + final boolean reloadFlag = reload; + InputStream stream; + try { + stream = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public InputStream run() throws IOException { + InputStream is = null; + if (reloadFlag) { + URL url = classLoader.getResource(resourceName); + if (url != null) { + URLConnection connection = url.openConnection(); + if (connection != null) { + // Disable caches to get fresh data for + // reloading. + connection.setUseCaches(false); + is = connection.getInputStream(); + } + } + } else { + is = classLoader.getResourceAsStream(resourceName); + } + return is; + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + if (stream != null) { + try { + bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); + } finally { + stream.close(); + } + } + + break; + default: + throw new IllegalArgumentException("unknown format: " + format); + } + return bundle; + } +}