KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > i18n > MessageBundle


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64 package com.jcorporate.expresso.core.i18n;
65
66 import com.jcorporate.expresso.core.dbobj.Schema;
67 import com.jcorporate.expresso.core.dbobj.SchemaFactory;
68 import com.jcorporate.expresso.core.misc.StringUtil;
69 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
70 import org.apache.log4j.Logger;
71
72 import java.text.MessageFormat JavaDoc;
73 import java.util.HashMap JavaDoc;
74 import java.util.Locale JavaDoc;
75 import java.util.Map JavaDoc;
76 import java.util.ResourceBundle JavaDoc;
77 import java.util.WeakHashMap JavaDoc;
78
79
80 /**
81  * A message bundle handles the messages for a specific combination of
82  * language, country and schema Created on January 21, 2001, 8:43 PM
83  */

84 public class MessageBundle extends Object JavaDoc {
85     /**
86      * The default bundle name
87      */

88     public static final String JavaDoc DEFAULT_BUNDLE_NAME = "MessagesBundle";
89     public static final String JavaDoc DEFAULT_BUNDLE_PATH = "com.jcorporate.expresso.core";
90
91     /**
92      * The log4j logger
93      */

94     private static Logger log = Logger.getLogger(MessageBundle.class);
95
96     /**
97      * Default BLANK locale
98      */

99     private static final Locale JavaDoc BLANK_LOCALE = new Locale JavaDoc("en", "us", "null");
100     private static Map JavaDoc schemas = new HashMap JavaDoc();
101
102     /**
103      * Resounce bundle name
104      */

105     private String JavaDoc bundleName = DEFAULT_BUNDLE_NAME;
106     private String JavaDoc bundlePath = null;
107     private String JavaDoc myCountry = null;
108     private String JavaDoc myLanguage = null;
109     private String JavaDoc mySchema = null;
110
111     /**
112      * Bundle Map
113      */

114     private WeakHashMap JavaDoc bundleCache = new WeakHashMap JavaDoc();
115
116     /**
117      * Creates new Class
118      */

119     public MessageBundle() {
120     }
121
122     /* MessageBundle() */
123
124     /**
125      * Sets the resource bundle name
126      *
127      * @param bundleName The bundle name to use when retrieving messages
128      */

129     public synchronized void setBundleName(String JavaDoc bundleName) {
130         this.bundleName = bundleName;
131     }
132
133     /**
134      * Gets the resource bundle name author: Peter Pilgrim, Sun Sep 07 12:16:56
135      * BST 2003
136      *
137      * @return java.lang.String the bundle name
138      */

139     public synchronized String JavaDoc getBundleName() {
140         return bundleName;
141     }
142
143     /**
144      * Sets the path for the bundle for the specified schema
145      *
146      * @param newBundlePath the bundle path
147      */

148     public synchronized void setBundlePath(String JavaDoc newBundlePath) {
149         bundlePath = newBundlePath;
150     }
151
152     /* setBundlePath(String) */
153
154     /**
155      * Returns the location of the Messages bundle path as specified by your
156      * schema.
157      *
158      * @return java.lang.String
159      */

160     public synchronized String JavaDoc getBundlePath() {
161         return bundlePath;
162     }
163
164     /* getBundlePath() */
165
166     /**
167      * Sets the country for the bundle
168      *
169      * @param newCountry the new two digit country code
170      */

171     public synchronized void setCountry(String JavaDoc newCountry) {
172         myCountry = newCountry;
173     }
174
175     /* setCountry(String) */
176
177     /**
178      * Used to get the sub-language country code
179      *
180      * @return the ISO two letter country code.
181      */

182     public String JavaDoc getCountry() {
183         return myCountry;
184     }
185
186     /* getCountry() */
187
188     /**
189      * Sets the language to get the Messages for
190      *
191      * @param newLanguage the new language code
192      */

193     public synchronized void setLanguage(String JavaDoc newLanguage) {
194         myLanguage = newLanguage;
195     }
196
197     /* setLanguage(String) */
198
199     /**
200      * @return the language code as a java.lang.String
201      */

202     public String JavaDoc getLanguage() {
203         return myLanguage;
204     }
205
206     /* getLanguage() */
207
208     /**
209      * Sets the schema so you can get messages from your own apps messages
210      * bundle
211      *
212      * @param schemaName The name of the schema to get the messages from
213      */

214     public synchronized void setSchema(String JavaDoc schemaName) {
215         mySchema = schemaName;
216
217         Schema theSchema = getSchema(mySchema);
218
219         bundlePath = theSchema.getMessageBundlePath();
220     }
221
222     /* setSchema(String) */
223
224     /**
225      * Formats the string code with the appropriate argument array. Issues warning log if code is not found.
226      *
227      * @param stringCode The string code to retrieve
228      * @param args the formatting arguments for the String
229      * @return The properly formatted string as read from the messages bundle, or the stringCode if not found
230      * @see java.text.MessageFormat
231      */

232     public String JavaDoc getString(String JavaDoc stringCode, Object JavaDoc[] args) {
233         try {
234             Locale JavaDoc l = null;
235
236             if (myLanguage != null) {
237                 if (myCountry.equals("default")) {
238                     l = new Locale JavaDoc(myLanguage, "");
239                 } else {
240                     l = new Locale JavaDoc(myLanguage, myCountry);
241                 }
242             } else {
243                 l = Locale.getDefault();
244             }
245
246             String JavaDoc messageString = getStringFromBundle(l, stringCode);
247             MessageFormat JavaDoc formatter = new MessageFormat JavaDoc("");
248             formatter.setLocale(l);
249             formatter.applyPattern(messageString);
250
251             return StringUtil.notNull(formatter.format(args));
252         } catch (Exception JavaDoc se) {
253
254             String JavaDoc msg = "No such key '" +
255                     stringCode + "' in bundle at '" + bundlePath + "'";
256             if (log.isDebugEnabled()) {
257                 msg += " with language '" + getLanguage() + "', " + "Country '" +
258                         getCountry() + "'";
259             }
260             log.warn(msg);
261             return stringCode;
262         }
263     }
264
265     /* getString(String, Object[]) */
266
267     /**
268      * Formats the string code with the appropriate argument array, throwing an exception if
269      * the key does not exist.
270      *
271      * @param stringCode The string code to retrieve
272      * @param args the formatting arguments for the String
273      * @return The properly formatted string as read from the messages bundle
274      * @throws IllegalArgumentException if the given string code doesn't exist
275      * in the given bundle.
276      * @see java.text.MessageFormat
277      */

278     public String JavaDoc getStringRequired(String JavaDoc stringCode, Object JavaDoc[] args) throws IllegalArgumentException JavaDoc {
279         try {
280             Locale JavaDoc locale = null;
281             String JavaDoc result = "";
282
283             if (myLanguage != null) {
284                 if (myCountry.equals("default")) {
285                     locale = new Locale JavaDoc(myLanguage, "");
286                 } else {
287                     locale = new Locale JavaDoc(myLanguage, myCountry);
288                 }
289             } else {
290                 locale = Locale.getDefault();
291             }
292
293             String JavaDoc messageString = getStringFromBundle(locale, stringCode);
294             if (args != null && args.length > 0) {
295                 MessageFormat JavaDoc formatter = new MessageFormat JavaDoc(messageString, locale);
296                 result = StringUtil.notNull(formatter.format(args));
297             } else {
298                 result = messageString;
299             }
300
301             return result;
302         } catch (Exception JavaDoc se) {
303             String JavaDoc msg = "No such key '" +
304                     stringCode + "' in bundle at '" + bundlePath + "'";
305             if (log.isDebugEnabled()) {
306                 msg += " with language '" + getLanguage() + "', " + "Country '" +
307                         getCountry() + "'";
308             }
309             log.warn(msg);
310             throw new IllegalArgumentException JavaDoc(msg);
311         }
312     }
313     /* getStringRequired(String, Object[]) */
314
315     /**
316      * Instantiate & return the schema class given in the current parameter
317      *
318      * @param schemaClass The instantiated schema factory
319      * @return A Schema object instantiated from the class named by the
320      * 'SchemaClass' parameter
321      * @throws IllegalArgumentException if schema class cannot be instantiated
322      */

323     protected Schema getSchema(String JavaDoc schemaClass) {
324         Schema oneSchema;
325
326         synchronized (schemas) {
327             oneSchema = (Schema) schemas.get(schemaClass);
328         }
329
330         if (oneSchema != null) {
331             return oneSchema;
332         } else {
333             oneSchema = SchemaFactory.getInstance().getSchema(schemaClass);
334
335             if (oneSchema == null) {
336                 throw new IllegalArgumentException JavaDoc("Can't instantiate " +
337                         "Schema class " + schemaClass);
338             }
339         }
340
341         synchronized (schemas) {
342             schemas.put(schemaClass, oneSchema);
343         }
344
345         return oneSchema;
346     }
347
348     /* getSchema(String) */
349
350     /**
351      * Return a string for a specific locale
352      *
353      * @param ourLocale The specified Locale Object
354      * @param stringCode The specified String code
355      * @return The properly formatted string as read from the messages bundle; never null--will throw runtime exception if not found
356      */

357     protected String JavaDoc getStringFromBundle(Locale JavaDoc ourLocale, String JavaDoc stringCode) {
358         String JavaDoc result = null;
359         try {
360             ResourceBundle JavaDoc rb = getBundle(ourLocale);
361             result = rb.getString(stringCode);
362         } catch (Exception JavaDoc e) {
363             // try default bundle if we fail in app bundle
364
if (!DEFAULT_BUNDLE_PATH.equals(bundlePath)) {
365                 result = getStringFromDefaultSchemaBundle(ourLocale, stringCode);
366             }
367             if (result == null) {
368                 throw new RuntimeException JavaDoc("cannot find translated string");
369             }
370         }
371         return result;
372     }
373
374     /**
375      * Return a string for a specific locale, using the default (expresso) schema
376      *
377      * @param ourLocale The specified Locale Object
378      * @param stringCode The specified String code
379      * @return The properly formatted string as read from the messages bundle
380      */

381     protected String JavaDoc getStringFromDefaultSchemaBundle(Locale JavaDoc ourLocale, String JavaDoc stringCode) {
382         ResourceBundle JavaDoc rb = null;
383         synchronized (bundleCache) {
384             if (ourLocale != null) {
385                 rb = getBundleFromPath(ourLocale, DEFAULT_BUNDLE_PATH);
386             } else {
387                 rb = getBundleFromPath(BLANK_LOCALE, DEFAULT_BUNDLE_PATH);
388             }
389         }
390
391         return rb.getString(stringCode);
392     }
393
394     /* getStringFromBundle(Locale, String) */
395
396     /**
397      * Get the resource bundle associated with the specified schema Needs to
398      * be synchronized because of the creation elements.
399      *
400      * @param ourLocale The specified Locale Object
401      * @return a loaded resource bundle
402      */

403     private synchronized ResourceBundle JavaDoc getBundle(Locale JavaDoc ourLocale) {
404
405         ResourceBundle JavaDoc rb = null;
406         synchronized (bundleCache) {
407             if (ourLocale != null) {
408                 rb = getBundleFromPath(ourLocale, bundlePath);
409             } else {
410                 rb = getBundleFromPath(BLANK_LOCALE, bundlePath);
411             }
412         }
413         return rb;
414     }
415
416     /**
417      * requires external sync
418      */

419     private ResourceBundle JavaDoc getBundleFromPath(Locale JavaDoc ourLocale, String JavaDoc path) {
420         String JavaDoc key = ourLocale + path;
421         ResourceBundle JavaDoc rb = (ResourceBundle JavaDoc) bundleCache.get(key);
422
423         if (rb == null) {
424             FastStringBuffer fsb = new FastStringBuffer(path);
425             fsb.append("/" + bundleName);
426             rb = ResourceBundle.getBundle(fsb.toString(), ourLocale);
427
428             bundleCache.put(key, rb);
429         }
430
431         return rb;
432     }
433
434     /**
435      * Formats the string code with the appropriate argument array. Does NOT issue warning log if code is not found, but rather returns null
436      *
437      * @param stringCode The string code to retrieve
438      * @param args the formatting arguments for the String
439      * @return The properly formatted string as read from the messages bundle, or null if not found
440      * @see java.text.MessageFormat
441      */

442     public String JavaDoc getStringOrNull(String JavaDoc stringCode, Object JavaDoc[] args) {
443         try {
444             Locale JavaDoc l = null;
445
446             if (myLanguage != null) {
447                 if (myCountry.equals("default")) {
448                     l = new Locale JavaDoc(myLanguage, "");
449                 } else {
450                     l = new Locale JavaDoc(myLanguage, myCountry);
451                 }
452             } else {
453                 l = Locale.getDefault();
454             }
455
456             String JavaDoc messageString = getStringFromBundle(l, stringCode);
457             MessageFormat JavaDoc formatter = new MessageFormat JavaDoc("");
458             formatter.setLocale(l);
459             formatter.applyPattern(messageString);
460
461             return StringUtil.notNull(formatter.format(args));
462         } catch (Exception JavaDoc se) {
463             return null;
464         }
465     }
466 }
467
468 /* MessageBundle */
469
Popular Tags