KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > i18n > ProjectResourceBundle


1 /*
2  * Copyright 2001-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
17 package org.apache.axis.i18n;
18
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.commons.logging.Log;
21
22 import java.util.Enumeration JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Locale JavaDoc;
27 import java.util.MissingResourceException JavaDoc;
28 import java.util.ResourceBundle JavaDoc;
29
30 /**
31  * <p>Wrapper class for resource bundles. Property files are used to store
32  * resource strings, which are the only types of resources available.
33  * Property files can inherit properties from other files so that
34  * a base property file can be used and a small number of properties
35  * can be over-ridden by another property file. For example you may
36  * create an english version of a resource file named "resource.properties".
37  * You then decide that the British English version of all of the properties
38  * except one are the same, so there is no need to redefine all of the
39  * properties in "resource_en_GB", just the one that is different.</p>
40  * <p>The basename is the name of the property file without the ".properties"
41  * extension.</p>
42  * <p>Properties will be cached for performance.<p>
43  * <p>Property values stored in the property files can also contain dynamic
44  * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
45  * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
46  * Argument values are specified in the various overloaded getString() methods.</p>
47  *
48  * @author Richard A. Sitze (rsitze@us.ibm.com)
49  * @author Karl Moss (kmoss@macromedia.com)
50  * @author Glen Daniels (gdaniels@apache.org)
51  */

