Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
LoadBundle |
|
| 2.65;2.65 | ||||
LoadBundle$1 |
|
| 2.65;2.65 |
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.beans.Beans; | |
21 | import java.util.ArrayList; | |
22 | import java.util.Collection; | |
23 | import java.util.Collections; | |
24 | import java.util.Enumeration; | |
25 | import java.util.HashMap; | |
26 | import java.util.HashSet; | |
27 | import java.util.List; | |
28 | import java.util.Locale; | |
29 | import java.util.Map; | |
30 | import java.util.MissingResourceException; | |
31 | import java.util.ResourceBundle; | |
32 | import java.util.Set; | |
33 | import javax.faces.component.UIViewRoot; | |
34 | ||
35 | import javax.faces.context.FacesContext; | |
36 | ||
37 | /** | |
38 | * <p>Utility class emulating the behavior of the standard JSF Core Library | |
39 | * tag <code><f:loadBundle></code>. This class is designed to be used | |
40 | * as a managed bean, and exposes a <code>map</code> property containing the | |
41 | * messages in the resoruce bundle specified by the <code>basename</code> | |
42 | * property, localized for the <code>Locale</code> specified on the current | |
43 | * request.</p> | |
44 | * | |
45 | * <p>A typical use of this class would be to declare a managed bean like this:</p> | |
46 | * <pre> | |
47 | * <managed-bean> | |
48 | * <managed-bean-name>bundle</managed-bean-name> | |
49 | * <managed-bean-class> | |
50 | * org.apache.shale.util.LoadBundle | |
51 | * </managed-bean-class> | |
52 | * <managed-bean-scope>request</managed-bean-scope> | |
53 | * <managed-property> | |
54 | * <property-name>basename</property-name> | |
55 | * <value>com.mycompany.mypackage.Bundle</value> | |
56 | * </managed-property> | |
57 | * </managed-bean> | |
58 | * </pre> | |
59 | * | |
60 | * <p>This will result in creation of a request scope object whose <code>map</code> | |
61 | * property will return a <code>Map</code> representing the localized messages for | |
62 | * the <code>com.mycompany.mypackage.Bundle</code> resource bundle. You can look | |
63 | * up localized messages in this <code>Map</code> by evaluating a value binding | |
64 | * expression like this:</p> | |
65 | * <blockquote> | |
66 | * <code>#{messages.['message.key']}</code> | |
67 | * </blockquote> | |
68 | * <p>where <code>message.key</code> is the key for which to retrieve a | |
69 | * localized message.</p> | |
70 | * | |
71 | * <p>(Since 1.0.1) <strong>IMPLEMENTATION NOTE</strong> - For backwards | |
72 | * compatibility in applications that utilized the 1.0.0 version of this | |
73 | * class, the following sort of expression resolves to the same value:</p> | |
74 | * <blockquote> | |
75 | * <code>#{messages.map['message.key']}</code> | |
76 | * </blockquote> | |
77 | */ | |
78 | 2 | public class LoadBundle { |
79 | ||
80 | // ------------------------------------------------------------- Constructors | |
81 | ||
82 | ||
83 | /** Creates a new instance of LoadBundle. */ | |
84 | public LoadBundle() { | |
85 | this(null); | |
86 | } | |
87 | ||
88 | ||
89 | /** <p>Creates a new instance of LoadBundle for the specified bundle.</p> | |
90 | * | |
91 | * @param basename Base resource bundle name for this <code>LoadBundle</code> | |
92 | */ | |
93 | 5 | public LoadBundle(String basename) { |
94 | 5 | this.basename = basename; |
95 | 5 | } |
96 | ||
97 | ||
98 | // --------------------------------------------------------- Static Variables | |
99 | ||
100 | ||
101 | /** | |
102 | * <p>The default <code>Locale</code> for this application.</p> | |
103 | */ | |
104 | 1 | private static final Locale defaultLocale = Locale.getDefault(); |
105 | ||
106 | ||
107 | // --------------------------------------------------------------- Properties | |
108 | ||
109 | ||
110 | /** | |
111 | * <p>The base resource bundle name for this <code>LoadBundle</code> instance.</p> | |
112 | */ | |
113 | 5 | private String basename = null; |
114 | ||
115 | ||
116 | /** | |
117 | * <p>Return the base resource bundle name for this <code>LoadBundle</code> | |
118 | * instance.</p> | |
119 | */ | |
120 | public String getBasename() { | |
121 | 1 | return this.basename; |
122 | } | |
123 | ||
124 | ||
125 | /** | |
126 | * <p>Set the base resource bundle name for this <code>LoadBundle</code> | |
127 | * instance.</p> | |
128 | * | |
129 | * @param basename The new base resource bundle name | |
130 | */ | |
131 | public void setBasename(String basename) { | |
132 | this.basename = basename; | |
133 | } | |
134 | ||
135 | ||
136 | // ----------------------------------------------------------- Public Methods | |
137 | ||
138 | ||
139 | /** | |
140 | * <p>Return a <code>Map</code> whose keys and values represent the content | |
141 | * of the application resource bundle specified by the <code>basename</code> | |
142 | * property, localized for the <code>Locale</code> stored in the | |
143 | * <code>UIViewRoot</code> for the current request.</p> | |
144 | * | |
145 | * @exception IllegalStateException if we are not inside a Faces request, | |
146 | * or if there is not a current view root with a valid locale | |
147 | */ | |
148 | public Map getMap() throws IllegalStateException { | |
149 | ||
150 | // Validate our current state | |
151 | 4 | if (basename == null) { |
152 | if (Beans.isDesignTime()) { | |
153 | return Collections.EMPTY_MAP; | |
154 | } | |
155 | throw new IllegalStateException("The 'basename' property cannot be null"); // FIXME - i18n | |
156 | } | |
157 | 4 | FacesContext context = FacesContext.getCurrentInstance(); |
158 | 4 | UIViewRoot root = null; |
159 | 4 | Locale locale = null; |
160 | 4 | if (context != null) { |
161 | 4 | root = context.getViewRoot(); |
162 | } | |
163 | 4 | if (root != null) { |
164 | 4 | locale = root.getLocale(); |
165 | } | |
166 | 4 | if (locale == null) { |
167 | throw new IllegalStateException("Cannot retrieve locale-specific map if there " + | |
168 | "is not a current Faces request, containing a valid view root, with" + | |
169 | "a Locale instance inside."); | |
170 | } | |
171 | ||
172 | // Look up the requested resource bundle | |
173 | 4 | final ResourceBundle bundle = getBundle(basename, locale); |
174 | 4 | if (bundle == null) { |
175 | throw new IllegalArgumentException | |
176 | ("No resource bundle found for base name '" + basename + "' and locale '" + locale + "'"); // FIXME - i18n | |
177 | } | |
178 | ||
179 | // Construct and return an immutable Map representing these contents | |
180 | 4 | Map map = new Map() { |
181 | ||
182 | public void clear() { | |
183 | throw new UnsupportedOperationException(); | |
184 | } | |
185 | ||
186 | public boolean containsKey(Object key) { | |
187 | boolean result = false; | |
188 | if (key != null) { | |
189 | result = bundle.getObject(key.toString()) != null; | |
190 | } | |
191 | return result; | |
192 | } | |
193 | ||
194 | public boolean containsValue(Object value) { | |
195 | Enumeration keys = bundle.getKeys(); | |
196 | while (keys.hasMoreElements()) { | |
197 | Object val = bundle.getObject(keys.nextElement().toString()); | |
198 | if ((val != null) && val.equals(value)) { | |
199 | return true; | |
200 | } | |
201 | } | |
202 | return false; | |
203 | } | |
204 | ||
205 | ||
206 | public Set entrySet() { | |
207 | Map map = new HashMap(); | |
208 | Enumeration keys = bundle.getKeys(); | |
209 | while (keys.hasMoreElements()) { | |
210 | String key = keys.nextElement().toString(); | |
211 | Object value = bundle.getObject(key); | |
212 | map.put(key, value); | |
213 | } | |
214 | return map.entrySet(); | |
215 | } | |
216 | ||
217 | public boolean equals(Object o) { | |
218 | if ((o == null) || !(o instanceof Map)) { | |
219 | return false; | |
220 | } | |
221 | return entrySet().equals(((Map) o).entrySet()); | |
222 | } | |
223 | ||
224 | public Object get(Object key) { | |
225 | 6 | if (key == null) { |
226 | return null; | |
227 | } | |
228 | try { | |
229 | 6 | return bundle.getObject(key.toString()); |
230 | } catch (MissingResourceException e) { | |
231 | return "???" + key.toString() + "???"; | |
232 | } | |
233 | } | |
234 | ||
235 | public int hashCode() { | |
236 | return bundle.hashCode(); | |
237 | } | |
238 | ||
239 | public boolean isEmpty() { | |
240 | Enumeration keys = bundle.getKeys(); | |
241 | while (keys.hasMoreElements()) { | |
242 | return false; | |
243 | } | |
244 | return true; | |
245 | } | |
246 | ||
247 | public Set keySet() { | |
248 | Set set = new HashSet(); | |
249 | Enumeration keys = bundle.getKeys(); | |
250 | while (keys.hasMoreElements()) { | |
251 | set.add(keys.nextElement()); | |
252 | } | |
253 | return set; | |
254 | } | |
255 | ||
256 | public Object put(Object key, Object value) { | |
257 | throw new UnsupportedOperationException(); | |
258 | } | |
259 | ||
260 | public void putAll(Map map) { | |
261 | throw new UnsupportedOperationException(); | |
262 | } | |
263 | ||
264 | public Object remove(Object key) { | |
265 | throw new UnsupportedOperationException(); | |
266 | } | |
267 | ||
268 | public int size() { | |
269 | int size = 0; | |
270 | Enumeration keys = bundle.getKeys(); | |
271 | while (keys.hasMoreElements()) { | |
272 | keys.nextElement(); | |
273 | size++; | |
274 | } | |
275 | return size; | |
276 | } | |
277 | ||
278 | 4 | public Collection values() { |
279 | List list = new ArrayList(); | |
280 | Enumeration keys = bundle.getKeys(); | |
281 | while (keys.hasMoreElements()) { | |
282 | String key = keys.nextElement().toString(); | |
283 | list.add(bundle.getObject(key)); | |
284 | } | |
285 | return list; | |
286 | } | |
287 | ||
288 | }; | |
289 | 4 | return map; |
290 | ||
291 | } | |
292 | ||
293 | ||
294 | // --------------------------------------------------------- Private Methods | |
295 | ||
296 | ||
297 | /** | |
298 | * <p>Return the localized <code>ResourceBundle</code> for the specified | |
299 | * <code>Locale</code>.</p> | |
300 | * | |
301 | * @param basename Base name of the resource bundle to return | |
302 | * @param locale Locale used to select the appropriate resource bundle | |
303 | */ | |
304 | private ResourceBundle getBundle(String basename, Locale locale) { | |
305 | ||
306 | 4 | assert basename != null; |
307 | 4 | assert locale != null; |
308 | 4 | ClassLoader rbcl = Thread.currentThread().getContextClassLoader(); |
309 | 4 | if (rbcl == null) { |
310 | rbcl = this.getClass().getClassLoader(); | |
311 | } | |
312 | try { | |
313 | 4 | return ResourceBundle.getBundle(basename, locale, rbcl); |
314 | } catch (MissingResourceException e) { | |
315 | return ResourceBundle.getBundle(basename, defaultLocale, rbcl); | |
316 | } | |
317 | ||
318 | } | |
319 | ||
320 | ||
321 | } |