KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > script > common > BundleMap


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18 package org.apache.beehive.netui.script.common;
19
20 import org.apache.beehive.netui.util.internal.InternalStringBuilder;
21 import org.apache.beehive.netui.util.internal.ServletUtils;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.Set JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Locale JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.ResourceBundle JavaDoc;
30 import javax.servlet.http.HttpServletRequest JavaDoc;
31 import javax.servlet.http.HttpSession JavaDoc;
32 import javax.servlet.ServletContext JavaDoc;
33
34 import org.apache.struts.Globals;
35 import org.apache.struts.config.MessageResourcesConfig;
36 import org.apache.struts.config.ModuleConfig;
37 import org.apache.struts.util.MessageResources;
38
39 import org.apache.beehive.netui.script.common.bundle.BundleNode;
40 import org.apache.beehive.netui.script.common.bundle.BundleNodeFactory;
41 import org.apache.beehive.netui.util.logging.Logger;
42 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
43
44 /**
45  * Provide a {@link java.util.Map} of {@link org.apache.beehive.netui.script.common.BundleMap.BundleNodeMap} objects that can
46  * expose various implementations of {@link BundleNode} to
47  * expression languages. <p/> This {@link java.util.Map} implementation is
48  * optimized for read as the entrySet() is created lazily. In addition, the
49  * entrySet does not contain all possible BundleNodeMap objects as named
50  * "message-resources" bundles are discovered at runtime and requested by name.
51  * <p/>
52  */

