Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buxfix(i18n): read utf8 resource if needed. #190 #212

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 56 additions & 9 deletions src/main/java/org/mamute/i18n/MamuteLocalization.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.mamute.i18n;

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.annotation.Priority;
Expand All @@ -10,12 +11,16 @@
import javax.interceptor.Interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.jstl.core.Config;
import javax.servlet.jsp.jstl.fmt.LocalizationContext;

import br.com.caelum.vraptor.core.JstlLocalization;
import br.com.caelum.vraptor.util.EmptyBundle;
import br.com.caelum.vraptor.util.SafeResourceBundle;
import com.google.common.base.Objects;

@Alternative
@Priority(Interceptor.Priority.APPLICATION)
public class MamuteLocalization extends JstlLocalization{
public class MamuteLocalization extends JstlLocalization {

private final HttpServletRequest request;

Expand All @@ -25,27 +30,69 @@ public class MamuteLocalization extends JstlLocalization{
protected MamuteLocalization() {
this(null);
}

@Inject
public MamuteLocalization(HttpServletRequest request) {
super(request);
this.request = request;
}


@Override @Produces
public ResourceBundle getBundle(Locale locale) {
Config.set(request, Config.FMT_LOCALIZATION_CONTEXT, null);
ResourceBundle customBundle = super.getBundle(locale);
ResourceBundle customBundle = getUTF8Bundle(locale);
Config.set(request, Config.FMT_LOCALIZATION_CONTEXT, "mamute-messages");
ResourceBundle mamuteBundle = super.getBundle(locale);
ResourceBundle mamuteBundle = getUTF8Bundle(locale);

return new MamuteResourceBundle(customBundle, mamuteBundle);
}


public ResourceBundle getUTF8Bundle(Locale locale) {
Object bundle = this.findByKey("javax.servlet.jsp.jstl.fmt.localizationContext");
ResourceBundle unsafe = this.extractUnsafeBundle(bundle, locale);
return new SafeResourceBundle(unsafe);
}


private ResourceBundle extractUnsafeBundle(Object bundle, Locale locale) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code is quite big and complex, I think we should extract it to a separate class to be able to unit test it easier, what do you think @khajavi?

if (!(bundle instanceof String) && bundle != null) {
if (bundle instanceof LocalizationContext) {
return ((LocalizationContext) bundle).getResourceBundle();
} else {
return new EmptyBundle();
}
} else {
String baseName = Objects.firstNonNull((String) bundle, "messages");
try {
if (locale.getLanguage().equals("fa"))
return ResourceBundle.getBundle(baseName, locale, new UTF8Control());
else
return ResourceBundle.getBundle(baseName, locale);
} catch (MissingResourceException var5) {
return new EmptyBundle();
}
}
}

private Object findByKey(String key) {
Object value = Config.get(this.request, key);
if (value != null) {
return value;
} else {
value = Config.get(this.request.getSession(), key);
if (value != null) {
return value;
} else {
value = Config.get(this.request.getServletContext(), key);
return value != null ? value : this.request.getServletContext().getInitParameter(key);
}
}
}

@Override @Produces
public Locale getLocale() {
return super.getLocale();
}

}
86 changes: 86 additions & 0 deletions src/main/java/org/mamute/i18n/UTF8Control.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.mamute.i18n;
/* https://gist.github.com/Hasacz89/d93955ec91afc73a06e3 */

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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is quite complex also, maybe we should extract two classes here, something like: JavaClassResourceLoader and JavaPropertiesResourceLoader, what do you think?

Class<? extends ResourceBundle> bundleClass
= (Class<? extends ResourceBundle>) 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we at least log this exception?

}

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<InputStream>() {
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;
}
}