KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55
56 package org.jboss.axis.i18n;
57
58 import org.jboss.logging.Logger;
59
60 import java.util.Enumeration JavaDoc;
61 import java.util.HashSet JavaDoc;
62 import java.util.Hashtable JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.Locale JavaDoc;
65 import java.util.MissingResourceException JavaDoc;
66 import java.util.ResourceBundle JavaDoc;
67
68 /**
69  * <p>Wrapper class for resource bundles. Property files are used to store
70  * resource strings, which are the only types of resources available.
71  * Property files can inherit properties from other files so that
72  * a base property file can be used and a small number of properties
73  * can be over-ridden by another property file. For example you may
74  * create an english version of a resource file named "resource.properties".
75  * You then decide that the British English version of all of the properties
76  * except one are the same, so there is no need to redefine all of the
77  * properties in "resource_en_GB", just the one that is different.</p>
78  * <p>The basename is the name of the property file without the ".properties"
79  * extension.</p>
80  * <p>Properties will be cached for performance.<p>
81  * <p>Property values stored in the property files can also contain dynamic
82  * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
83  * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
84  * Argument values are specified in the various overloaded getString() methods.</p>
85  *
86  * @author Richard A. Sitze (rsitze@us.ibm.com)
87  * @author Karl Moss (kmoss@macromedia.com)
88  * @author Glen Daniels (gdaniels@macromedia.com)
89  */