53 public class BundleMap
54     extends AbstractScriptableMap {
55
56     public static final String JavaDoc DEFAULT_STRUTS_BUNDLE_NAME = "default";
57
58     private static final Logger LOGGER = Logger.getInstance(BundleMap.class);
59
60     private HashMap JavaDoc _registeredBundles = null;
61
62     private HttpServletRequest JavaDoc _servletRequest = null;
63     private HttpSession JavaDoc _httpSession = null;
64     private ServletContext JavaDoc _servletContext = null;
65
66     /**
67      * Create a BundleMap object that is used for data binding to resource
68      * bundles.
69      *
70      * @param servletRequest the current {@link javax.servlet.http.HttpServletRequest} object
71      * @param servletContext a {@link javax.servlet.ServletContext} object that facilitates binding to resource bundles
72      * declared in Struts modules
73      */

74     public BundleMap(HttpServletRequest JavaDoc servletRequest, ServletContext JavaDoc servletContext) {
75         assert servletRequest != null;
76         assert servletContext != null;
77
78         _servletRequest = servletRequest;
79         _httpSession = servletRequest.getSession(false);
80         _servletContext = servletContext;
81
82         _registeredBundles = new HashMap JavaDoc();
83     }
84
85     public void registerResourceBundle(String JavaDoc name, String JavaDoc resourcePath, Locale JavaDoc forcedLocale) {
86         if(_registeredBundles == null)
87             _registeredBundles = new HashMap JavaDoc();
88
89         if(LOGGER.isInfoEnabled() && _registeredBundles.containsKey(name))
90             LOGGER.info("The bundle map already contains a key \"" + name + "\" overwriting the previous value.");
91
92         Locale JavaDoc locale = forcedLocale != null ? forcedLocale : InternalUtils.lookupLocale(_servletRequest);
93         ResourceBundle JavaDoc resourceBundle = ResourceBundle.getBundle(resourcePath, locale);
94         BundleNode bundle = BundleNodeFactory.getInstance().getResourceBundleNode(name, resourceBundle, locale);
95         _registeredBundles.put(name, bundle);
96     }
97
98     public Object JavaDoc get(Object JavaDoc key) {
99         if(key == null)
100             throw new NullPointerException JavaDoc("Binding to a resource bundle does not accept a null key");
101
102         BundleNodeMap map = lookupScriptableBundle(key.toString());
103         if(map == null) {
104             /* handleBundleNotFound will throw an exception when the message key isn't found */
105             handleBundleNotFound(key.toString());
106             return null;
107         }
108         else return map;
109     }
110
111     /**
112      * Implementation of Map.containsKey for the bundle implicit object.
113      *
114      * This method is required by JSP 2.0 EL and performs the lookups of the
115      * various available bundles which have been registered either explicitly or
116      * implicitly.
117      *
118      * @param key The name of a bundle to lookup
119      * @return <code>true</code> if the bundle is available; <code>false</code> otherwise
120      */

121     public boolean containsKey(Object JavaDoc key) {
122         if(key == null)
123             throw new NullPointerException JavaDoc("Binding to a resource bundle does not accept a null key");
124
125         BundleNodeMap map = lookupScriptableBundle(key.toString());
126         return map != null;
127     }
128
129     public Set JavaDoc entrySet() {
130         ArrayList JavaDoc entries = new ArrayList JavaDoc();
131
132         /* add BundleNode objects that have been accessed */
133         if(_registeredBundles != null) {
134             Iterator JavaDoc iterator = _registeredBundles.keySet().iterator();
135             while(iterator.hasNext()) {
136                 Object JavaDoc key = iterator.next();
137                 entries.add(new BundleNodeEntry(key));
138             }
139         }
140
141         MessageResources resources = null;
142
143         resources = lookupDefaultStrutsBundle();
144         if(resources != null)
145             entries.add(new BundleNodeEntry(DEFAULT_STRUTS_BUNDLE_NAME));
146
147         ModuleConfig moduleConfig = lookupCurrentModuleConfig();
148         if(moduleConfig != null) {
149             MessageResourcesConfig[] mrs = moduleConfig.findMessageResourcesConfigs();
150             for(int i = 0; i < mrs.length; i++) {
151                 String JavaDoc resourceKey = mrs[i].getKey() + moduleConfig.getPrefix();
152                 resources = lookupStrutsBundle(resourceKey);
153                 entries.add(new BundleNodeEntry(mrs[i].getKey()));
154             }
155         }
156
157         return new EntrySet((Entry[])entries.toArray(new Entry[] {}));
158     }
159
160     /*
161      */

162     private BundleNodeMap lookupScriptableBundle(String JavaDoc name) {
163         BundleNodeMap map = null;
164
165         /* check to see if the bundle was explicitly registered */
166         if(_registeredBundles != null && _registeredBundles.containsKey(name)) {
167             map = new BundleNodeMap(name, (BundleNode)_registeredBundles.get(name));
168         }
169         else if(name.equals(DEFAULT_STRUTS_BUNDLE_NAME)) {
170             MessageResources resources = lookupDefaultStrutsBundle();
171             if(resources != null) {
172                 BundleNode bundleNode = BundleNodeFactory.getInstance().getStrutsBundleNode(name, resources, retrieveUserLocale());
173                 map = new BundleNodeMap(name, bundleNode);
174             }
175         }
176         else if(_servletContext.getAttribute(name) != null) {
177             MessageResources resources = lookupStrutsBundle(name);
178             if(resources != null) {
179                 BundleNode bundleNode = BundleNodeFactory.getInstance().getStrutsBundleNode(name, resources, retrieveUserLocale());
180                 map = new BundleNodeMap(name, bundleNode);
181             }
182         }
183         else {
184             ModuleConfig moduleConfig = lookupCurrentModuleConfig();
185             if(moduleConfig != null) {
186                 MessageResourcesConfig[] mrs = moduleConfig.findMessageResourcesConfigs();
187                 if(mrs != null) {
188                     for(int i = 0; i < mrs.length; i++) {
189                         /* skip the default bundle */
190                         if(mrs[i].getKey().equals(Globals.MESSAGES_KEY))
191                             continue;
192                         else if(mrs[i].getKey().equals(name)) {
193                             String JavaDoc resourceKey = mrs[i].getKey() + moduleConfig.getPrefix();
194                             MessageResources resources = lookupStrutsBundle(resourceKey);
195                             BundleNode bundleNode = BundleNodeFactory.getInstance().getStrutsBundleNode(name, resources, retrieveUserLocale());
196                             map = new BundleNodeMap(name, bundleNode);
197                             break;
198                         }
199                     }
200                 }
201             }
202         }
203
204         return map;
205     }
206
207     /**
208      * Lookup the "default" resource bundle for the current Struts module.
209      *
210      * @return a MessageResources object if a "default" bundle exists.
211      * <code>null</code> otherwise
212      */

213     private MessageResources lookupDefaultStrutsBundle() {
214         Object JavaDoc value = _servletRequest.getAttribute(Globals.MESSAGES_KEY);
215         if(value instanceof MessageResources)
216             return (MessageResources)value;
217         else {
218             if(value != null)
219                 LOGGER.warn("Can not resolve the default module bundle."
220                                 + " The object resolved from the request is of type "
221                                 +(value != null ? value.getClass().toString() : "null"));
222             return null;
223         }
224     }
225
226     /**
227      * Lookup a specific resource bundle for the current Struts module.
228      *
229      * @param name
230      * the name of the resource bundle to lookup
231      * @return a MessageResources object if a bundle matching the given name
232      * exists. <code>null</code> otherwise.
233      */

234     private MessageResources lookupStrutsBundle(String JavaDoc name) {
235         Object JavaDoc value = _servletContext.getAttribute(name);
236         if(value instanceof MessageResources)
237             return (MessageResources)value;
238         else {
239             if(value != null)
240                 LOGGER.warn("Can not resolve module bundle with name \"" + name
241                                 + "\". The object resolved from ServletContext is of type "
242                                 +(value != null ? value.getClass().toString() : "null"));
243             return null;
244         }
245     }
246
247     private final ModuleConfig lookupCurrentModuleConfig() {
248         return (ModuleConfig)_servletRequest.getAttribute(Globals.MODULE_KEY);
249     }
250
251     private void handleBundleNotFound(String JavaDoc name) {
252
253         /* At this point, no message bundle could be found. Throw an error that contains a
254            descriptive message about the bundles that are available
255           */

256         String JavaDoc registeredBundles = formatBundleNames(createBundleList());
257         String JavaDoc strutsBundles = formatBundleNames(createStrutsBundleList());
258
259         String JavaDoc msg = "The bundle named \"" + name + "\" was not found in the list of registered bundles with names "
260                      + registeredBundles + " or implicit bundle names " + strutsBundles + ".";
261
262         LOGGER.error(msg);
263         throw new RuntimeException JavaDoc(msg);
264     }
265
266     private final String JavaDoc formatBundleNames(String JavaDoc[] names) {
267         InternalStringBuilder sb = new InternalStringBuilder(128);
268         sb.append("[");
269         for(int i = 0; i < names.length; i++) {
270             if(i > 0)
271                 sb.append(", ");
272             sb.append(names[i]);
273         }
274         sb.append("]");
275
276         return sb.toString();
277     }
278
279     private final String JavaDoc[] createBundleList() {
280         String JavaDoc[] names = null;
281         if(_registeredBundles != null) {
282             names = new String JavaDoc[_registeredBundles.size()];
283             Iterator JavaDoc iterator = _registeredBundles.keySet().iterator();
284             for(int i = 0; iterator.hasNext(); i++) {
285                 names[i] = iterator.next().toString();
286             }
287         }
288
289         return names;
290     }
291
292     private final String JavaDoc[] createStrutsBundleList() {
293         String JavaDoc[] names = null;
294         ModuleConfig config = lookupCurrentModuleConfig();
295         if(config != null) {
296             MessageResourcesConfig[] mrs = config.findMessageResourcesConfigs();
297             names = new String JavaDoc[mrs.length];
298             if(mrs != null) {
299                 for(int i = 0; i < mrs.length; i++) {
300                     if(mrs[i].getKey().equals(Globals.MESSAGES_KEY))
301                         names[i] = DEFAULT_STRUTS_BUNDLE_NAME;
302                     else names[i] = mrs[i].getKey() + config.getPrefix();
303                 }
304             }
305         }
306         return names;
307     }
308
309     /**
310      * Utility method that discovers the {@link java.util.Locale} for the
311      * current request.
312      *
313      * @return the {@link java.util.Locale} to use when looking-up strings while data binding to resource bundles
314      */

315     private final Locale JavaDoc retrieveUserLocale() {
316         return InternalUtils.lookupLocale(_servletRequest);
317     }
318
319     final class BundleNodeEntry
320         extends Entry
321     {
322         BundleNodeEntry(Object JavaDoc key) {
323             super(key, null);
324         }
325
326         public Object JavaDoc getValue() {
327             assert getKey() instanceof String JavaDoc;
328
329             String JavaDoc key = (String JavaDoc)getKey();
330             return lookupScriptableBundle(key);
331         }
332     }
333
334     /**
335      * Provide a {@link java.util.Map} implementation that exposes a
336      * {@link org.apache.beehive.netui.script.common.bundle.BundleNode}
337      * object to an expression language as a Map. Access to the values in the
338      * map is by key and depends on the implementation of the BundleNode. <p/>
339      * Access is read optimized and the complete entrySet() is only constructed
340      * when needed.
341      */

342     final class BundleNodeMap
343         extends AbstractScriptableMap {
344
345         private String JavaDoc _propertiesName = null;
346         private BundleNode _bundle = null;
347         private Set JavaDoc _entrySet = null;
348
349         BundleNodeMap(String JavaDoc propertiesName, BundleNode bundle) {
350             assert bundle != null;
351             assert propertiesName != null;
352
353             _bundle = bundle;
354             _propertiesName = propertiesName;
355         }
356
357         public Set JavaDoc entrySet() {
358             if(_entrySet == null) {
359                 ArrayList JavaDoc list = new ArrayList JavaDoc();
360                 Enumeration JavaDoc enumeration = _bundle.getKeys();
361                 while(enumeration.hasMoreElements()) {
362                     String JavaDoc key =(String JavaDoc)enumeration.nextElement();
363                     String JavaDoc msg = _bundle.getString(key);
364                     list.add(new Entry(key, msg));
365                 }
366                 _entrySet = new EntrySet((Entry[])list.toArray(new Entry[] {}));
367             }
368
369             return _entrySet;
370         }
371
372         public Object JavaDoc get(Object JavaDoc key) {
373             if(key == null)
374                 throw new NullPointerException JavaDoc("Bundle data binding does not accept a null key");
375
376             String JavaDoc result = _bundle.getString(key.toString());
377             if(result == null) {
378                 String JavaDoc msg = "The bundle property name \"" + key + "\" could not be found in the properties bundle \"" + _propertiesName + "\".";
379                 LOGGER.error(msg);
380                 throw new IllegalArgumentException JavaDoc(msg);
381             }
382             else return result;
383         }
384
385         public boolean containsKey(Object JavaDoc key) {
386             if(key == null)
387                 return false;
388             else return _bundle.getString(key.toString()) != null;
389         }
390
391         public String JavaDoc toString() {
392             return _bundle != null ? _bundle.toString() : "BundleMap contains an empty BundleNode";
393         }
394     }
395 }
396      
397
Popular Tags