View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.commons.util;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  import javax.el.ValueExpression;
25  import javax.faces.FactoryFinder;
26  import javax.faces.application.Application;
27  import javax.faces.application.ApplicationFactory;
28  import javax.faces.application.FacesMessage;
29  import javax.faces.component.UIComponent;
30  import javax.faces.context.FacesContext;
31  import java.text.MessageFormat;
32  import java.util.Locale;
33  import java.util.MissingResourceException;
34  import java.util.ResourceBundle;
35  
36  /**
37   * Utility class to support multilingual FacesMessages using ResourceBundles.
38   * Standard messages are stored at <code>DEFAULT_BUNDLE</code>.<br>
39   * The summary of the message is stored at the requested key value. The detail
40   * of the message is stored at &lt;messageId&gt;_detail.
41   *
42   * @see FacesMessage
43   * @see java.util.ResourceBundle
44   *
45   * @author Thomas Spiegl (latest modification by $Author: skitching $)
46   * @author Manfred Geiler
47   * @author Sean Schofield
48   * @author Stpehan Strittmatter
49   * @version $Revision: 676268 $ $Date: 2008-07-13 02:45:56 -0500 (Sun, 13 Jul 2008) $
50   */
51  public final class MessageUtils
52  {
53    /** Utility class, do not instatiate */
54      private MessageUtils()
55      {
56          // nope
57      }
58  
59      /** Default bundle for messages (<code>org.apache.myfaces.commons.Messages</code>) */ 
60      private static final String DEFAULT_BUNDLE = "org.apache.myfaces.commons.Messages";//javax.faces.Messages
61  
62      /** Suffix for message details (<code>_detail</code>)*/
63      private static final String DETAIL_SUFFIX = "_detail";
64      private static Log log = LogFactory.getLog(MessageUtils.class);
65  
66      /**
67       * @param severity serverity of message
68       * @param messageId id of message
69       * @param arg arument of message
70       *
71       * @return generated FacesMessage
72       */
73      public static FacesMessage getMessage(FacesMessage.Severity severity,
74                                            String messageId,
75                                            Object arg)
76      {
77          return getMessage(severity,
78                            messageId,
79                            new Object[]{arg},
80                            FacesContext.getCurrentInstance());
81      }
82  
83      /**
84       * @param severity serverity of message
85       * @param messageId id of message
86       * @param args aruments of message
87       *
88       * @return generated FacesMessage
89       */
90      public static FacesMessage getMessage(FacesMessage.Severity severity,
91                                            String messageId,
92                                            Object[] args)
93      {
94          return getMessage(severity,
95                            messageId,
96                            args,
97                            FacesContext.getCurrentInstance());
98      }
99  
100     public static FacesMessage getMessage(FacesMessage.Severity severity,
101                                           String messageId,
102                                           Object[] args,
103                                           FacesContext facesContext)
104     {
105         FacesMessage message = getMessage(facesContext, messageId, args);
106         message.setSeverity(severity);
107 
108         return message;
109     }
110 
111     public static void addMessage(FacesMessage.Severity severity,
112                                   String messageId,
113                                   Object[] args)
114     {
115         addMessage(severity, messageId, args, null, FacesContext.getCurrentInstance());
116     }
117 
118     public static void addMessage(FacesMessage.Severity severity,
119                                   String messageId,
120                                   Object[] args,
121                                   FacesContext facesContext)
122     {
123         addMessage(severity, messageId, args, null, facesContext);
124     }
125 
126     public static void addMessage(FacesMessage.Severity severity,
127                                   String messageId,
128                                   Object[] args,
129                                   String forClientId)
130     {
131         addMessage(severity, messageId, args, forClientId, FacesContext.getCurrentInstance());
132     }
133 
134     public static void addMessage(FacesMessage.Severity severity,
135                                   String messageId,
136                                   Object[] args,
137                                   String forClientId,
138                                   FacesContext facesContext)
139     {
140         if(log.isTraceEnabled()) {
141           log.trace("adding message " + messageId + " for clientId " + forClientId);
142         }
143         facesContext.addMessage(forClientId,
144                                 getMessage(severity, messageId, args, facesContext));
145     }
146 
147     /**
148      * Uses <code>MessageFormat</code> and the supplied parameters to fill in the param placeholders in the String.
149      *
150      * @param locale The <code>Locale</code> to use when performing the substitution.
151      * @param msgtext The original parameterized String.
152      * @param params The params to fill in the String with.
153      * @return The updated String.
154      */
155     public static String substituteParams(Locale locale, String msgtext, Object params[])
156     {
157         String localizedStr = null;
158         if(params == null || msgtext == null)
159             return msgtext;
160         StringBuffer b = new StringBuffer(100);
161         MessageFormat mf = new MessageFormat(msgtext);
162         if(locale != null)
163         {
164             mf.setLocale(locale);
165             b.append(mf.format(((Object) (params))));
166             localizedStr = b.toString();
167         }
168         return localizedStr;
169     }
170 
171     public static FacesMessage getMessage(String messageId, Object params[])
172     {
173         Locale locale = null;
174         FacesContext context = FacesContext.getCurrentInstance();
175         if(context != null && context.getViewRoot() != null)
176         {
177             locale = context.getViewRoot().getLocale();
178             if(locale == null)
179                 locale = Locale.getDefault();
180         } else
181         {
182             locale = Locale.getDefault();
183         }
184         return getMessage(locale, messageId, params);
185     }
186 
187     public static FacesMessage getMessage(Locale locale, String messageId, Object params[])
188     {
189         String summary = null;
190         String detail = null;
191         String bundleName = getApplication().getMessageBundle();
192         ResourceBundle bundle = null;
193 
194         if (bundleName != null)
195         {
196             try
197             {
198                 bundle = ResourceBundle.getBundle(bundleName, locale, getCurrentLoader(bundleName));
199                 summary = bundle.getString(messageId);
200             }
201             catch (MissingResourceException e) {
202                 // NoOp
203             }
204         }
205 
206         if (summary == null)
207         {
208             try
209             {
210                 bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, getCurrentLoader(DEFAULT_BUNDLE));
211                 if(bundle == null)
212                 {
213                     throw new NullPointerException();
214                 }
215                 summary = bundle.getString(messageId);
216             }
217             catch(MissingResourceException e) {
218                 // NoOp
219             }
220         }
221 
222         if(summary == null)
223         {
224             summary = messageId;
225         }
226 
227         if (bundle == null)
228         {
229             throw new NullPointerException(
230                 "Unable to locate ResourceBundle: bundle is null");
231         }
232         summary = substituteParams(locale, summary, params);
233 
234         try
235         {
236             detail = substituteParams(locale,
237                 bundle.getString(messageId + DETAIL_SUFFIX), params);
238         }
239         catch(MissingResourceException e) {
240             // NoOp
241         }
242 
243         return new FacesMessage(summary, detail);
244     }
245 
246     /**
247      * @param bundleBaseName baseName of ResourceBundle to load localized messages
248      * @param messageId id of message
249      * @param params parameters to set at localized message
250      * @return generated FacesMessage
251      */
252     public static FacesMessage getMessage(String bundleBaseName, String messageId, Object params[])
253     {
254         return getMessage(bundleBaseName, getCurrentLocale(), messageId, params);
255     }
256     
257     /**
258      * 
259      * @return  currently applicable Locale for this request.
260      */
261     public static Locale getCurrentLocale() {
262         Locale locale;
263         
264         FacesContext context = FacesContext.getCurrentInstance();
265         if(context != null && context.getViewRoot() != null) {
266             locale = context.getViewRoot().getLocale();
267             if(locale == null)
268                 locale = Locale.getDefault();
269         } else {
270             locale = Locale.getDefault();
271         }
272         
273         return locale;
274     }
275 
276     /**
277      * @param severity severity of message
278      * @param bundleBaseName baseName of ResourceBundle to load localized messages
279      * @param messageId id of message
280      * @param params parameters to set at localized message
281      * @return generated FacesMessage
282      */
283     public static FacesMessage getMessage(FacesMessage.Severity severity, String bundleBaseName, String messageId, Object params[])
284     {
285       FacesMessage msg = getMessage(bundleBaseName, messageId, params);
286       msg.setSeverity(severity);
287 
288       return msg;
289     }
290 
291     /**
292      * @param bundleBaseName baseName of ResourceBundle to load localized messages
293      * @param locale current locale
294      * @param messageId id of message
295      * @param params parameters to set at localized message
296      * @return generated FacesMessage
297      */
298     public static FacesMessage getMessage(String bundleBaseName, Locale locale, String messageId, Object params[])
299     {
300       if (bundleBaseName == null)
301       {
302           throw new NullPointerException(
303               "Unable to locate ResourceBundle: bundle is null");
304       }
305 
306       ResourceBundle bundle = ResourceBundle.getBundle(bundleBaseName, locale);
307 
308       return getMessage(bundle, messageId, params);
309     }
310     /**
311      * @param bundle ResourceBundle to load localized messages
312      * @param messageId id of message
313      * @param params parameters to set at localized message
314      * @return generated FacesMessage
315      */
316     public static FacesMessage getMessage(ResourceBundle bundle, String messageId, Object params[])
317     {
318 
319       String summary = null;
320       String detail = null;
321 
322       try
323       {
324           summary = bundle.getString(messageId);
325       }
326       catch (MissingResourceException e) {
327         // NoOp
328       }
329 
330 
331       if(summary == null)
332       {
333           summary = messageId;
334       }
335 
336       summary = substituteParams(bundle.getLocale(), summary, params);
337 
338       try
339       {
340           detail = substituteParams(bundle.getLocale(),
341               bundle.getString(messageId + DETAIL_SUFFIX), params);
342       }
343       catch(MissingResourceException e) {
344         // NoOp
345       }
346 
347       return new FacesMessage(summary, detail);
348     }
349 
350     /**
351      *
352      * @param context
353      * @param messageId
354      * @return generated FacesMessage
355      */
356     public static FacesMessage getMessage(FacesContext context, String messageId)
357     {
358         return getMessage(context, messageId, ((Object []) (null)));
359     }
360 
361     /**
362      *
363      * @param context
364      * @param messageId
365      * @param params
366      * @return generated FacesMessage
367      */
368     public static FacesMessage getMessage(FacesContext context, String messageId, Object params[])
369     {
370         if(context == null || messageId == null)
371             throw new NullPointerException(" context " + context + " messageId " + messageId);
372         Locale locale = getCurrentLocale();
373         if(null == locale)
374             throw new NullPointerException(" locale " + locale);
375         FacesMessage message = getMessage(locale, messageId, params);
376         if(message != null)
377         {
378             return message;
379         } else
380         {
381             // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
382             // but similar behavior above does not.  The methods should probably behave
383             locale = Locale.getDefault();
384             return getMessage(locale, messageId, params);
385         }
386     }
387 
388     private static Application getApplication()
389     {
390         FacesContext context = FacesContext.getCurrentInstance();
391         if(context != null)
392         {
393             return FacesContext.getCurrentInstance().getApplication();
394         } else
395         {
396             ApplicationFactory afactory = (ApplicationFactory)FactoryFinder.getFactory("javax.faces.application.ApplicationFactory");
397             return afactory.getApplication();
398         }
399     }
400     private static ClassLoader getCurrentLoader(Object defaultObject)
401     {
402         ClassLoader loader = Thread.currentThread().getContextClassLoader();
403         if(loader == null)
404         {
405             loader = defaultObject.getClass().getClassLoader();
406         }
407         return loader;
408     }
409 
410     public static String getLabel(FacesContext facesContext, UIComponent component) {
411         Object label = component.getAttributes().get("label");
412         if(label != null)
413           return label.toString();
414 
415         ValueExpression expression = component.getValueExpression("label");
416         if (expression != null)
417           return expression.getExpressionString();
418 
419         //If no label is not specified, use clientId
420         return component.getClientId( facesContext );
421       }
422 }