52 public class ProjectResourceBundle extends ResourceBundle JavaDoc {
53     protected static Log log =
54         LogFactory.getLog(ProjectResourceBundle.class.getName());
55
56
57     // The static cache of ResourceBundles.
58
// The key is the 'basename + locale + default locale'
59
// The element is a ResourceBundle object
60
private static final Hashtable JavaDoc bundleCache = new Hashtable JavaDoc();
61
62     private static final Locale JavaDoc defaultLocale = Locale.getDefault();
63
64     private final ResourceBundle JavaDoc resourceBundle;
65     private final String JavaDoc resourceName;
66
67     
68     protected Object JavaDoc handleGetObject(String JavaDoc key)
69         throws MissingResourceException JavaDoc
70     {
71         if (log.isDebugEnabled()) {
72             log.debug(this.toString() + "::handleGetObject(" + key + ")");
73         }
74 // return resourceBundle.handleGetObject(key);
75
Object JavaDoc obj;
76         try {
77             obj = resourceBundle.getObject(key);
78         } catch (MissingResourceException JavaDoc e) {
79             /* catch missing resource, ignore, & return null
80              * if this method doesn't return null, then parents
81              * are not searched
82              */

83             obj = null;
84         }
85         return obj;
86     }
87     
88     public Enumeration JavaDoc getKeys() {
89         Enumeration JavaDoc myKeys = resourceBundle.getKeys();
90         if (parent == null) {
91             return myKeys;
92         } else {
93             final HashSet JavaDoc set = new HashSet JavaDoc();
94             while (myKeys.hasMoreElements()) {
95                 set.add(myKeys.nextElement());
96             }
97             
98             Enumeration JavaDoc pKeys = parent.getKeys();
99             while (pKeys.hasMoreElements()) {
100                 set.add(pKeys.nextElement());
101             }
102             
103             return new Enumeration JavaDoc() {
104                     private Iterator JavaDoc it = set.iterator();
105                     public boolean hasMoreElements() { return it.hasNext(); }
106                     public Object JavaDoc nextElement() { return it.next(); }
107                 };
108         }
109     }
110     
111
112     /**
113      * Construct a new ProjectResourceBundle
114      *
115      * @param projectName The name of the project to which the class belongs.
116      * It must be a proper prefix of the caller's package.
117      *
118      * @param caller The calling class.
119      * This is used to get the package name to further construct
120      * the basename as well as to get the proper ClassLoader.
121      *
122      * @param resourceName The name of the resource without the
123      * ".properties" extension
124      *
125      * @throws MissingResourceException if projectName is not a prefix of
126      * the caller's package name, or if the resource could not be
127      * found/loaded.
128      */

129     public static ProjectResourceBundle getBundle(String JavaDoc projectName,
130                                                   String JavaDoc packageName,
131                                                   String JavaDoc resourceName)
132         throws MissingResourceException JavaDoc
133     {
134         return getBundle(projectName, packageName, resourceName, null, null, null);
135     }
136
137     /**
138      * Construct a new ProjectResourceBundle
139      *
140      * @param projectName The name of the project to which the class belongs.
141      * It must be a proper prefix of the caller's package.
142      *
143      * @param caller The calling class.
144      * This is used to get the package name to further construct
145      * the basename as well as to get the proper ClassLoader.
146      *
147      * @param resourceName The name of the resource without the
148      * ".properties" extension
149      *
150      * @throws MissingResourceException if projectName is not a prefix of
151      * the caller's package name, or if the resource could not be
152      * found/loaded.
153      */

154     public static ProjectResourceBundle getBundle(String JavaDoc projectName,
155                                                   Class JavaDoc caller,
156                                                   String JavaDoc resourceName,
157                                                   Locale JavaDoc locale)
158         throws MissingResourceException JavaDoc
159     {
160         return getBundle(projectName,
161                          caller,
162                          resourceName,
163                          locale,
164                          null);
165     }
166
167     /**
168      * Construct a new ProjectResourceBundle
169      *
170      * @param projectName The name of the project to which the class belongs.
171      * It must be a proper prefix of the caller's package.
172      *
173      * @param caller The calling class.
174      * This is used to get the package name to further construct
175      * the basename as well as to get the proper ClassLoader.
176      *
177      * @param resourceName The name of the resource without the
178      * ".properties" extension
179      *
180      * @param locale The locale
181      *
182      * @throws MissingResourceException if projectName is not a prefix of
183      * the caller's package name, or if the resource could not be
184      * found/loaded.
185      */

186     public static ProjectResourceBundle getBundle(String JavaDoc projectName,
187                                                   String JavaDoc packageName,
188                                                   String JavaDoc resourceName,
189                                                   Locale JavaDoc locale,
190                                                   ClassLoader JavaDoc loader)
191         throws MissingResourceException JavaDoc
192     {
193         return getBundle(projectName, packageName, resourceName, locale, loader, null);
194     }
195
196     /**
197      * Construct a new ProjectResourceBundle
198      *
199      * @param projectName The name of the project to which the class belongs.
200      * It must be a proper prefix of the caller's package.
201      *
202      * @param caller The calling class.
203      * This is used to get the package name to further construct
204      * the basename as well as to get the proper ClassLoader.
205      *
206      * @param resourceName The name of the resource without the
207      * ".properties" extension
208      *
209      * @param locale The locale
210      *
211      * @param extendsBundle If non-null, then this ExtendMessages will
212      * default to extendsBundle.
213      *
214      * @throws MissingResourceException if projectName is not a prefix of
215      * the caller's package name, or if the resource could not be
216      * found/loaded.
217      */

218     public static ProjectResourceBundle getBundle(String JavaDoc projectName,
219                                                   Class JavaDoc caller,
220                                                   String JavaDoc resourceName,
221                                                   Locale JavaDoc locale,
222                                                   ResourceBundle JavaDoc extendsBundle)
223         throws MissingResourceException JavaDoc
224     {
225         return getBundle(projectName,
226                          getPackage(caller.getClass().getName()),
227                          resourceName,
228                          locale,
229                          caller.getClass().getClassLoader(),
230                          extendsBundle);
231     }
232
233     /**
234      * Construct a new ProjectResourceBundle
235      *
236      * @param projectName The name of the project to which the class belongs.
237      * It must be a proper prefix of the caller's package.
238      *
239      * @param caller The calling class.
240      * This is used to get the package name to further construct
241      * the basename as well as to get the proper ClassLoader.
242      *
243      * @param resourceName The name of the resource without the
244      * ".properties" extension
245      *
246      * @param locale The locale
247      *
248      * @param extendsBundle If non-null, then this ExtendMessages will
249      * default to extendsBundle.
250      *
251      * @throws MissingResourceException if projectName is not a prefix of
252      * the caller's package name, or if the resource could not be
253      * found/loaded.
254      */

255     public static ProjectResourceBundle getBundle(String JavaDoc projectName,
256                                                   String JavaDoc packageName,
257                                                   String JavaDoc resourceName,
258                                                   Locale JavaDoc locale,
259                                                   ClassLoader JavaDoc loader,
260                                                   ResourceBundle JavaDoc extendsBundle)
261         throws MissingResourceException JavaDoc
262     {
263         if (log.isDebugEnabled()) {
264             log.debug("getBundle(" + projectName + ","
265                                    + packageName + ","
266                                    + resourceName + ","
267                                    + String.valueOf(locale) + ",...)");
268         }
269         
270         Context context = new Context();
271         context.setLocale(locale);
272         context.setLoader(loader);
273         context.setProjectName(projectName);
274         context.setResourceName(resourceName);
275         context.setParentBundle(extendsBundle);
276
277         packageName = context.validate(packageName);
278
279         ProjectResourceBundle bundle = null;
280         try {
281             bundle = getBundle(context, packageName);
282         } catch (RuntimeException JavaDoc e) {
283             log.debug("Exception: ", e);
284             throw e;
285         }
286         
287         if (bundle == null) {
288             throw new MissingResourceException JavaDoc("Cannot find resource '" +
289                                                packageName + '.' + resourceName + "'",
290                                                resourceName, "");
291         }
292         
293         return bundle;
294     }
295
296     /**
297      * get bundle...
298      * - check cache
299      * - try up hierarchy
300      * - if at top of hierarchy, use (link to) context.getParentBundle()
301      */

302     private static synchronized ProjectResourceBundle getBundle(Context context, String JavaDoc packageName)
303         throws MissingResourceException JavaDoc
304     {
305         String JavaDoc cacheKey = context.getCacheKey(packageName);
306         
307         ProjectResourceBundle prb = (ProjectResourceBundle)bundleCache.get(cacheKey);
308
309         if (prb == null) {
310             String JavaDoc name = packageName + '.' + context.getResourceName();
311             ResourceBundle JavaDoc rb = context.loadBundle(packageName);
312             ResourceBundle JavaDoc parent = context.getParentBundle(packageName);
313             
314             if (rb != null) {
315                 prb = new ProjectResourceBundle(name, rb);
316                 prb.setParent(parent);
317                 if (log.isDebugEnabled()) {
318                     log.debug("Created " + prb + ", linked to parent " + String.valueOf(parent));
319                 }
320             } else {
321                 if (parent != null) {
322                     if (parent instanceof ProjectResourceBundle) {
323                         prb = (ProjectResourceBundle)parent;
324                     } else {
325                         prb = new ProjectResourceBundle(name, parent);
326                     }
327                     if (log.isDebugEnabled()) {
328                         log.debug("Root package not found, cross link to " + parent);
329                     }
330                 }
331             }
332
333             if (prb != null) {
334                 // Cache the resource
335
bundleCache.put(cacheKey, prb);
336             }
337         }
338
339         return prb;
340     }
341
342     private static final String JavaDoc getPackage(String JavaDoc name) {
343         return name.substring(0, name.lastIndexOf('.')).intern();
344     }
345     
346     /**
347       * Construct a new ProjectResourceBundle
348       */

349     private ProjectResourceBundle(String JavaDoc name, ResourceBundle JavaDoc bundle)
350         throws MissingResourceException JavaDoc
351     {
352         this.resourceBundle = bundle;
353         this.resourceName = name;
354     }
355     
356     public String JavaDoc getResourceName() {
357         return resourceName;
358     }
359
360     /**
361      * Clears the internal cache
362      */

363     public static void clearCache()
364     {
365         bundleCache.clear();
366     }
367     
368     public String JavaDoc toString() {
369         return resourceName;
370     }
371
372
373     private static class Context {
374         private Locale JavaDoc _locale;
375         private ClassLoader JavaDoc _loader;
376         private String JavaDoc _projectName;
377         private String JavaDoc _resourceName;
378         private ResourceBundle JavaDoc _parent;
379         
380         void setLocale(Locale JavaDoc l) {
381             /* 1. Docs indicate that if locale is not specified,
382              * then the default local is used in it's place.
383              * 2. A null value for locale is invalid.
384              *
385              * Therefore, default...
386              */

387             _locale = (l == null) ? defaultLocale : l;
388         }
389
390         void setLoader(ClassLoader JavaDoc l) {
391             _loader = (l != null) ? l : this.getClass().getClassLoader();
392             // START FIX: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16868
393
if (_loader == null) {
394                 _loader = ClassLoader.getSystemClassLoader();
395             }
396             // END FIX: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16868
397
}
398         
399         void setProjectName(String JavaDoc name) { _projectName = name.intern(); }
400         void setResourceName(String JavaDoc name) { _resourceName = name.intern(); }
401         void setParentBundle(ResourceBundle JavaDoc b) { _parent = b; }
402         
403         Locale JavaDoc getLocale() { return _locale; }
404         ClassLoader JavaDoc getLoader() { return _loader; }
405         String JavaDoc getProjectName() { return _projectName; }
406         String JavaDoc getResourceName() { return _resourceName; }
407         ResourceBundle JavaDoc getParentBundle() { return _parent; }
408     
409         String JavaDoc getCacheKey(String JavaDoc packageName)
410         {
411             String JavaDoc loaderName = (_loader == null) ? "" : (":" + _loader.hashCode());
412             return packageName + "." + _resourceName + ":" + _locale + ":" + defaultLocale + loaderName;
413         }
414
415         ResourceBundle JavaDoc loadBundle(String JavaDoc packageName)
416         {
417             try {
418                 return ResourceBundle.getBundle(packageName + '.' + _resourceName,
419                                                 _locale,
420                                                 _loader);
421             } catch (MissingResourceException JavaDoc e) {
422                 // Deliberately surpressing print stack.. just the string for info.
423
log.debug("loadBundle: Ignoring MissingResourceException: " + e.getMessage());
424             }
425             return null;
426         }
427     
428         ResourceBundle JavaDoc getParentBundle(String JavaDoc packageName)
429         {
430             ResourceBundle JavaDoc p;
431             if (packageName != _projectName) {
432                 p = getBundle(this, getPackage(packageName));
433             } else {
434                 p = _parent;
435                 _parent = null;
436             }
437             return p;
438         }
439         
440         String JavaDoc validate(String JavaDoc packageName)
441             throws MissingResourceException JavaDoc
442         {
443             if (_projectName == null || _projectName.length() == 0) {
444                 log.debug("Project name not specified");
445                 throw new MissingResourceException JavaDoc("Project name not specified",
446                                                    "", "");
447             }
448
449             if (packageName == null || packageName.length() == 0) {
450                 log.debug("Package name not specified");
451                 throw new MissingResourceException JavaDoc("Package not specified",
452                                                    packageName, "");
453             }
454             packageName = packageName.intern();
455     
456             /* Ensure that project is a proper prefix of class.
457              * Terminate project name with '.' to ensure proper match.
458              */

459             if (packageName != _projectName && !packageName.startsWith(_projectName + '.')) {
460                 log.debug("Project not a prefix of Package");
461                 throw new MissingResourceException JavaDoc("Project '" + _projectName
462                                  + "' must be a prefix of Package '"
463                                  + packageName + "'",
464                                  packageName + '.' + _resourceName, "");
465             }
466                 
467             return packageName;
468         }
469     }
470 }
471
Popular Tags