90 public class ProjectResourceBundle extends ResourceBundle JavaDoc
91 {
92    private static Logger log = Logger.getLogger(ProjectResourceBundle.class);
93
94    // The static cache of ResourceBundles.
95
// The key is the 'basename + locale + default locale'
96
// The element is a ResourceBundle object
97
private static final Hashtable JavaDoc bundleCache = new Hashtable JavaDoc();
98
99    private static final Locale JavaDoc defaultLocale = Locale.getDefault();
100
101    private final ResourceBundle JavaDoc resourceBundle;
102    private final String JavaDoc resourceName;
103
104
105    protected Object JavaDoc handleGetObject(String JavaDoc key)
106            throws MissingResourceException JavaDoc
107    {
108       if (log.isTraceEnabled())
109          log.trace(this.toString() + "::handleGetObject(" + key + ")");
110
111       Object JavaDoc obj;
112       try
113       {
114          obj = resourceBundle.getObject(key);
115       }
116       catch (MissingResourceException JavaDoc e)
117       {
118          /* catch missing resource, ignore, & return null
119           * if this method doesn't return null, then parents
120           * are not searched
121           */

122          obj = null;
123       }
124       return obj;
125    }
126
127    public Enumeration JavaDoc getKeys()
128    {
129       Enumeration JavaDoc myKeys = resourceBundle.getKeys();
130       if (parent == null)
131       {
132          return myKeys;
133       }
134       else
135       {
136          final HashSet JavaDoc set = new HashSet JavaDoc();
137          while (myKeys.hasMoreElements())
138          {
139             set.add(myKeys.nextElement());
140          }
141
142          Enumeration JavaDoc pKeys = parent.getKeys();
143          while (pKeys.hasMoreElements())
144          {
145             set.add(pKeys.nextElement());
146          }
147
148          return new Enumeration JavaDoc()
149          {
150             private Iterator JavaDoc it = set.iterator();
151
152             public boolean hasMoreElements()
153             {
154                return it.hasNext();
155             }
156
157             public Object JavaDoc nextElement()
158             {
159                return it.next();
160             }
161          };
162       }
163    }
164
165
166    /**
167     * Construct a new ProjectResourceBundle
168     *
169     * @param projectName The name of the project to which the class belongs.
170     * It must be a proper prefix of the caller's package.
171     * @param resourceName The name of the resource without the ".properties" extension
172     * @throws MissingResourceException if projectName is not a prefix of
173     * the caller's package name, or if the resource could not be
174     * found/loaded.
175     */

176    public static ProjectResourceBundle getBundle(String JavaDoc projectName,
177                                                  String JavaDoc packageName,
178                                                  String JavaDoc resourceName)
179            throws MissingResourceException JavaDoc
180    {
181       return getBundle(projectName, packageName, resourceName, null, null, null);
182    }
183
184    /**
185     * Construct a new ProjectResourceBundle
186     *
187     * @param projectName The name of the project to which the class belongs.
188     * It must be a proper prefix of the caller's package.
189     * @param caller The calling class.
190     * This is used to get the package name to further construct
191     * the basename as well as to get the proper ClassLoader.
192     * @param resourceName The name of the resource without the
193     * ".properties" extension
194     * @throws MissingResourceException if projectName is not a prefix of
195     * the caller's package name, or if the resource could not be
196     * found/loaded.
197     */

198    public static ProjectResourceBundle getBundle(String JavaDoc projectName,
199                                                  Class JavaDoc caller,
200                                                  String JavaDoc resourceName,
201                                                  Locale JavaDoc locale)
202            throws MissingResourceException JavaDoc
203    {
204       return getBundle(projectName,
205               caller,
206               resourceName,
207               locale,
208               null);
209    }
210
211    /**
212     * Construct a new ProjectResourceBundle
213     *
214     * @param projectName The name of the project to which the class belongs.
215     * It must be a proper prefix of the caller's package.
216     * @param resourceName The name of the resource without the
217     * ".properties" extension
218     * @param locale The locale
219     * @throws MissingResourceException if projectName is not a prefix of
220     * the caller's package name, or if the resource could not be
221     * found/loaded.
222     */

223    public static ProjectResourceBundle getBundle(String JavaDoc projectName,
224                                                  String JavaDoc packageName,
225                                                  String JavaDoc resourceName,
226                                                  Locale JavaDoc locale,
227                                                  ClassLoader JavaDoc loader)
228            throws MissingResourceException JavaDoc
229    {
230       return getBundle(projectName, packageName, resourceName, locale, loader, null);
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     * @param caller The calling class.
239     * This is used to get the package name to further construct
240     * the basename as well as to get the proper ClassLoader.
241     * @param resourceName The name of the resource without the
242     * ".properties" extension
243     * @param locale The locale
244     * @param extendsBundle If non-null, then this ExtendMessages will
245     * default to extendsBundle.
246     * @throws MissingResourceException if projectName is not a prefix of
247     * the caller's package name, or if the resource could not be
248     * found/loaded.
249     */

250    public static ProjectResourceBundle getBundle(String JavaDoc projectName,
251                                                  Class JavaDoc caller,
252                                                  String JavaDoc resourceName,
253                                                  Locale JavaDoc locale,
254                                                  ResourceBundle JavaDoc extendsBundle)
255            throws MissingResourceException JavaDoc
256    {
257       return getBundle(projectName,
258               getPackage(caller.getClass().getName()),
259               resourceName,
260               locale,
261               caller.getClass().getClassLoader(),
262               extendsBundle);
263    }
264
265    /**
266     * Construct a new ProjectResourceBundle
267     *
268     * @param projectName The name of the project to which the class belongs.
269     * It must be a proper prefix of the caller's package.
270     * @param resourceName The name of the resource without the
271     * ".properties" extension
272     * @param locale The locale
273     * @param extendsBundle If non-null, then this ExtendMessages will
274     * default to extendsBundle.
275     * @throws MissingResourceException if projectName is not a prefix of
276     * the caller's package name, or if the resource could not be
277     * found/loaded.
278     */

279    public static ProjectResourceBundle getBundle(String JavaDoc projectName,
280                                                  String JavaDoc packageName,
281                                                  String JavaDoc resourceName,
282                                                  Locale JavaDoc locale,
283                                                  ClassLoader JavaDoc loader,
284                                                  ResourceBundle JavaDoc extendsBundle)
285            throws MissingResourceException JavaDoc
286    {
287       if (log.isDebugEnabled())
288          log.debug("getBundle(" + projectName + "," + packageName + "," + resourceName + "," + String.valueOf(locale) + ",...)");
289
290       Context context = new Context();
291       context.setLocale(locale);
292       context.setLoader(loader);
293       context.setProjectName(projectName);
294       context.setResourceName(resourceName);
295       context.setParentBundle(extendsBundle);
296
297       packageName = context.validate(packageName);
298
299       ProjectResourceBundle bundle = null;
300       bundle = getBundle(context, packageName);
301
302       if (bundle == null)
303       {
304          throw new MissingResourceException JavaDoc("Cannot find resource '" +
305                  packageName + '.' + resourceName + "'",
306                  resourceName, "");
307       }
308
309       return bundle;
310    }
311
312    /**
313     * get bundle...
314     * - check cache
315     * - try up hierarchy
316     * - if at top of hierarchy, use (link to) context.getParentBundle()
317     */

318    private static synchronized ProjectResourceBundle getBundle(Context context, String JavaDoc packageName)
319            throws MissingResourceException JavaDoc
320    {
321       String JavaDoc cacheKey = context.getCacheKey(packageName);
322
323       ProjectResourceBundle prb = (ProjectResourceBundle)bundleCache.get(cacheKey);
324
325       if (prb == null)
326       {
327          String JavaDoc name = packageName + '.' + context.getResourceName();
328          ResourceBundle JavaDoc rb = context.loadBundle(packageName);
329          ResourceBundle JavaDoc parent = context.getParentBundle(packageName);
330
331          if (rb != null)
332          {
333             prb = new ProjectResourceBundle(name, rb);
334             prb.setParent(parent);
335
336             if (log.isDebugEnabled())
337                log.debug("Created " + prb + ", linked to parent " + String.valueOf(parent));
338          }
339          else
340          {
341             if (parent != null)
342             {
343                if (parent instanceof ProjectResourceBundle)
344                {
345                   prb = (ProjectResourceBundle)parent;
346                }
347                else
348                {
349                   prb = new ProjectResourceBundle(name, parent);
350                }
351
352                if (log.isDebugEnabled())
353                   log.debug("Root package not found, cross link to " + parent);
354             }
355          }
356
357          if (prb != null)
358          {
359             // Cache the resource
360
bundleCache.put(cacheKey, prb);
361          }
362       }
363
364       return prb;
365    }
366
367    private static final String JavaDoc getPackage(String JavaDoc name)
368    {
369       return name.substring(0, name.lastIndexOf('.')).intern();
370    }
371
372    /**
373     * Construct a new ProjectResourceBundle
374     */

375    private ProjectResourceBundle(String JavaDoc name, ResourceBundle JavaDoc bundle)
376            throws MissingResourceException JavaDoc
377    {
378       this.resourceBundle = bundle;
379       this.resourceName = name;
380    }
381
382    public String JavaDoc getResourceName()
383    {
384       return resourceName;
385    }
386
387    /**
388     * Clears the internal cache
389     */

390    public static void clearCache()
391    {
392       bundleCache.clear();
393    }
394
395    public String JavaDoc toString()
396    {
397       return resourceName;
398    }
399
400
401    private static class Context
402    {
403       private Locale JavaDoc _locale;
404       private ClassLoader JavaDoc _loader;
405       private String JavaDoc _projectName;
406       private String JavaDoc _resourceName;
407       private ResourceBundle JavaDoc _parent;
408
409       void setLocale(Locale JavaDoc l)
410       {
411          /* 1. Docs indicate that if locale is not specified,
412           * then the default local is used in it's place.
413           * 2. A null value for locale is invalid.
414           *
415           * Therefore, default...
416           */

417          _locale = (l == null) ? defaultLocale : l;
418       }
419
420       void setLoader(ClassLoader JavaDoc l)
421       {
422          _loader = (l != null) ? l : this.getClass().getClassLoader();
423          // START FIX: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16868
424
if (_loader == null)
425          {
426             _loader = ClassLoader.getSystemClassLoader();
427          }
428          // END FIX: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16868
429
}
430
431       void setProjectName(String JavaDoc name)
432       {
433          _projectName = name.intern();
434       }
435
436       void setResourceName(String JavaDoc name)
437       {
438          _resourceName = name.intern();
439       }
440
441       void setParentBundle(ResourceBundle JavaDoc b)
442       {
443          _parent = b;
444       }
445
446       Locale JavaDoc getLocale()
447       {
448          return _locale;
449       }
450
451       ClassLoader JavaDoc getLoader()
452       {
453          return _loader;
454       }
455
456       String JavaDoc getProjectName()
457       {
458          return _projectName;
459       }
460
461       String JavaDoc getResourceName()
462       {
463          return _resourceName;
464       }
465
466       ResourceBundle JavaDoc getParentBundle()
467       {
468          return _parent;
469       }
470
471       String JavaDoc getCacheKey(String JavaDoc packageName)
472       {
473          String JavaDoc loaderName = (_loader == null) ? "" : (":" + _loader.hashCode());
474          return packageName + "." + _resourceName + ":" + _locale + ":" + defaultLocale + loaderName;
475       }
476
477       ResourceBundle JavaDoc loadBundle(String JavaDoc packageName)
478       {
479          try
480          {
481             return ResourceBundle.getBundle(packageName + '.' + _resourceName,
482                     _locale,
483                     _loader);
484          }
485          catch (MissingResourceException JavaDoc e)
486          {
487             // Deliberately surpressing print stack.. just the string for info.
488
log.debug("loadBundle: Ignoring MissingResourceException: " + e.getMessage());
489          }
490          return null;
491       }
492
493       ResourceBundle JavaDoc getParentBundle(String JavaDoc packageName)
494       {
495          ResourceBundle JavaDoc p;
496          if (packageName != _projectName)
497          {
498             p = getBundle(this, getPackage(packageName));
499          }
500          else
501          {
502             p = _parent;
503             _parent = null;
504          }
505          return p;
506       }
507
508       String JavaDoc validate(String JavaDoc packageName)
509               throws MissingResourceException JavaDoc
510       {
511          if (_projectName == null || _projectName.length() == 0)
512          {
513             throw new MissingResourceException JavaDoc("Project name not specified",
514                     "", "");
515          }
516
517          if (packageName == null || packageName.length() == 0)
518          {
519             throw new MissingResourceException JavaDoc("Package not specified",
520                     packageName, "");
521          }
522          packageName = packageName.intern();
523
524          /* Ensure that project is a proper prefix of class.
525           * Terminate project name with '.' to ensure proper match.
526           */

527          if (packageName != _projectName && !packageName.startsWith(_projectName + '.'))
528          {
529             throw new MissingResourceException JavaDoc("Project '" + _projectName
530                     + "' must be a prefix of Package '"
531                     + packageName + "'",
532                     packageName + '.' + _resourceName, "");
533          }
534
535          return packageName;
536       }
537    }
538 }
539
Popular Tags