Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Messages |
|
| 1.7857142857142858;1.786 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to you under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | package org.apache.shale.util; | |
19 | ||
20 | import java.text.MessageFormat; | |
21 | import java.util.HashMap; | |
22 | import java.util.Locale; | |
23 | import java.util.Map; | |
24 | import java.util.MissingResourceException; | |
25 | import java.util.ResourceBundle; | |
26 | import org.apache.commons.logging.Log; | |
27 | import org.apache.commons.logging.LogFactory; | |
28 | ||
29 | /** | |
30 | * <p>Utility wrapper around resource bundles that provides locale-specific | |
31 | * message string lookups, as well as parameter replacement services.</p> | |
32 | * | |
33 | * <p>If desired, this class can be used to define a managed bean wrapping | |
34 | * a specified resource bundle, with a declaration like this in a | |
35 | * <code>faces-config.xml</code> configuration file:</p> | |
36 | * <pre> | |
37 | * <managed-bean> | |
38 | * <managed-bean-name>messages</managed-bean-name> | |
39 | * <managed-bean-class> | |
40 | * org.apache.shale.util.Messages | |
41 | * </managed-bean-class> | |
42 | * <managed-bean-scope>application</managed-bean-scope> | |
43 | * <managed-property> | |
44 | * <property-name>name</property-name> | |
45 | * <value>com.mycompany.mypackage.Bundle</value> | |
46 | * </managed-property> | |
47 | * </managed-bean> | |
48 | * </pre> | |
49 | * | |
50 | * $Id: Messages.java 481403 2006-12-01 21:27:54Z rahul $ | |
51 | */ | |
52 | 2 | public class Messages { |
53 | ||
54 | ||
55 | // ------------------------------------------------------------ Constructors | |
56 | ||
57 | ||
58 | /** | |
59 | * <p>Construct an initialized {@link Messages} wrapper. At least the | |
60 | * <code>name</code> property must be initialized before the message | |
61 | * retrieval public methods may be successfully utilized.</p> | |
62 | */ | |
63 | public Messages() { | |
64 | ||
65 | this(null, null); | |
66 | ||
67 | } | |
68 | ||
69 | ||
70 | /** | |
71 | * <p>Construct a new {@link Messages} wrapper around the specified | |
72 | * resource bundle name, loaded by the default class loader.</p> | |
73 | * | |
74 | * @param name Name of the requested <code>ResourceBundle</code> | |
75 | */ | |
76 | public Messages(String name) { | |
77 | ||
78 | 3 | this(name, null); |
79 | ||
80 | 3 | } |
81 | ||
82 | ||
83 | /** | |
84 | * <P>Construct a new {@link Messages} wrapper around the specified | |
85 | * resource bundle name, loaded by the specified class loader.</p> | |
86 | * | |
87 | * @param name Name of the requested <code>ResourceBundle</code> | |
88 | * @param cl <code>ClassLoader</code> to use for loading this | |
89 | * resource bundle, or <code>null</code> for the default (which | |
90 | * selects the thread context class loader) | |
91 | */ | |
92 | 4 | public Messages(String name, ClassLoader cl) { |
93 | ||
94 | 4 | this.name = name; |
95 | 4 | this.cl = cl; |
96 | ||
97 | 4 | } |
98 | ||
99 | ||
100 | // ------------------------------------------------------ Instance Variables | |
101 | ||
102 | ||
103 | /** | |
104 | * <p>Set of localized <code>ResourceBundle</code> instances we have ever | |
105 | * retrieved, keyed by <code>Locale</code>.</p> | |
106 | */ | |
107 | 4 | private Map bundles = new HashMap(); |
108 | ||
109 | ||
110 | /** | |
111 | * <p>The default <code>Locale</code> for this server.</p> | |
112 | */ | |
113 | 4 | private Locale defaultLocale = Locale.getDefault(); |
114 | ||
115 | ||
116 | /** | |
117 | * <p><code>MessageFormat</code> used to perform parameter substitution.</p> | |
118 | */ | |
119 | 4 | private MessageFormat format = new MessageFormat(""); |
120 | ||
121 | ||
122 | /** | |
123 | * <p>Log instance for this class.</p> | |
124 | */ | |
125 | 4 | private transient Log log = null; |
126 | ||
127 | ||
128 | // -------------------------------------------------------------- Properties | |
129 | ||
130 | ||
131 | /** | |
132 | * <p><code>ClassLoader</code> from which to load the specfied | |
133 | * resource bundle, or <code>null</code> for the thread context | |
134 | * class loader.</p> | |
135 | */ | |
136 | 4 | private ClassLoader cl = null; |
137 | ||
138 | ||
139 | /** | |
140 | * <p>Return the <code>ClassLoader</code> from which to load the | |
141 | * specified resource bundle, or <code>null</code> for the thread | |
142 | * context class loader.</p> | |
143 | */ | |
144 | public ClassLoader getClassLoader() { | |
145 | ||
146 | return this.cl; | |
147 | ||
148 | } | |
149 | ||
150 | ||
151 | /** | |
152 | * <p>Set the <code>ClassLoader</code> from which to load the | |
153 | * specified resource bundle.</p> | |
154 | * | |
155 | * @param cl The new class loader, or <code>null</code> for the | |
156 | * thread context class loader | |
157 | */ | |
158 | public void setClassLoader(ClassLoader cl) { | |
159 | ||
160 | this.cl = null; | |
161 | reset(); | |
162 | ||
163 | } | |
164 | ||
165 | ||
166 | /** | |
167 | * <p>Name of the resource bundle to be retrieved.</p> | |
168 | */ | |
169 | 4 | private String name = null; |
170 | ||
171 | ||
172 | /** | |
173 | * <p>Return the name of the resource bundle to be retrieved.</p> | |
174 | */ | |
175 | public String getName() { | |
176 | ||
177 | 1 | return this.name; |
178 | ||
179 | } | |
180 | ||
181 | ||
182 | /** | |
183 | * <p>Set the name of the resource bunde to be retrieved.</p> | |
184 | * | |
185 | * @param name New name of the resource bundle to be retrieved | |
186 | */ | |
187 | public void setName(String name) { | |
188 | ||
189 | this.name = name; | |
190 | reset(); | |
191 | ||
192 | } | |
193 | ||
194 | ||
195 | // ---------------------------------------------------------- Public Methods | |
196 | ||
197 | ||
198 | /** | |
199 | * <p>Retrieve the specified message string for the default locale. If no | |
200 | * message can be found, return <code>null</code>.</p> | |
201 | * | |
202 | * @param key Key to the message string to look up | |
203 | */ | |
204 | public String getMessage(String key) { | |
205 | ||
206 | 2 | return getMessage(key, defaultLocale); |
207 | ||
208 | } | |
209 | ||
210 | ||
211 | /** | |
212 | * <p>Retrieve the specified message string for the default locale, and | |
213 | * perform parameter substitution with the specified parameters. If no | |
214 | * message can be found, return <code>null</code>.</p> | |
215 | * | |
216 | * @param key Key to the message string to look up | |
217 | * @param params Parameter replacement values | |
218 | */ | |
219 | public String getMessage(String key, Object params[]) { | |
220 | ||
221 | return getMessage(key, defaultLocale, params); | |
222 | ||
223 | } | |
224 | ||
225 | ||
226 | /** | |
227 | * <p>Retrieve the specified message string for the specified locale. If no | |
228 | * message can be found, return <code>null</code>.</p> | |
229 | * | |
230 | * @param key Key to the message string to look up | |
231 | * @param locale Locale used to localize this message | |
232 | */ | |
233 | public String getMessage(String key, Locale locale) { | |
234 | ||
235 | 6 | ResourceBundle rb = getBundle(locale); |
236 | try { | |
237 | 6 | return rb.getString(key); |
238 | } catch (MissingResourceException e) { | |
239 | if (log().isWarnEnabled()) { | |
240 | log().warn("Key " + key + " was not found in resource bundle '" + | |
241 | getName() + "' for locale '" + locale + "'"); | |
242 | } | |
243 | return null; | |
244 | } | |
245 | ||
246 | } | |
247 | ||
248 | ||
249 | /** | |
250 | * <p>Retrieve the specified message string for the specified locale, and | |
251 | * perform parameter substitution with the specified parameters. If no | |
252 | * message can be found, return <code>null</code>.</p> | |
253 | * | |
254 | * @param key Key to the message string to look up | |
255 | * @param locale Locale used to localize this message | |
256 | * @param params Parameter replacement values | |
257 | */ | |
258 | public String getMessage(String key, Locale locale, Object params[]) { | |
259 | ||
260 | String message = getMessage(key, locale); | |
261 | if ((message == null) || (params == null) || (params.length < 1)) { | |
262 | return message; | |
263 | } | |
264 | synchronized (format) { | |
265 | format.applyPattern(message); | |
266 | message = format.format(params); | |
267 | } | |
268 | return message; | |
269 | ||
270 | } | |
271 | ||
272 | ||
273 | // --------------------------------------------------------- Private Methods | |
274 | ||
275 | ||
276 | /** | |
277 | * <p>Return the localized <code>ResourceBundle</code> for the specified | |
278 | * <code>Locale</code>.</p> | |
279 | * | |
280 | * @param locale Locale used to select the appropriate resource bundle | |
281 | */ | |
282 | private ResourceBundle getBundle(Locale locale) { | |
283 | ||
284 | 6 | assert locale != null; |
285 | 6 | ResourceBundle rb = null; |
286 | 6 | ClassLoader rbcl = cl; |
287 | 6 | if (rbcl == null) { |
288 | 4 | rbcl = Thread.currentThread().getContextClassLoader(); |
289 | } | |
290 | 6 | synchronized (bundles) { |
291 | 6 | rb = (ResourceBundle) bundles.get(locale); |
292 | 6 | if (rb == null) { |
293 | try { | |
294 | 3 | rb = ResourceBundle.getBundle(name, locale, rbcl); |
295 | } catch (MissingResourceException e) { | |
296 | rb = ResourceBundle.getBundle(name, defaultLocale, rbcl); | |
297 | 3 | } |
298 | 3 | if (rb == null) { |
299 | if (log().isWarnEnabled()) { | |
300 | log().warn("Resource bundle '" + getName() + | |
301 | "' was not found for locale '" + locale + "'"); | |
302 | } | |
303 | } else { | |
304 | 3 | bundles.put(locale, rb); |
305 | } | |
306 | } | |
307 | 6 | return rb; |
308 | } | |
309 | ||
310 | } | |
311 | ||
312 | ||
313 | /** | |
314 | * <p>Return the <code>Log</code> instance for this class.</p> | |
315 | */ | |
316 | private Log log() { | |
317 | ||
318 | if (log == null) { | |
319 | log = LogFactory.getLog(Messages.class); | |
320 | } | |
321 | return log; | |
322 | ||
323 | } | |
324 | ||
325 | ||
326 | /** | |
327 | * <p>Reset any cached <code>ResourceBundle</code> instances due to a | |
328 | * change in one of the relevant properties.</p> | |
329 | */ | |
330 | private void reset() { | |
331 | ||
332 | synchronized (bundles) { | |
333 | bundles.clear(); | |
334 | } | |
335 | ||
336 | } | |
337 | ||
338 | ||
339 | } |