View Javadoc
1   /*
2    * Copyright 2006 Assaf Arkin, Ralf Joachim
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   * $Id: Messages.java 6907 2007-03-28 21:24:52Z rjoachim $
17   */
18  package org.castor.core.util;
19  
20  import java.text.MessageFormat;
21  import java.util.Enumeration;
22  import java.util.Hashtable;
23  import java.util.Locale;
24  import java.util.MissingResourceException;
25  import java.util.ResourceBundle;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * I18N message formatting class. A static factory for obtaining
32   * messages and formatting messages with arguments.
33   * <p>
34   * The resource file <tt>org.exolab.castor.util.resources.messages</tt>
35   * contains a list of all the messages in English. Additional resource
36   * files can be added for other languages and locales by placing them
37   * in the same package with a language/locale prefix. See the I18N
38   * documentation and use of resource bundles in the JDK docs.
39   *
40   * @author <a href="mailto:arkin AT intalio DOT com">Assaf Arkin</a>
41   * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
42   * @version $Revision: 6907 $ $Date: 2006-04-10 16:39:24 -0600 (Mon, 10 Apr 2006) $
43   * @since 1.0.1
44   */
45  public final class Messages {
46      //--------------------------------------------------------------------------
47  
48      /** The <a href="http://jakarta.apache.org/commons/logging/">Jakarta Commons
49       *  Logging </a> instance used for all logging. */
50      private static final Log LOG = LogFactory.getLog(Messages.class);
51      
52      /** The name of the resource holding all the messages in the English
53       *  language. Resources for other languages and locales use the same
54       *  name with a language/locale prefix. */
55      public static final String RESOURCE_NAME = "org.castor.messages";
56      
57      /** The resource bundle holds all the messages. */
58      private static ResourceBundle   _messages;
59      
60      /** Once a format has been created once, it is cached here. */
61      private static Hashtable        _formats;
62      //--------------------------------------------------------------------------
63  
64      static { setDefaultLocale(); }
65  
66      //--------------------------------------------------------------------------
67  
68      /**
69       * Set the default locale to use for loading messages. Calling this method
70       * will reload all the messages based on the new locale name.
71       */
72      public static void setDefaultLocale() {
73          setLocale(Locale.getDefault());
74      }
75      
76      /**
77       * Set the locale to use for loading messages. Calling this method
78       * will reload all the messages based on the new locale name.
79       * 
80       * @param locale the locale for which a resource bundle is desired.
81       */
82      public static void setLocale(final Locale locale) {
83          try {
84              _messages = ResourceBundle.getBundle(RESOURCE_NAME, locale);
85          } catch (Exception except) {
86              _messages = new EmptyResourceBundle();
87              LOG.error("Failed to locate messages resource " + RESOURCE_NAME);
88          }
89          _formats = new Hashtable();
90      }
91      
92      /**
93       * Format the named message using a single argument and return the
94       * full message text.
95       *
96       * @param message The message name
97       * @param arg1 The first argument
98       * @return The full message text
99       */
100     public static String format(final String message, final Object arg1) {
101         return format(message, new Object[] {arg1});
102     }
103     
104     /**
105      * Format the named message using two argument and return the
106      * full message text.
107      *
108      * @param message The message name
109      * @param arg1 The first argument
110      * @param arg2 The second argument
111      * @return The full message text
112      */
113     public static String format(final String message,
114             final Object arg1, final Object arg2) {
115         return format(message, new Object[] {arg1, arg2});
116     }
117     
118     /**
119      * Format the named message using three argument and return the
120      * full message text.
121      *
122      * @param message The message name
123      * @param arg1 The first argument
124      * @param arg2 The second argument
125      * @param arg3 The third argument
126      * @return The full message text
127      */
128     public static String format(final String message,
129             final Object arg1, final Object arg2, final Object arg3) {
130         return format(message, new Object[] {arg1, arg2, arg3});
131     }
132 
133     /**
134      * Format the named message using any number of arguments and return the
135      * full message text.
136      *
137      * @param message The message name
138      * @param args Argument list
139      * @return The full message text
140      */
141     public static String format(final String message, final Object[] args) {
142         
143         try {
144             MessageFormat mf = (MessageFormat) _formats.get(message);
145             if (mf == null) {
146                 String msg;
147                 try {
148                     msg = _messages.getString(message);
149                 } catch (MissingResourceException except) {
150                     return message;
151                 }
152                 mf = new MessageFormat(msg);
153                 _formats.put(message, mf);
154             }
155             return mf.format(args);
156         } catch (Exception except) {
157             return "An internal error occured while processing message " + message;
158         }
159     }
160 
161     /**
162      * Return the text of the named message without formatting.
163      *
164      * @param message The message name
165      * @return The full message text
166      */
167     public static String message(final String message) {
168         try {
169             return _messages.getString(message);
170         } catch (MissingResourceException except) {
171             return message;
172         }
173     }
174     
175     //--------------------------------------------------------------------------
176 
177     /**
178      * Hide default constructor of utility class.
179      */
180     private Messages() { }
181     
182     //--------------------------------------------------------------------------
183 
184     /**
185      * A empty resource bundle.
186      */
187     private static class EmptyResourceBundle
188     extends ResourceBundle implements Enumeration {
189         /**
190          * {@inheritDoc}
191          * @see java.util.ResourceBundle#getKeys()
192          */
193         public Enumeration getKeys() {
194             return this;
195         }
196         
197         /**
198          * {@inheritDoc}
199          * @see java.util.ResourceBundle#handleGetObject(java.lang.String)
200          */
201         protected Object handleGetObject(final String name) {
202             return "[Missing message " + name + "]";
203         }
204         
205         /**
206          * {@inheritDoc}
207          * @see java.util.Enumeration#hasMoreElements()
208          */
209         public boolean hasMoreElements() {
210             return false;
211         }
212         
213         /**
214          * {@inheritDoc}
215          * @see java.util.Enumeration#nextElement()
216          */
217         public Object nextElement() {
218             return null;
219         }
220     }
221 
222     //--------------------------------------------------------------------------
223 }