Source code: org/apache/axis/i18n/RB.java
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 java.io.IOException;
20 import java.io.InputStream;
21 import java.text.MessageFormat;
22 import java.util.Enumeration;
23 import java.util.Hashtable;
24 import java.util.Locale;
25 import java.util.MissingResourceException;
26 import java.util.Properties;
27
28 /**
29 * CURRENTLY NOT USED
30 * KEEPING FOR REFERENCE 9/19/2002
31 *
32 * <p>Wrapper class for resource bundles. Property files are used to store
33 * resource strings, which are the only types of resources available.
34 * Property files can inherit properties from other files so that
35 * a base property file can be used and a small number of properties
36 * can be over-ridden by another property file. For example you may
37 * create an english version of a resource file named "resource.properties".
38 * You then decide that the British English version of all of the properties
39 * except one are the same, so there is no need to redefine all of the
40 * properties in "resource_en_GB", just the one that is different.</p>
41 * <p>The property file lookup searches for classes with various suffixes
42 * on the basis if the desired local and the current default local
43 * (as returned by Local.getDefault()). As property files are found the
44 * property values are merged so that inheritance is preserved.</p>
45 * <p>The order of searching is:</p>
46 * <dir>
47 * basename + "_" + langage + "_" + country + "_" + variant
48 * basename + "_" + langage + "_" + country
49 * basename + "_" + langage
50 * basename + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant
51 * basename + "_" + defaultLanguage + "_" + defaultCountry
52 * basename + "_" + defaultLanguage
53 * basename
54 * </dir>
55 * <p>The basename is the name of the property file without the ".properties"
56 * extension.</p>
57 * <p>Properties will be cached for performance.<p>
58 * <p>Property values stored in the property files can also contain dynamic
59 * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
60 * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
61 * Argument values are specified in the various overloaded getString() methods.</p>
62 *
63 * @author Karl Moss (kmoss@macromedia.com)
64 * @author Glen Daniels (gdaniels@apache.org)
65 */
66 public class RB {
67 // The static cache of properties. The key is the basename + the local +
68 // the default local and the element is the Properties object containing
69 // the resources
70 static Hashtable propertyCache = new Hashtable();
71
72 // The default base name
73 public static final String BASE_NAME = "resource";
74
75 // The property file extension
76 public static final String PROPERTY_EXT = ".properties";
77
78 // The name of the current base property file (with extension)
79 protected String basePropertyFileName;
80
81 // The properties for the current resource bundle
82 protected Properties resourceProperties;
83
84 /**
85 * Construct a new RB
86 * @param name The name of the property file without the ".properties" extension
87 */
88 public RB(String name) throws MissingResourceException
89 {
90 this(null, name, null);
91 }
92
93 /**
94 * Construct a new RB
95 * @param caller The calling object. This is used to get the package name
96 * to further construct the basename as well as to get the proper ClassLoader
97 * @param name The name of the property file without the ".properties" extension
98 */
99 public RB(Object caller, String name) throws MissingResourceException
100 {
101 this(caller, name, null);
102 }
103
104 /**
105 * Construct a new RB
106 * @param caller The calling object. This is used to get the package name
107 * to further construct the basename as well as to get the proper ClassLoader
108 * @param name The name of the property file without the ".properties" extension
109 * @param local The local
110 */
111 public RB(Object caller, String name, Locale locale) throws MissingResourceException
112 {
113 ClassLoader cl = null;
114
115 if (caller != null) {
116
117 Class c;
118 if (caller instanceof Class) {
119 c = (Class) caller;
120 }
121 else {
122 c = caller.getClass();
123 }
124
125 // Get the appropriate class loader
126 cl = c.getClassLoader();
127
128 if (name.indexOf("/") == -1) {
129
130 // Create the full basename only if not given
131 String fullName = c.getName();
132
133 int pos = fullName.lastIndexOf(".");
134 if (pos > 0) {
135 name = fullName.substring(0, pos + 1).replace('.', '/') + name;
136 }
137 }
138 } else {
139 // Try the shared default properties file...
140 if (name.indexOf("/") == -1) {
141 name = "org/apache/axis/default-resource";
142 }
143 }
144
145 Locale defaultLocale = Locale.getDefault();
146
147 // If the locale given is the same as the default locale, ignore it
148 if (locale != null) {
149 if (locale.equals(defaultLocale)) {
150 locale = null;
151 }
152 }
153
154 // Load the properties. If no property files exist then a
155 // MissingResourceException will be thrown
156 loadProperties(name, cl, locale, defaultLocale);
157 }
158
159 /**
160 * Gets a string message from the resource bundle for the given key
161 * @param key The resource key
162 * @return The message
163 */
164 public String getString(String key) throws MissingResourceException
165 {
166 return getString(key, (Object[]) null);
167 }
168
169 /**
170 * <p>Gets a string message from the resource bundle for the given key. The
171 * message may contain variables that will be substituted with the given
172 * arguments. Variables have the format:</p>
173 * <dir>
174 * This message has two variables: {0} and {1}
175 * </dir>
176 * @param key The resource key
177 * @param arg0 The argument to place in variable {0}
178 * @return The message
179 */
180 public String getString(String key, Object arg0) throws MissingResourceException
181 {
182 Object[] o = new Object[1];
183 o[0] = arg0;
184 return getString(key, o);
185 }
186
187 /**
188 * <p>Gets a string message from the resource bundle for the given key. The
189 * message may contain variables that will be substituted with the given
190 * arguments. Variables have the format:</p>
191 * <dir>
192 * This message has two variables: {0} and {1}
193 * </dir>
194 * @param key The resource key
195 * @param arg0 The argument to place in variable {0}
196 * @param arg1 The argument to place in variable {1}
197 * @return The message
198 */
199 public String getString(String key, Object arg0, Object arg1) throws MissingResourceException
200 {
201 Object[] o = new Object[2];
202 o[0] = arg0;
203 o[1] = arg1;
204 return getString(key, o);
205 }
206
207 /**
208 * <p>Gets a string message from the resource bundle for the given key. The
209 * message may contain variables that will be substituted with the given
210 * arguments. Variables have the format:</p>
211 * <dir>
212 * This message has two variables: {0} and {1}
213 * </dir>
214 * @param key The resource key
215 * @param arg0 The argument to place in variable {0}
216 * @param arg1 The argument to place in variable {1}
217 * @param arg2 The argument to place in variable {1}
218 * @return The message
219 */
220 public String getString(String key, Object arg0, Object arg1, Object arg2) throws MissingResourceException
221 {
222 Object[] o = new Object[3];
223 o[0] = arg0;
224 o[1] = arg1;
225 o[2] = arg2;
226 return getString(key, o);
227 }
228
229 /**
230 * <p>Gets a string message from the resource bundle for the given key. The
231 * message may contain variables that will be substituted with the given
232 * arguments. Variables have the format:</p>
233 * <dir>
234 * This message has two variables: {0} and {1}
235 * </dir>
236 * @param key The resource key
237 * @param array An array of objects to place in corresponding variables
238 * @return The message
239 */
240 public String getString(String key, Object[] array) throws MissingResourceException
241 {
242 String msg = null;
243 if (resourceProperties != null) {
244 msg = resourceProperties.getProperty(key);
245 }
246
247 if (msg == null) {
248 throw new MissingResourceException("Cannot find resource key \"" + key +
249 "\" in base name " + basePropertyFileName,
250 basePropertyFileName, key);
251 }
252
253 msg = MessageFormat.format(msg, array);
254 return msg;
255 }
256
257 protected void loadProperties(String basename, ClassLoader loader, Locale locale,
258 Locale defaultLocale)
259 throws MissingResourceException
260 {
261 // Check the cache first
262 String loaderName = "";
263 if (loader != null) {
264 loaderName = ":" + loader.hashCode();
265 }
266 String cacheKey = basename + ":" + locale + ":" + defaultLocale + loaderName;
267 Properties p = (Properties) propertyCache.get(cacheKey);
268 basePropertyFileName = basename + PROPERTY_EXT;
269
270 if (p == null) {
271 // The properties were not found in the cache. Search the given locale
272 // first
273 if (locale != null) {
274 p = loadProperties(basename, loader, locale, p);
275 }
276
277 // Search the default locale
278 if (defaultLocale != null) {
279 p = loadProperties(basename, loader, defaultLocale, p);
280 }
281
282 // Search for the basename
283 p = merge(p, loadProperties(basePropertyFileName, loader));
284
285 if (p == null) {
286 throw new MissingResourceException("Cannot find resource for base name " +
287 basePropertyFileName, basePropertyFileName, "");
288 }
289
290 // Cache the properties
291 propertyCache.put(cacheKey, p);
292
293 }
294
295 resourceProperties = p;
296 }
297
298 protected Properties loadProperties(String basename, ClassLoader loader, Locale locale,
299 Properties props)
300 {
301
302 String language = locale.getLanguage();
303 String country = locale.getCountry();
304 String variant = locale.getVariant();
305 if (variant != null) {
306 if (variant.trim().length() == 0) {
307 variant = null;
308 }
309 }
310
311 if (language != null) {
312
313 if (country != null) {
314
315 if (variant != null) {
316 props = merge(props, loadProperties(basename + "_" + language +"_" + country + "_" + variant +
317 PROPERTY_EXT, loader));
318 }
319 props = merge(props, loadProperties(basename + "_" + language +"_" + country +
320 PROPERTY_EXT, loader));
321 }
322 props = merge(props, loadProperties(basename + "_" + language + PROPERTY_EXT, loader));
323 }
324 return props;
325 }
326
327 protected Properties loadProperties(String resname, ClassLoader loader)
328 {
329 Properties props = null;
330
331 // Attempt to open and load the properties
332 InputStream in = null;
333 try {
334 if (loader != null) {
335 in = loader.getResourceAsStream(resname);
336 }
337
338 // Either we're using the system class loader or we didn't find the
339 // resource using the given class loader
340 if (in == null) {
341 in = ClassLoader.getSystemResourceAsStream(resname);
342 }
343 if (in != null) {
344 props = new Properties();
345 try {
346 props.load(in);
347 }
348 catch (IOException ex) {
349 // On error, clear the props
350 props = null;
351 }
352 }
353 }
354 finally {
355 if (in != null) {
356 try {
357 in.close();
358 }
359 catch (Exception ex) {
360 // Ignore error on close
361 }
362 }
363 }
364 return props;
365 }
366
367 /**
368 * Merge two Properties objects
369 */
370 protected Properties merge(Properties p1, Properties p2)
371 {
372 if ((p1 == null) &&
373 (p2 == null)) {
374 return null;
375 }
376 else if (p1 == null) {
377 return p2;
378 }
379 else if (p2 == null) {
380 return p1;
381 }
382
383 // Now merge. p1 takes precedence
384 Enumeration enumeration = p2.keys();
385 while (enumeration.hasMoreElements()) {
386 String key = (String) enumeration.nextElement();
387 if (p1.getProperty(key) == null) {
388 p1.put(key, p2.getProperty(key));
389 }
390 }
391
392 return p1;
393 }
394
395 /**
396 * Get the underlying properties
397 */
398 public Properties getProperties()
399 {
400 return resourceProperties;
401 }
402
403 // STATIC ACCESSORS
404
405 /**
406 * Get a message from resource.properties from the package of the given object.
407 * @param caller The calling object, used to get the package name and class loader
408 * @param key The resource key
409 * @return The formatted message
410 */
411 public static String getString(Object caller, String key)
412 throws MissingResourceException
413 {
414 return getMessage(caller, BASE_NAME, null, key, null);
415 }
416
417 /**
418 * Get a message from resource.properties from the package of the given object.
419 * @param caller The calling object, used to get the package name and class loader
420 * @param key The resource key
421 * @param arg0 The argument to place in variable {0}
422 * @return The formatted message
423 */
424 public static String getString(Object caller, String key, Object arg0)
425 throws MissingResourceException
426 {
427 Object[] o = new Object[1];
428 o[0] = arg0;
429 return getMessage(caller, BASE_NAME, null, key, o);
430 }
431
432 /**
433 * Get a message from resource.properties from the package of the given object.
434 * @param caller The calling object, used to get the package name and class loader
435 * @param key The resource key
436 * @param arg0 The argument to place in variable {0}
437 * @param arg1 The argument to place in variable {1}
438 * @return The formatted message
439 */
440 public static String getString(Object caller, String key, Object arg0, Object arg1)
441 throws MissingResourceException
442 {
443 Object[] o = new Object[2];
444 o[0] = arg0;
445 o[1] = arg1;
446 return getMessage(caller, BASE_NAME, null, key, o);
447 }
448
449 /**
450 * Get a message from resource.properties from the package of the given object.
451 * @param caller The calling object, used to get the package name and class loader
452 * @param key The resource key
453 * @param arg0 The argument to place in variable {0}
454 * @param arg1 The argument to place in variable {1}
455 * @param arg2 The argument to place in variable {2}
456 * @return The formatted message
457 */
458 public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2)
459 throws MissingResourceException
460 {
461 Object[] o = new Object[3];
462 o[0] = arg0;
463 o[1] = arg1;
464 o[2] = arg2;
465 return getMessage(caller, BASE_NAME, null, key, o);
466 }
467
468 /**
469 * Get a message from resource.properties from the package of the given object.
470 * @param caller The calling object, used to get the package name and class loader
471 * @param key The resource key
472 * @param arg0 The argument to place in variable {0}
473 * @param arg1 The argument to place in variable {1}
474 * @param arg2 The argument to place in variable {2}
475 * @param arg3 The argument to place in variable {3}
476 * @return The formatted message
477 */
478 public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3)
479 throws MissingResourceException
480 {
481 Object[] o = new Object[4];
482 o[0] = arg0;
483 o[1] = arg1;
484 o[2] = arg2;
485 o[3] = arg3;
486 return getMessage(caller, BASE_NAME, null, key, o);
487 }
488
489
490 /**
491 * Get a message from resource.properties from the package of the given object.
492 * @param caller The calling object, used to get the package name and class loader
493 * @param key The resource key
494 * @param arg0 The argument to place in variable {0}
495 * @param arg1 The argument to place in variable {1}
496 * @param arg2 The argument to place in variable {2}
497 * @param arg3 The argument to place in variable {3}
498 * @param arg4 The argument to place in variable {4}
499 * @return The formatted message
500 */
501 public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4)
502 throws MissingResourceException
503 {
504 Object[] o = new Object[5];
505 o[0] = arg0;
506 o[1] = arg1;
507 o[2] = arg2;
508 o[3] = arg3;
509 o[4] = arg4;
510 return getMessage(caller, BASE_NAME, null, key, o);
511 }
512
513
514 /**
515 * Get a message from resource.properties from the package of the given object.
516 * @param caller The calling object, used to get the package name and class loader
517 * @param key The resource key
518 * @param array An array of objects to place in corresponding variables
519 * @return The formatted message
520 */
521 public static String getString(Object caller, String key, Object[] args)
522 throws MissingResourceException
523 {
524 return getMessage(caller, BASE_NAME, null, key, args);
525 }
526
527
528 /**
529 * Get a message from resource.properties from the package of the given object.
530 * @param caller The calling object, used to get the package name and class loader
531 * @param locale The locale
532 * @param key The resource key
533 * @return The formatted message
534 */
535 public static String getString(Object caller, Locale locale, String key)
536 throws MissingResourceException
537 {
538 return getMessage(caller, BASE_NAME, locale, key, null);
539 }
540
541 /**
542 * Get a message from resource.properties from the package of the given object.
543 * @param caller The calling object, used to get the package name and class loader
544 * @param locale The locale
545 * @param key The resource key
546 * @param arg0 The argument to place in variable {0}
547 * @return The formatted message
548 */
549 public static String getString(Object caller, Locale locale, String key, Object arg0)
550 throws MissingResourceException
551 {
552 Object[] o = new Object[1];
553 o[0] = arg0;
554 return getMessage(caller, BASE_NAME, locale, key, o);
555 }
556
557 /**
558 * Get a message from resource.properties from the package of the given object.
559 * @param caller The calling object, used to get the package name and class loader
560 * @param locale The locale
561 * @param key The resource key
562 * @param arg0 The argument to place in variable {0}
563 * @param arg1 The argument to place in variable {1}
564 * @return The formatted message
565 */
566 public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1)
567 throws MissingResourceException
568 {
569 Object[] o = new Object[2];
570 o[0] = arg0;
571 o[1] = arg1;
572 return getMessage(caller, BASE_NAME, locale, key, o);
573 }
574
575 /**
576 * Get a message from resource.properties from the package of the given object.
577 * @param caller The calling object, used to get the package name and class loader
578 * @param locale The locale
579 * @param key The resource key
580 * @param arg0 The argument to place in variable {0}
581 * @param arg1 The argument to place in variable {1}
582 * @param arg2 The argument to place in variable {2}
583 * @return The formatted message
584 */
585 public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2)
586 throws MissingResourceException
587 {
588 Object[] o = new Object[3];
589 o[0] = arg0;
590 o[1] = arg1;
591 o[2] = arg2;
592 return getMessage(caller, BASE_NAME, locale, key, o);
593 }
594
595 /**
596 * Get a message from resource.properties from the package of the given object.
597 * @param caller The calling object, used to get the package name and class loader
598 * @param locale The locale
599 * @param key The resource key
600 * @param arg0 The argument to place in variable {0}
601 * @param arg1 The argument to place in variable {1}
602 * @param arg2 The argument to place in variable {2}
603 * @param arg3 The argument to place in variable {3}
604 * @return The formatted message
605 */
606 public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2, Object arg3)
607 throws MissingResourceException
608 {
609 Object[] o = new Object[4];
610 o[0] = arg0;
611 o[1] = arg1;
612 o[2] = arg2;
613 o[3] = arg3;
614 return getMessage(caller, BASE_NAME, locale, key, o);
615 }
616
617 /**
618 * Get a message from resource.properties from the package of the given object.
619 * @param caller The calling object, used to get the package name and class loader
620 * @param locale The locale
621 * @param key The resource key
622 * @param arg0 The argument to place in variable {0}
623 * @param arg1 The argument to place in variable {1}
624 * @param arg2 The argument to place in variable {2}
625 * @param arg3 The argument to place in variable {3}
626 * @return The formatted message
627 */
628 public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4)
629 throws MissingResourceException
630 {
631 Object[] o = new Object[5];
632 o[0] = arg0;
633 o[1] = arg1;
634 o[2] = arg2;
635 o[3] = arg3;
636 o[4] = arg4;
637 return getMessage(caller, BASE_NAME, locale, key, o);
638 }
639
640 /**
641 * Get a message from resource.properties from the package of the given object.
642 * @param caller The calling object, used to get the package name and class loader
643 * @param locale The locale
644 * @param key The resource key
645 * @param array An array of objects to place in corresponding variables
646 * @return The formatted message
647 */
648 public static String getString(Object caller, Locale locale, String key, Object[] args)
649 throws MissingResourceException
650 {
651 return getMessage(caller, BASE_NAME, locale, key, args);
652 }
653
654 // Workhorse that does the resource loading and key lookup
655 public static String getMessage(Object caller, String basename, Locale locale, String key,
656 Object[] args)
657 throws MissingResourceException
658 {
659 String msg = null;
660 MissingResourceException firstEx = null;
661 String fullName = null;
662 Class curClass = null;
663 boolean didNull = false;
664
665 if (caller != null) {
666 if(caller instanceof Class)
667 curClass = (Class) caller;
668 else
669 curClass = caller.getClass();
670 }
671
672 while (msg == null) {
673
674 // Get the full name of the resource
675 if (curClass != null) {
676
677 // Create the full basename
678 String pkgName = curClass.getName();
679
680 int pos = pkgName.lastIndexOf(".");
681 if (pos > 0) {
682 fullName = pkgName.substring(0, pos + 1).replace('.', '/') + basename;
683 }
684 else {
685 fullName = basename;
686 }
687 }
688 else {
689 fullName = basename;
690 }
691
692 try {
693 RB rb = new RB(caller, fullName, locale);
694 msg = rb.getString(key, args);
695 }
696 catch (MissingResourceException ex) {
697 if (curClass == null) {
698 throw ex;
699 }
700
701 // Save the first exception
702 if (firstEx == null) {
703 firstEx = ex;
704 }
705
706 // Get the superclass
707 curClass = curClass.getSuperclass();
708 if (curClass == null) {
709 if (didNull)
710 throw firstEx;
711 didNull = true;
712 caller = null;
713 } else {
714 String cname = curClass.getName();
715 if (cname.startsWith("java.") ||
716 cname.startsWith("javax.")) {
717 if (didNull)
718 throw firstEx;
719 didNull = true;
720 caller = null;
721 curClass = null;
722 }
723 }
724 }
725
726 }
727 return msg;
728 }
729
730 /**
731 * Clears the internal cache
732 */
733 public static void clearCache()
734 {
735 propertyCache.clear();
736 }
737 }