Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/struts/util/MessageResources.java


1   /*
2    * $Id: MessageResources.java 54929 2004-10-16 16:38:42Z germuska $ 
3    *
4    * Copyright 1999-2004 The Apache Software Foundation.
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.struts.util;
20  
21  import java.io.Serializable;
22  import java.text.MessageFormat;
23  import java.util.HashMap;
24  import java.util.Locale;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  /**
30   * General purpose abstract class that describes an API for retrieving
31   * Locale-sensitive messages from underlying resource locations of an
32   * unspecified design, and optionally utilizing the <code>MessageFormat</code>
33   * class to produce internationalized messages with parametric replacement.
34   * <p>
35   * Calls to <code>getMessage()</code> variants without a <code>Locale</code>
36   * argument are presumed to be requesting a message string in the default
37   * <code>Locale</code> for this JVM.
38   * <p>
39   * Calls to <code>getMessage()</code> with an unknown key, or an unknown
40   * <code>Locale</code> will return <code>null</code> if the
41   * <code>returnNull</code> property is set to <code>true</code>.  Otherwise,
42   * a suitable error message will be returned instead.
43   * <p>
44   * <strong>IMPLEMENTATION NOTE</strong> - Classes that extend this class
45   * must be Serializable so that instances may be used in distributable
46   * application server environments.
47   *
48   * @version $Rev: 54929 $ $Date: 2004-10-16 09:38:42 -0700 (Sat, 16 Oct 2004) $
49   */
50  public abstract class MessageResources implements Serializable {
51  
52      // ------------------------------------------------------------- Properties
53  
54      /**
55       * Commons Logging instance.
56       */
57      protected static Log log = LogFactory.getLog(MessageResources.class);
58  
59      /**
60       * The configuration parameter used to initialize this MessageResources.
61       */
62      protected String config = null;
63  
64      /**
65       * The configuration parameter used to initialize this MessageResources.
66       * @return parameter used to initialize this MessageResources
67       */
68      public String getConfig() {
69          return (this.config);
70      }
71  
72      /**
73       * The default Locale for our environment.
74       */
75      protected Locale defaultLocale = Locale.getDefault();
76  
77      /**
78       * The <code>MessageResourcesFactory</code> that created this instance.
79       */
80      protected MessageResourcesFactory factory = null;
81  
82      /**
83       * The <code>MessageResourcesFactory</code> that created this instance.
84       * @return <code>MessageResourcesFactory</code> that created instance
85       */
86      public MessageResourcesFactory getFactory() {
87          return (this.factory);
88      }
89  
90      /**
91       * The set of previously created MessageFormat objects, keyed by the
92       * key computed in <code>messageKey()</code>.
93       */
94      protected HashMap formats = new HashMap();
95  
96      /**
97       * Indicate is a <code>null</code> is returned instead of an error message string
98       * when an unknown Locale or key is requested.
99       */
100     protected boolean returnNull = false;
101 
102     /**
103      * Indicates that a <code>null</code> is returned instead of an error message string
104      * if an unknown Locale or key is requested.
105      * @return true if null is returned if unknown key or locale is requested
106      */
107     public boolean getReturnNull() {
108         return (this.returnNull);
109     }
110 
111     /**
112      * Indicates that a <code>null</code> is returned instead of an error message string
113      * if an unknown Locale or key is requested.
114      * @param returnNull true Indicates that a <code>null</code> is returned
115      * if an unknown Locale or key is requested.
116      */
117     public void setReturnNull(boolean returnNull) {
118         this.returnNull = returnNull;
119     }
120 
121     // ----------------------------------------------------------- Constructors
122 
123     /**
124      * Construct a new MessageResources according to the specified parameters.
125      *
126      * @param factory The MessageResourcesFactory that created us
127      * @param config The configuration parameter for this MessageResources
128      */
129     public MessageResources(MessageResourcesFactory factory, String config) {
130 
131         this(factory, config, false);
132 
133     }
134 
135     /**
136      * Construct a new MessageResources according to the specified parameters.
137      *
138      * @param factory The MessageResourcesFactory that created us
139      * @param config The configuration parameter for this MessageResources
140      * @param returnNull The returnNull property we should initialize with
141      */
142     public MessageResources(
143         MessageResourcesFactory factory,
144         String config,
145         boolean returnNull) {
146 
147         super();
148         this.factory = factory;
149         this.config = config;
150         this.returnNull = returnNull;
151 
152     }
153 
154     // --------------------------------------------------------- Public Methods
155 
156     /**
157      * Returns a text message for the specified key, for the default Locale.
158      *
159      * @param key The message key to look up
160      */
161     public String getMessage(String key) {
162 
163         return this.getMessage((Locale) null, key, null);
164 
165     }
166 
167     /**
168      * Returns a text message after parametric replacement of the specified
169      * parameter placeholders.
170      *
171      * @param key The message key to look up
172      * @param args An array of replacement parameters for placeholders
173      */
174     public String getMessage(String key, Object args[]) {
175 
176         return this.getMessage((Locale) null, key, args);
177 
178     }
179 
180     /**
181      * Returns a text message after parametric replacement of the specified
182      * parameter placeholders.
183      *
184      * @param key The message key to look up
185      * @param arg0 The replacement for placeholder {0} in the message
186      */
187     public String getMessage(String key, Object arg0) {
188 
189         return this.getMessage((Locale) null, key, arg0);
190 
191     }
192 
193     /**
194      * Returns a text message after parametric replacement of the specified
195      * parameter placeholders.
196      *
197      * @param key The message key to look up
198      * @param arg0 The replacement for placeholder {0} in the message
199      * @param arg1 The replacement for placeholder {1} in the message
200      */
201     public String getMessage(String key, Object arg0, Object arg1) {
202 
203         return this.getMessage((Locale) null, key, arg0, arg1);
204 
205     }
206 
207     /**
208      * Returns a text message after parametric replacement of the specified
209      * parameter placeholders.
210      *
211      * @param key The message key to look up
212      * @param arg0 The replacement for placeholder {0} in the message
213      * @param arg1 The replacement for placeholder {1} in the message
214      * @param arg2 The replacement for placeholder {2} in the message
215      */
216     public String getMessage(String key, Object arg0, Object arg1, Object arg2) {
217 
218         return this.getMessage((Locale) null, key, arg0, arg1, arg2);
219 
220     }
221 
222     /**
223      * Returns a text message after parametric replacement of the specified
224      * parameter placeholders.
225      *
226      * @param key The message key to look up
227      * @param arg0 The replacement for placeholder {0} in the message
228      * @param arg1 The replacement for placeholder {1} in the message
229      * @param arg2 The replacement for placeholder {2} in the message
230      * @param arg3 The replacement for placeholder {3} in the message
231      */
232     public String getMessage(
233         String key,
234         Object arg0,
235         Object arg1,
236         Object arg2,
237         Object arg3) {
238 
239         return this.getMessage((Locale) null, key, arg0, arg1, arg2, arg3);
240 
241     }
242 
243     /**
244      * Returns a text message for the specified key, for the default Locale.
245      * A null string result will be returned by this method if no relevant
246      * message resource is found for this key or Locale, if the
247      * <code>returnNull</code> property is set.  Otherwise, an appropriate
248      * error message will be returned.
249      * <p>
250      * This method must be implemented by a concrete subclass.
251      *
252      * @param locale The requested message Locale, or <code>null</code>
253      *  for the system default Locale
254      * @param key The message key to look up
255      */
256     public abstract String getMessage(Locale locale, String key);
257 
258     /**
259      * Returns a text message after parametric replacement of the specified
260      * parameter placeholders.  A null string result will be returned by
261      * this method if no resource bundle has been configured.
262      *
263      * @param locale The requested message Locale, or <code>null</code>
264      *  for the system default Locale
265      * @param key The message key to look up
266      * @param args An array of replacement parameters for placeholders
267      */
268     public String getMessage(Locale locale, String key, Object args[]) {
269 
270         // Cache MessageFormat instances as they are accessed
271         if (locale == null) {
272             locale = defaultLocale;
273         }
274 
275         MessageFormat format = null;
276         String formatKey = messageKey(locale, key);
277 
278         synchronized (formats) {
279             format = (MessageFormat) formats.get(formatKey);
280             if (format == null) {
281                 String formatString = getMessage(locale, key);
282 
283                 if (formatString == null) {
284                     return returnNull ? null : ("???" + formatKey + "???");
285                 }
286 
287                 format = new MessageFormat(escape(formatString));
288                 format.setLocale(locale);
289                 formats.put(formatKey, format);
290             }
291 
292         }
293 
294         return format.format(args);
295     }
296 
297     /**
298      * Returns a text message after parametric replacement of the specified
299      * parameter placeholders.  A null string result will never be returned
300      * by this method.
301      *
302      * @param locale The requested message Locale, or <code>null</code>
303      *  for the system default Locale
304      * @param key The message key to look up
305      * @param arg0 The replacement for placeholder {0} in the message
306      */
307     public String getMessage(Locale locale, String key, Object arg0) {
308         return this.getMessage(locale, key, new Object[] { arg0 });
309     }
310 
311     /**
312      * Returns a text message after parametric replacement of the specified
313      * parameter placeholders.  A null string result will never be returned
314      * by this method.
315      *
316      * @param locale The requested message Locale, or <code>null</code>
317      *  for the system default Locale
318      * @param key The message key to look up
319      * @param arg0 The replacement for placeholder {0} in the message
320      * @param arg1 The replacement for placeholder {1} in the message
321      */
322     public String getMessage(Locale locale, String key, Object arg0, Object arg1) {
323         return this.getMessage(locale, key, new Object[] { arg0, arg1 });
324     }
325 
326     /**
327      * Returns a text message after parametric replacement of the specified
328      * parameter placeholders.  A null string result will never be returned
329      * by this method.
330      *
331      * @param locale The requested message Locale, or <code>null</code>
332      *  for the system default Locale
333      * @param key The message key to look up
334      * @param arg0 The replacement for placeholder {0} in the message
335      * @param arg1 The replacement for placeholder {1} in the message
336      * @param arg2 The replacement for placeholder {2} in the message
337      */
338     public String getMessage(
339         Locale locale,
340         String key,
341         Object arg0,
342         Object arg1,
343         Object arg2) {
344 
345         return this.getMessage(locale, key, new Object[] { arg0, arg1, arg2 });
346     }
347 
348     /**
349      * Returns a text message after parametric replacement of the specified
350      * parameter placeholders.  A null string result will never be returned
351      * by this method.
352      *
353      * @param locale The requested message Locale, or <code>null</code>
354      *  for the system default Locale
355      * @param key The message key to look up
356      * @param arg0 The replacement for placeholder {0} in the message
357      * @param arg1 The replacement for placeholder {1} in the message
358      * @param arg2 The replacement for placeholder {2} in the message
359      * @param arg3 The replacement for placeholder {3} in the message
360      */
361     public String getMessage(
362         Locale locale,
363         String key,
364         Object arg0,
365         Object arg1,
366         Object arg2,
367         Object arg3) {
368 
369         return this.getMessage(locale, key, new Object[] { arg0, arg1, arg2, arg3 });
370     }
371 
372     /**
373      * Return <code>true</code> if there is a defined message for the specified
374      * key in the system default locale.
375      *
376      * @param key The message key to look up
377      */
378     public boolean isPresent(String key) {
379 
380         return this.isPresent(null, key);
381 
382     }
383 
384     /**
385      * Return <code>true</code> if there is a defined message for the specified
386      * key in the specified Locale.
387      *
388      * @param locale The requested message Locale, or <code>null</code>
389      *  for the system default Locale
390      * @param key The message key to look up
391      */
392     public boolean isPresent(Locale locale, String key) {
393 
394         String message = getMessage(locale, key);
395 
396         if (message == null) {
397             return false;
398 
399         } else if (message.startsWith("???") && message.endsWith("???")) {
400             return false; // FIXME - Only valid for default implementation
401 
402         } else {
403             return true;
404         }
405 
406     }
407 
408     // ------------------------------------------------------ Protected Methods
409 
410     /**
411      * Escape any single quote characters that are included in the specified
412      * message string.
413      *
414      * @param string The string to be escaped
415      */
416     protected String escape(String string) {
417 
418         if ((string == null) || (string.indexOf('\'') < 0)) {
419             return string;
420         }
421 
422         int n = string.length();
423         StringBuffer sb = new StringBuffer(n);
424 
425         for (int i = 0; i < n; i++) {
426             char ch = string.charAt(i);
427 
428             if (ch == '\'') {
429                 sb.append('\'');
430             }
431 
432             sb.append(ch);
433         }
434 
435         return sb.toString();
436 
437     }
438 
439     /**
440      * Compute and return a key to be used in caching information by a Locale.
441      * <strong>NOTE</strong> - The locale key for the default Locale in our
442      * environment is a zero length String.
443      *
444      * @param locale The locale for which a key is desired
445      */
446     protected String localeKey(Locale locale) {
447         return (locale == null) ? "" : locale.toString();
448     }
449 
450     /**
451      * Compute and return a key to be used in caching information
452      * by Locale and message key.
453      *
454      * @param locale The Locale for which this format key is calculated
455      * @param key The message key for which this format key is calculated
456      */
457     protected String messageKey(Locale locale, String key) {
458 
459         return (localeKey(locale) + "." + key);
460 
461     }
462 
463     /**
464      * Compute and return a key to be used in caching information
465      * by locale key and message key.
466      *
467      * @param localeKey The locale key for which this cache key is calculated
468      * @param key The message key for which this cache key is calculated
469      */
470     protected String messageKey(String localeKey, String key) {
471 
472         return (localeKey + "." + key);
473 
474     }
475 
476     // --------------------------------------------------------- Static Methods
477 
478     /**
479      * The default MessageResourcesFactory used to create MessageResources
480      * instances.
481      */
482     protected static MessageResourcesFactory defaultFactory = null;
483 
484     /**
485      * Create and return an instance of <code>MessageResources</code> for the
486      * created by the default <code>MessageResourcesFactory</code>.
487      *
488      * @param config Configuration parameter for this message bundle.
489      */
490     public synchronized static MessageResources getMessageResources(String config) {
491 
492         if (defaultFactory == null) {
493             defaultFactory = MessageResourcesFactory.createFactory();
494         }
495 
496         return defaultFactory.createResources(config);
497     }
498 
499     /**
500      * Log a message to the Writer that has been configured for our use.
501      *
502      * @param message The message to be logged
503      */
504     public void log(String message) {
505         log.debug(message);
506     }
507 
508     /**
509      * Log a message and exception to the Writer that has been configured
510      * for our use.
511      *
512      * @param message The message to be logged
513      * @param throwable The exception to be logged
514      */
515     public void log(String message, Throwable throwable) {
516         log.debug(message, throwable);
517     }
518 
519 }