1 |
package net.oni2.resourcebundle; |
2 |
|
3 |
/* |
4 |
* This file is part of aion-emu <aion-emu.com>. |
5 |
* |
6 |
* aion-emu is free software: you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation, either version 3 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* aion-emu is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with aion-emu. If not, see <http://www.gnu.org/licenses/>. |
18 |
*/ |
19 |
//package com.aionemu.commons.utils.i18n; |
20 |
|
21 |
import java.io.IOException; |
22 |
import java.io.InputStream; |
23 |
import java.io.InputStreamReader; |
24 |
import java.net.URL; |
25 |
import java.net.URLConnection; |
26 |
import java.security.AccessController; |
27 |
import java.security.PrivilegedActionException; |
28 |
import java.security.PrivilegedExceptionAction; |
29 |
import java.util.Locale; |
30 |
import java.util.PropertyResourceBundle; |
31 |
import java.util.ResourceBundle; |
32 |
|
33 |
/** |
34 |
* This class allows us to read ResourceBundles with custom encodings, so we |
35 |
* don't have write \\uxxxx symbols and use utilities like native2ascii to |
36 |
* convert files. |
37 |
* <p/> |
38 |
* <br> |
39 |
* |
40 |
* Usage: For instance we want to load resource bundle "test" from current |
41 |
* deirectory and use english locale. If locale not found, we will use default |
42 |
* file (and ignore default locale). |
43 |
* |
44 |
* <pre> |
45 |
* URLClassLoader loader = new URLClassLoader(new URL[] { new File(".").toURI() |
46 |
* .toURL() }); |
47 |
* |
48 |
* ResourceBundle rb = ResourceBundle.getBundle("test", Locale.ENGLISH, loader, |
49 |
* new ResourceBundleControl("UTF-8")); |
50 |
* |
51 |
* // English locale not found, use default |
52 |
* if (!rb.getLocale().equals(Locale.ENGLISH)) { |
53 |
* rb = ResourceBundle.getBundle("test", Locale.ROOT, loader, |
54 |
* new ResourceBundleControl("UTF-8")); |
55 |
* } |
56 |
* |
57 |
* System.out.println(rb.getString("test")); |
58 |
* </pre> |
59 |
* |
60 |
* @author SoulKeeper |
61 |
*/ |
62 |
public class ResourceBundleControl extends ResourceBundle.Control { |
63 |
/** |
64 |
* Encoding which will be used to read resource bundle, by defaults it's |
65 |
* 8859_1 |
66 |
*/ |
67 |
private String encoding = "UTF-8"; |
68 |
|
69 |
/** |
70 |
* Just empty default constructor |
71 |
*/ |
72 |
public ResourceBundleControl() { |
73 |
} |
74 |
|
75 |
/** |
76 |
* This constructor allows to set encoding that will be used while reading |
77 |
* resource bundle |
78 |
* |
79 |
* @param encoding |
80 |
* encoding to use |
81 |
*/ |
82 |
public ResourceBundleControl(String encoding) { |
83 |
this.encoding = encoding; |
84 |
} |
85 |
|
86 |
/** |
87 |
* This code is just copy-paste with usage {@link java.io.Reader} instead of |
88 |
* {@link java.io.InputStream} to read properties.<br> |
89 |
* <br> |
90 |
* |
91 |
* {@inheritDoc} |
92 |
*/ |
93 |
@Override |
94 |
public ResourceBundle newBundle(String baseName, Locale locale, |
95 |
String format, ClassLoader loader, boolean reload) |
96 |
throws IllegalAccessException, InstantiationException, IOException { |
97 |
String bundleName = toBundleName(baseName, locale); |
98 |
ResourceBundle bundle = null; |
99 |
if (format.equals("java.class")) { |
100 |
try { |
101 |
@SuppressWarnings({ "unchecked" }) |
102 |
Class<? extends ResourceBundle> bundleClass = (Class<? extends ResourceBundle>) loader |
103 |
.loadClass(bundleName); |
104 |
|
105 |
// If the class isn't a ResourceBundle subclass, throw a |
106 |
// ClassCastException. |
107 |
if (ResourceBundle.class.isAssignableFrom(bundleClass)) { |
108 |
bundle = bundleClass.newInstance(); |
109 |
} else { |
110 |
throw new ClassCastException(bundleClass.getName() |
111 |
+ " cannot be cast to ResourceBundle"); |
112 |
} |
113 |
} catch (ClassNotFoundException ignored) { |
114 |
} |
115 |
} else if (format.equals("java.properties")) { |
116 |
final String resourceName = toResourceName(bundleName, "properties"); |
117 |
final ClassLoader classLoader = loader; |
118 |
final boolean reloadFlag = reload; |
119 |
InputStreamReader isr = null; |
120 |
InputStream stream; |
121 |
try { |
122 |
stream = AccessController |
123 |
.doPrivileged(new PrivilegedExceptionAction<InputStream>() { |
124 |
@Override |
125 |
public InputStream run() throws IOException { |
126 |
InputStream is = null; |
127 |
if (reloadFlag) { |
128 |
URL url = classLoader |
129 |
.getResource(resourceName); |
130 |
if (url != null) { |
131 |
URLConnection connection = url |
132 |
.openConnection(); |
133 |
if (connection != null) { |
134 |
// Disable caches to get fresh data |
135 |
// for |
136 |
// reloading. |
137 |
connection.setUseCaches(false); |
138 |
is = connection.getInputStream(); |
139 |
} |
140 |
} |
141 |
} else { |
142 |
is = classLoader |
143 |
.getResourceAsStream(resourceName); |
144 |
} |
145 |
return is; |
146 |
} |
147 |
}); |
148 |
if (stream != null) { |
149 |
isr = new InputStreamReader(stream, encoding); |
150 |
} |
151 |
} catch (PrivilegedActionException e) { |
152 |
throw (IOException) e.getException(); |
153 |
} |
154 |
if (isr != null) { |
155 |
try { |
156 |
bundle = new PropertyResourceBundle(isr); |
157 |
} finally { |
158 |
isr.close(); |
159 |
} |
160 |
} |
161 |
} else { |
162 |
throw new IllegalArgumentException("unknown format: " + format); |
163 |
} |
164 |
return bundle; |
165 |
} |
166 |
|
167 |
/** |
168 |
* Returns encoding that will be used to read .properties resource bundles |
169 |
* |
170 |
* @return encoding |
171 |
*/ |
172 |
public String getEncoding() { |
173 |
return encoding; |
174 |
} |
175 |
|
176 |
/** |
177 |
* Sets the encoding that will be used to read properties resource bundles |
178 |
* |
179 |
* @param encoding |
180 |
* encoding that will be used for properties |
181 |
*/ |
182 |
public void setEncoding(String encoding) { |
183 |
this.encoding = encoding; |
184 |
} |
185 |
} |