001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.jaxws.i18n;
021:
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.text.MessageFormat;
025: import java.util.Enumeration;
026: import java.util.Hashtable;
027: import java.util.Locale;
028: import java.util.MissingResourceException;
029: import java.util.Properties;
030:
031: /**
032: * CURRENTLY NOT USED KEEPING FOR REFERENCE 9/19/2002
033: * <p/>
034: * <p>Wrapper class for resource bundles. Property files are used to store resource strings, which
035: * are the only types of resources available. Property files can inherit properties from other files
036: * so that a base property file can be used and a small number of properties can be over-ridden by
037: * another property file. For example you may create an english version of a resource file named
038: * "resource.properties". You then decide that the British English version of all of the properties
039: * except one are the same, so there is no need to redefine all of the properties in
040: * "resource_en_GB", just the one that is different.</p> <p>The property file lookup searches for
041: * classes with various suffixes on the basis if the desired local and the current default local (as
042: * returned by Local.getDefault()). As property files are found the property values are merged so
043: * that inheritance is preserved.</p> <p>The order of searching is:</p> <dir> basename + "_" +
044: * langage + "_" + country + "_" + variant basename + "_" + langage + "_" + country basename + "_" +
045: * langage basename + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant basename +
046: * "_" + defaultLanguage + "_" + defaultCountry basename + "_" + defaultLanguage basename </dir>
047: * <p>The basename is the name of the property file without the ".properties" extension.</p>
048: * <p>Properties will be cached for performance.<p> <p>Property values stored in the property files
049: * can also contain dynamic variables. Any dynamic variable defined in
050: * PropertiesUtil.getVariableValue() can be used (such as {date}), as well as arguments in the form
051: * {0}, {1}, etc. Argument values are specified in the various overloaded getString() methods.</p>
052: */
053: public class RB {
054: // The static cache of properties. The key is the basename + the local +
055: // the default local and the element is the Properties object containing
056: // the resources
057: static Hashtable propertyCache = new Hashtable();
058:
059: // The default base name
060: public static final String BASE_NAME = "resource";
061:
062: // The property file extension
063: public static final String PROPERTY_EXT = ".properties";
064:
065: // The name of the current base property file (with extension)
066: protected String basePropertyFileName;
067:
068: // The properties for the current resource bundle
069: protected Properties resourceProperties;
070:
071: /**
072: * Construct a new RB
073: *
074: * @param name The name of the property file without the ".properties" extension
075: */
076: public RB(String name) throws MissingResourceException {
077: this (null, name, null);
078: }
079:
080: /**
081: * Construct a new RB
082: *
083: * @param caller The calling object. This is used to get the package name to further construct
084: * the basename as well as to get the proper ClassLoader
085: * @param name The name of the property file without the ".properties" extension
086: */
087: public RB(Object caller, String name)
088: throws MissingResourceException {
089: this (caller, name, null);
090: }
091:
092: /**
093: * Construct a new RB
094: *
095: * @param caller The calling object. This is used to get the package name to further construct
096: * the basename as well as to get the proper ClassLoader
097: * @param name The name of the property file without the ".properties" extension
098: * @param locale The locale
099: */
100: public RB(Object caller, String name, Locale locale)
101: throws MissingResourceException {
102: ClassLoader cl = null;
103:
104: if (caller != null) {
105:
106: Class c;
107: if (caller instanceof Class) {
108: c = (Class) caller;
109: } else {
110: c = caller.getClass();
111: }
112:
113: // Get the appropriate class loader
114: cl = c.getClassLoader();
115:
116: if (name.indexOf("/") == -1) {
117:
118: // Create the full basename only if not given
119: String fullName = c.getName();
120:
121: int pos = fullName.lastIndexOf(".");
122: if (pos > 0) {
123: name = fullName.substring(0, pos + 1).replace('.',
124: '/')
125: + name;
126: }
127: }
128: } else {
129: // Try the shared default properties file...
130: if (name.indexOf("/") == -1) {
131: name = "org/apache/axis2/default-resource";
132: }
133: }
134:
135: Locale defaultLocale = Locale.getDefault();
136:
137: // If the locale given is the same as the default locale, ignore it
138: if (locale != null) {
139: if (locale.equals(defaultLocale)) {
140: locale = null;
141: }
142: }
143:
144: // Load the properties. If no property files exist then a
145: // MissingResourceException will be thrown
146: loadProperties(name, cl, locale, defaultLocale);
147: }
148:
149: /**
150: * Gets a string message from the resource bundle for the given key
151: *
152: * @param key The resource key
153: * @return The message
154: */
155: public String getString(String key) throws MissingResourceException {
156: return getString(key, (Object[]) null);
157: }
158:
159: /**
160: * <p>Gets a string message from the resource bundle for the given key. The message may contain
161: * variables that will be substituted with the given arguments. Variables have the format:</p>
162: * <dir> This message has two variables: {0} and {1} </dir>
163: *
164: * @param key The resource key
165: * @param arg0 The argument to place in variable {0}
166: * @return The message
167: */
168: public String getString(String key, Object arg0)
169: throws MissingResourceException {
170: Object[] o = new Object[1];
171: o[0] = arg0;
172: return getString(key, o);
173: }
174:
175: /**
176: * <p>Gets a string message from the resource bundle for the given key. The message may contain
177: * variables that will be substituted with the given arguments. Variables have the format:</p>
178: * <dir> This message has two variables: {0} and {1} </dir>
179: *
180: * @param key The resource key
181: * @param arg0 The argument to place in variable {0}
182: * @param arg1 The argument to place in variable {1}
183: * @return The message
184: */
185: public String getString(String key, Object arg0, Object arg1)
186: throws MissingResourceException {
187: Object[] o = new Object[2];
188: o[0] = arg0;
189: o[1] = arg1;
190: return getString(key, o);
191: }
192:
193: /**
194: * <p>Gets a string message from the resource bundle for the given key. The message may contain
195: * variables that will be substituted with the given arguments. Variables have the format:</p>
196: * <dir> This message has two variables: {0} and {1} </dir>
197: *
198: * @param key The resource key
199: * @param arg0 The argument to place in variable {0}
200: * @param arg1 The argument to place in variable {1}
201: * @param arg2 The argument to place in variable {1}
202: * @return The message
203: */
204: public String getString(String key, Object arg0, Object arg1,
205: Object arg2) throws MissingResourceException {
206: Object[] o = new Object[3];
207: o[0] = arg0;
208: o[1] = arg1;
209: o[2] = arg2;
210: return getString(key, o);
211: }
212:
213: /**
214: * <p>Gets a string message from the resource bundle for the given key. The message may contain
215: * variables that will be substituted with the given arguments. Variables have the format:</p>
216: * <dir> This message has two variables: {0} and {1} </dir>
217: *
218: * @param key The resource key
219: * @param array An array of objects to place in corresponding variables
220: * @return The message
221: */
222: public String getString(String key, Object[] array)
223: throws MissingResourceException {
224: String msg = null;
225: if (resourceProperties != null) {
226: msg = resourceProperties.getProperty(key);
227: }
228:
229: if (msg == null) {
230: throw new MissingResourceException(
231: "Cannot find resource key \"" + key
232: + "\" in base name " + basePropertyFileName,
233: basePropertyFileName, key);
234: }
235:
236: msg = MessageFormat.format(msg, array);
237: return msg;
238: }
239:
240: protected void loadProperties(String basename, ClassLoader loader,
241: Locale locale, Locale defaultLocale)
242: throws MissingResourceException {
243: // Check the cache first
244: String loaderName = "";
245: if (loader != null) {
246: loaderName = ":" + loader.hashCode();
247: }
248: String cacheKey = basename + ":" + locale + ":" + defaultLocale
249: + loaderName;
250: Properties p = (Properties) propertyCache.get(cacheKey);
251: basePropertyFileName = basename + PROPERTY_EXT;
252:
253: if (p == null) {
254: // The properties were not found in the cache. Search the given locale
255: // first
256: if (locale != null) {
257: p = loadProperties(basename, loader, locale, p);
258: }
259:
260: // Search the default locale
261: if (defaultLocale != null) {
262: p = loadProperties(basename, loader, defaultLocale, p);
263: }
264:
265: // Search for the basename
266: p = merge(p, loadProperties(basePropertyFileName, loader));
267:
268: if (p == null) {
269: throw new MissingResourceException(
270: "Cannot find resource for base name "
271: + basePropertyFileName,
272: basePropertyFileName, "");
273: }
274:
275: // Cache the properties
276: propertyCache.put(cacheKey, p);
277:
278: }
279:
280: resourceProperties = p;
281: }
282:
283: protected Properties loadProperties(String basename,
284: ClassLoader loader, Locale locale, Properties props) {
285:
286: String language = locale.getLanguage();
287: String country = locale.getCountry();
288: String variant = locale.getVariant();
289: if (variant != null) {
290: if (variant.trim().length() == 0) {
291: variant = null;
292: }
293: }
294:
295: if (language != null) {
296:
297: if (country != null) {
298:
299: if (variant != null) {
300: props = merge(props, loadProperties(basename + "_"
301: + language + "_" + country + "_" + variant
302: + PROPERTY_EXT, loader));
303: }
304: props = merge(props, loadProperties(basename + "_"
305: + language + "_" + country + PROPERTY_EXT,
306: loader));
307: }
308: props = merge(props, loadProperties(basename + "_"
309: + language + PROPERTY_EXT, loader));
310: }
311: return props;
312: }
313:
314: protected Properties loadProperties(String resname,
315: ClassLoader loader) {
316: Properties props = null;
317:
318: // Attempt to open and load the properties
319: InputStream in = null;
320: try {
321: if (loader != null) {
322: in = loader.getResourceAsStream(resname);
323: }
324:
325: // Either we're using the system class loader or we didn't find the
326: // resource using the given class loader
327: if (in == null) {
328: in = ClassLoader.getSystemResourceAsStream(resname);
329: }
330: if (in != null) {
331: props = new Properties();
332: try {
333: props.load(in);
334: } catch (IOException ex) {
335: // On error, clear the props
336: props = null;
337: }
338: }
339: } finally {
340: if (in != null) {
341: try {
342: in.close();
343: } catch (Exception ex) {
344: // Ignore error on close
345: }
346: }
347: }
348: return props;
349: }
350:
351: /** Merge two Properties objects */
352: protected Properties merge(Properties p1, Properties p2) {
353: if ((p1 == null) && (p2 == null)) {
354: return null;
355: } else if (p1 == null) {
356: return p2;
357: } else if (p2 == null) {
358: return p1;
359: }
360:
361: // Now merge. p1 takes precedence
362: Enumeration enumeration = p2.keys();
363: while (enumeration.hasMoreElements()) {
364: String key = (String) enumeration.nextElement();
365: if (p1.getProperty(key) == null) {
366: p1.put(key, p2.getProperty(key));
367: }
368: }
369:
370: return p1;
371: }
372:
373: /** Get the underlying properties */
374: public Properties getProperties() {
375: return resourceProperties;
376: }
377:
378: // STATIC ACCESSORS
379:
380: /**
381: * Get a message from resource.properties from the package of the given object.
382: *
383: * @param caller The calling object, used to get the package name and class loader
384: * @param key The resource key
385: * @return The formatted message
386: */
387: public static String getString(Object caller, String key)
388: throws MissingResourceException {
389: return getMessage(caller, BASE_NAME, null, key, null);
390: }
391:
392: /**
393: * Get a message from resource.properties from the package of the given object.
394: *
395: * @param caller The calling object, used to get the package name and class loader
396: * @param key The resource key
397: * @param arg0 The argument to place in variable {0}
398: * @return The formatted message
399: */
400: public static String getString(Object caller, String key,
401: Object arg0) throws MissingResourceException {
402: Object[] o = new Object[1];
403: o[0] = arg0;
404: return getMessage(caller, BASE_NAME, null, key, o);
405: }
406:
407: /**
408: * Get a message from resource.properties from the package of the given object.
409: *
410: * @param caller The calling object, used to get the package name and class loader
411: * @param key The resource key
412: * @param arg0 The argument to place in variable {0}
413: * @param arg1 The argument to place in variable {1}
414: * @return The formatted message
415: */
416: public static String getString(Object caller, String key,
417: Object arg0, Object arg1) throws MissingResourceException {
418: Object[] o = new Object[2];
419: o[0] = arg0;
420: o[1] = arg1;
421: return getMessage(caller, BASE_NAME, null, key, o);
422: }
423:
424: /**
425: * Get a message from resource.properties from the package of the given object.
426: *
427: * @param caller The calling object, used to get the package name and class loader
428: * @param key The resource key
429: * @param arg0 The argument to place in variable {0}
430: * @param arg1 The argument to place in variable {1}
431: * @param arg2 The argument to place in variable {2}
432: * @return The formatted message
433: */
434: public static String getString(Object caller, String key,
435: Object arg0, Object arg1, Object arg2)
436: throws MissingResourceException {
437: Object[] o = new Object[3];
438: o[0] = arg0;
439: o[1] = arg1;
440: o[2] = arg2;
441: return getMessage(caller, BASE_NAME, null, key, o);
442: }
443:
444: /**
445: * Get a message from resource.properties from the package of the given object.
446: *
447: * @param caller The calling object, used to get the package name and class loader
448: * @param key The resource key
449: * @param arg0 The argument to place in variable {0}
450: * @param arg1 The argument to place in variable {1}
451: * @param arg2 The argument to place in variable {2}
452: * @param arg3 The argument to place in variable {3}
453: * @return The formatted message
454: */
455: public static String getString(Object caller, String key,
456: Object arg0, Object arg1, Object arg2, Object arg3)
457: throws MissingResourceException {
458: Object[] o = new Object[4];
459: o[0] = arg0;
460: o[1] = arg1;
461: o[2] = arg2;
462: o[3] = arg3;
463: return getMessage(caller, BASE_NAME, null, key, o);
464: }
465:
466: /**
467: * Get a message from resource.properties from the package of the given object.
468: *
469: * @param caller The calling object, used to get the package name and class loader
470: * @param key The resource key
471: * @param arg0 The argument to place in variable {0}
472: * @param arg1 The argument to place in variable {1}
473: * @param arg2 The argument to place in variable {2}
474: * @param arg3 The argument to place in variable {3}
475: * @param arg4 The argument to place in variable {4}
476: * @return Returns the formatted message.
477: */
478: public static String getString(Object caller, String key,
479: Object arg0, Object arg1, Object arg2, Object arg3,
480: Object arg4) throws MissingResourceException {
481: Object[] o = new Object[5];
482: o[0] = arg0;
483: o[1] = arg1;
484: o[2] = arg2;
485: o[3] = arg3;
486: o[4] = arg4;
487: return getMessage(caller, BASE_NAME, null, key, o);
488: }
489:
490: /**
491: * Get a message from resource.properties from the package of the given object.
492: *
493: * @param caller The calling object, used to get the package name and class loader
494: * @param key The resource key
495: * @param args An array of objects to place in corresponding variables
496: * @return Returns the formatted message.
497: */
498: public static String getString(Object caller, String key,
499: Object[] args) throws MissingResourceException {
500: return getMessage(caller, BASE_NAME, null, key, args);
501: }
502:
503: /**
504: * Get a message from resource.properties from the package of the given object.
505: *
506: * @param caller The calling object, used to get the package name and class loader
507: * @param locale The locale
508: * @param key The resource key
509: * @return The formatted message
510: */
511: public static String getString(Object caller, Locale locale,
512: String key) throws MissingResourceException {
513: return getMessage(caller, BASE_NAME, locale, key, null);
514: }
515:
516: /**
517: * Get a message from resource.properties from the package of the given object.
518: *
519: * @param caller The calling object, used to get the package name and class loader
520: * @param locale The locale
521: * @param key The resource key
522: * @param arg0 The argument to place in variable {0}
523: * @return The formatted message
524: */
525: public static String getString(Object caller, Locale locale,
526: String key, Object arg0) throws MissingResourceException {
527: Object[] o = new Object[1];
528: o[0] = arg0;
529: return getMessage(caller, BASE_NAME, locale, key, o);
530: }
531:
532: /**
533: * Get a message from resource.properties from the package of the given object.
534: *
535: * @param caller The calling object, used to get the package name and class loader
536: * @param locale The locale
537: * @param key The resource key
538: * @param arg0 The argument to place in variable {0}
539: * @param arg1 The argument to place in variable {1}
540: * @return The formatted message
541: */
542: public static String getString(Object caller, Locale locale,
543: String key, Object arg0, Object arg1)
544: throws MissingResourceException {
545: Object[] o = new Object[2];
546: o[0] = arg0;
547: o[1] = arg1;
548: return getMessage(caller, BASE_NAME, locale, key, o);
549: }
550:
551: /**
552: * Get a message from resource.properties from the package of the given object.
553: *
554: * @param caller The calling object, used to get the package name and class loader
555: * @param locale The locale
556: * @param key The resource key
557: * @param arg0 The argument to place in variable {0}
558: * @param arg1 The argument to place in variable {1}
559: * @param arg2 The argument to place in variable {2}
560: * @return The formatted message
561: */
562: public static String getString(Object caller, Locale locale,
563: String key, Object arg0, Object arg1, Object arg2)
564: throws MissingResourceException {
565: Object[] o = new Object[3];
566: o[0] = arg0;
567: o[1] = arg1;
568: o[2] = arg2;
569: return getMessage(caller, BASE_NAME, locale, key, o);
570: }
571:
572: /**
573: * Get a message from resource.properties from the package of the given object.
574: *
575: * @param caller The calling object, used to get the package name and class loader
576: * @param locale The locale
577: * @param key The resource key
578: * @param arg0 The argument to place in variable {0}
579: * @param arg1 The argument to place in variable {1}
580: * @param arg2 The argument to place in variable {2}
581: * @param arg3 The argument to place in variable {3}
582: * @return The formatted message
583: */
584: public static String getString(Object caller, Locale locale,
585: String key, Object arg0, Object arg1, Object arg2,
586: Object arg3) throws MissingResourceException {
587: Object[] o = new Object[4];
588: o[0] = arg0;
589: o[1] = arg1;
590: o[2] = arg2;
591: o[3] = arg3;
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: *
598: * @param caller The calling object, used to get the package name and class loader
599: * @param locale The locale
600: * @param key The resource key
601: * @param arg0 The argument to place in variable {0}
602: * @param arg1 The argument to place in variable {1}
603: * @param arg2 The argument to place in variable {2}
604: * @param arg3 The argument to place in variable {3}
605: * @return Returns the formatted message.
606: */
607: public static String getString(Object caller, Locale locale,
608: String key, Object arg0, Object arg1, Object arg2,
609: Object arg3, Object arg4) throws MissingResourceException {
610: Object[] o = new Object[5];
611: o[0] = arg0;
612: o[1] = arg1;
613: o[2] = arg2;
614: o[3] = arg3;
615: o[4] = arg4;
616: return getMessage(caller, BASE_NAME, locale, key, o);
617: }
618:
619: /**
620: * Get a message from resource.properties from the package of the given object.
621: *
622: * @param caller The calling object, used to get the package name and class loader
623: * @param locale The locale
624: * @param key The resource key
625: * @param args An array of objects to place in corresponding variables
626: * @return Returns the formatted message.
627: */
628: public static String getString(Object caller, Locale locale,
629: String key, Object[] args) throws MissingResourceException {
630: return getMessage(caller, BASE_NAME, locale, key, args);
631: }
632:
633: // Workhorse that does the resource loading and key lookup
634: public static String getMessage(Object caller, String basename,
635: Locale locale, String key, Object[] args)
636: throws MissingResourceException {
637: String msg = null;
638: MissingResourceException firstEx = null;
639: String fullName = null;
640: Class curClass = null;
641: boolean didNull = false;
642:
643: if (caller != null) {
644: if (caller instanceof Class)
645: curClass = (Class) caller;
646: else
647: curClass = caller.getClass();
648: }
649:
650: while (msg == null) {
651:
652: // Get the full name of the resource
653: if (curClass != null) {
654:
655: // Create the full basename
656: String pkgName = curClass.getName();
657:
658: int pos = pkgName.lastIndexOf(".");
659: if (pos > 0) {
660: fullName = pkgName.substring(0, pos + 1).replace(
661: '.', '/')
662: + basename;
663: } else {
664: fullName = basename;
665: }
666: } else {
667: fullName = basename;
668: }
669:
670: try {
671: RB rb = new RB(caller, fullName, locale);
672: msg = rb.getString(key, args);
673: } catch (MissingResourceException ex) {
674: if (curClass == null) {
675: throw ex;
676: }
677:
678: // Save the first exception
679: if (firstEx == null) {
680: firstEx = ex;
681: }
682:
683: // Get the superclass
684: curClass = curClass.getSuperclass();
685: if (curClass == null) {
686: if (didNull)
687: throw firstEx;
688: didNull = true;
689: caller = null;
690: } else {
691: String cname = curClass.getName();
692: if (cname.startsWith("java.")
693: || cname.startsWith("javax.")) {
694: if (didNull)
695: throw firstEx;
696: didNull = true;
697: caller = null;
698: curClass = null;
699: }
700: }
701: }
702:
703: }
704: return msg;
705: }
706:
707: /** Clears the internal cache. */
708: public static void clearCache() {
709: propertyCache.clear();
710: }
711: }
|