View Javadoc

1   /*
2    * $Id: MessageFactory.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config.i18n;
12  
13  import java.text.MessageFormat;
14  import java.util.Locale;
15  import java.util.MissingResourceException;
16  import java.util.ResourceBundle;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  
22  public abstract class MessageFactory
23  {
24      /**
25       * This error code is used for {@link Message} instances that are not read from a
26       * resource bundles but are created only with a string.
27       */
28      private static final int STATIC_ERROR_CODE = -1;
29      private static final transient Object[] EMPTY_ARGS = new Object[]{};
30  
31      protected transient Log logger = LogFactory.getLog(getClass());
32      // since java 6 only
33      //protected final ReloadControl control = new ReloadControl();
34  
35      /**
36       * Computes the bundle's full path 
37       * (<code>META-INF/services/org/mule/i18n/&lt;bundleName&gt;-messages.properties</code>) from
38       * <code>bundleName</code>.
39       * 
40       * @param bundleName Name of the bundle without the &quot;messages&quot; suffix and without
41       *          file extension.
42       */
43      protected static String getBundlePath(String bundleName)
44      {
45          return "META-INF.services.org.mule.i18n." + bundleName + "-messages";
46      }
47      
48      /**
49       * Factory method to create a new {@link Message} instance that is filled with the formatted
50       * message with id <code>code</code> from the resource bundle <code>bundlePath</code>.
51       * 
52       * @param bundlePath complete path to the resource bundle for lookup
53       * @param code numeric code of the message
54       * @param arg
55       * @see #getBundlePath(String)
56       */
57      protected Message createMessage(String bundlePath, int code, Object arg)
58      {
59          return createMessage(bundlePath, code, new Object[] {arg});
60      }
61      
62      /**
63       * Factory method to create a new {@link Message} instance that is filled with the formatted
64       * message with id <code>code</code> from the resource bundle <code>bundlePath</code>.
65       * 
66       * @param bundlePath complete path to the resource bundle for lookup
67       * @param code numeric code of the message
68       * @param arg1
69       * @param arg2
70       * @see #getBundlePath(String)
71       */
72      protected Message createMessage(String bundlePath, int code, Object arg1, Object arg2)
73      {
74          return createMessage(bundlePath, code, new Object[] {arg1, arg2});
75      }
76      
77      /**
78       * Factory method to create a new {@link Message} instance that is filled with the formatted
79       * message with id <code>code</code> from the resource bundle <code>bundlePath</code>.
80       * 
81       * @param bundlePath complete path to the resource bundle for lookup
82       * @param code numeric code of the message
83       * @param arg1
84       * @param arg2
85       * @param arg3
86       * @see #getBundlePath(String)
87       */
88      protected Message createMessage(String bundlePath, int code, Object arg1, Object arg2, 
89          Object arg3)
90      {
91          return createMessage(bundlePath, code, new Object[] {arg1, arg2, arg3});
92      }
93      
94      /**
95       * Factory method to create a new {@link Message} instance that is filled with the formatted
96       * message with id <code>code</code> from the resource bundle <code>bundlePath</code>.
97       * 
98       * <b>Attention:</b> do not confuse this method with 
99       * <code>createMessage(String, int, Object)</code>.
100      * 
101      * @param bundlePath complete path to the resource bundle for lookup
102      * @param code numeric code of the message
103      * @param arguments
104      * @see #getBundlePath(String)
105      */
106     protected Message createMessage(String bundlePath, int code, Object... arguments)
107     {
108         String messageString = getString(bundlePath, code, arguments);
109         return new Message(messageString, code, arguments);
110     }
111 
112     /**
113      * Factory method to create a new {@link Message} instance that is filled with the formatted
114      * message with id <code>code</code> from the resource bundle <code>bundlePath</code>.
115      * 
116      * @param bundlePath complete path to the resource bundle for lookup
117      * @param code numeric code of the message
118      */
119     protected Message createMessage(String bundlePath, int code)
120     {
121         String messageString = getString(bundlePath, code, null);
122         return new Message(messageString, code, EMPTY_ARGS);
123     }
124 
125     /**
126      * Factory method to create a {@link Message} instance that is not read from a resource bundle.
127      * 
128      * @param message Message's message text
129      * @return a Messsage instance that has an error code of -1 and no arguments.
130      */
131     public static Message createStaticMessage(String message)
132     {
133         return new Message(message, STATIC_ERROR_CODE, EMPTY_ARGS);
134     }    
135 
136     /**
137      * Factory method to read the message with code <code>code</code> from the resource bundle.
138      * 
139      * @param bundlePath complete path to the resource bundle for lookup
140      * @param code numeric code of the message
141      * @return formatted error message as {@link String}
142      */
143     protected String getString(String bundlePath, int code)
144     {
145         return getString(bundlePath, code, null);
146     }
147     
148     /**
149      * Factory method to read the message with code <code>code</code> from the resource bundle.
150      * 
151      * @param bundlePath complete path to the resource bundle for lookup
152      * @param code numeric code of the message
153      * @param arg
154      * @return formatted error message as {@link String}
155      */
156     protected String getString(String bundlePath, int code, Object arg)
157     {
158         Object[] arguments = new Object[] {arg};
159         return getString(bundlePath, code, arguments);
160     }
161     
162     /**
163      * Factory method to read the message with code <code>code</code> from the resource bundle.
164      * 
165      * @param bundlePath complete path to the resource bundle for lookup
166      * @param code numeric code of the message
167      * @param arg1
168      * @param arg2
169      * @return formatted error message as {@link String}
170      */
171     protected String getString(String bundlePath, int code, Object arg1, Object arg2)
172     {
173         Object[] arguments = new Object[] {arg1, arg2};
174         return getString(bundlePath, code, arguments);
175     }
176 
177     protected String getString(String bundlePath, int code, Object[] args)
178     {
179         // We will throw a MissingResourceException if the bundle name is invalid
180         // This happens if the code references a bundle name that just doesn't exist
181         ResourceBundle bundle = getBundle(bundlePath);
182 
183         try
184         {
185             String m = bundle.getString(String.valueOf(code));
186             if (m == null)
187             {
188                 logger.error("Failed to find message for id " + code + " in resource bundle " + bundlePath);
189                 return "";
190             }
191 
192             return MessageFormat.format(m, args);
193         }
194         catch (MissingResourceException e)
195         {
196             logger.error("Failed to find message for id " + code + " in resource bundle " + bundlePath);
197             return "";
198         }
199     }
200 
201     /**
202      * @throws MissingResourceException if resource is missing
203      */
204     private ResourceBundle getBundle(String bundlePath)
205     {
206         Locale locale = Locale.getDefault();
207         if (logger.isTraceEnabled())
208         {
209             logger.trace("Loading resource bundle: " + bundlePath + " for locale " + locale);
210         }
211         ResourceBundle bundle = ResourceBundle.getBundle(bundlePath, locale, getClassLoader());
212         return bundle;
213     }
214 
215     /**
216      * Override this method to return the classloader for the bundle/module which 
217      * contains the needed resource files.
218      */
219     protected ClassLoader getClassLoader()
220     {
221         final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
222         // if there's a deployment classloader present, use it for finding resources
223         return ccl == null ? getClass().getClassLoader() : ccl;
224     }
225 
226     // since java 6 only
227     /*static class ReloadControl extends ResourceBundle.Control
228     {
229         boolean needsReload = true;
230 
231         @Override
232         public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime)
233         {
234             // TODO always for now
235             return true;
236         }
237 
238         @Override
239         public long getTimeToLive(String baseName, Locale locale)
240         {
241             if (needsReload)
242             {
243                 // must be zero, as other 'DONT_CACHE' constant doesn't work here, and is -1
244                 return 0;
245             }
246 
247             return ResourceBundle.Control.TTL_NO_EXPIRATION_CONTROL;
248         }
249     }*/
250 }
251 
252