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.shared.util;
20  
21  import java.text.MessageFormat;
22  import java.util.Locale;
23  import java.util.MissingResourceException;
24  import java.util.ResourceBundle;
25  
26  import javax.el.ValueExpression;
27  import javax.faces.FactoryFinder;
28  import javax.faces.application.Application;
29  import javax.faces.application.ApplicationFactory;
30  import javax.faces.application.FacesMessage;
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /***
38   * Utility class to support multilingual FacesMessages using ResourceBundles.
39   * Standard messages are stored at <code>DEFAULT_BUNDLE</code>.<br>
40   * The summary of the message is stored at the requested key value. The detail
41   * of the message is stored at &lt;messageId&gt;_detail.
42   *
43   * @see FacesMessage
44   * @see java.util.ResourceBundle
45   *
46   * @author Thomas Spiegl (latest modification by $Author: lu4242 $)
47   * @author Manfred Geiler
48   * @author Sean Schofield
49   * @author Stpehan Strittmatter
50   * @version $Revision: 940133 $ $Date: 2010-05-01 20:30:31 -0500 (Sat, 01 May 2010) $
51   */
52  public final class MessageUtils
53  {
54      /*** Utility class, do not instatiate */
55      private MessageUtils()
56      {
57          // nope
58      }
59  
60      /*** Default bundle for messages (<code>javax.faces.Messages</code>) */
61      private static final String DEFAULT_BUNDLE = "javax.faces.Messages";
62  
63      /*** Suffix for message details (<code>_detail</code>)*/
64      private static final String DETAIL_SUFFIX = "_detail";
65      private static Log log = LogFactory.getLog(MessageUtils.class);
66  
67      /***
68       * @param severity serverity of message
69       * @param messageId id of message
70       * @param arg arument of message
71       *
72       * @return generated FacesMessage
73       */
74      public static FacesMessage getMessage(FacesMessage.Severity severity,
75                                            String messageId,
76                                            Object arg)
77      {
78          return getMessage(severity,
79                            messageId,
80                            new Object[]{arg},
81                            FacesContext.getCurrentInstance());
82      }
83      
84      public static FacesMessage getMessage(String bundleBaseName, 
85              FacesMessage.Severity severity,
86              String messageId,
87              Object arg)
88      {
89          return getMessage(bundleBaseName,
90                            severity,
91                            messageId,
92                            new Object[]{arg},
93                            FacesContext.getCurrentInstance());
94      }
95  
96      /***
97       * @param severity serverity of message
98       * @param messageId id of message
99       * @param args aruments of message
100      *
101      * @return generated FacesMessage
102      */
103     public static FacesMessage getMessage(FacesMessage.Severity severity,
104                                           String messageId,
105                                           Object[] args)
106     {
107         return getMessage(severity,
108                           messageId,
109                           args,
110                           FacesContext.getCurrentInstance());
111     }
112     
113     public static FacesMessage getMessage(String bundleBaseName, 
114             FacesMessage.Severity severity,
115             String messageId,
116             Object[] args)
117     {
118         return getMessage(bundleBaseName,
119                           severity,
120                           messageId,
121                           args,
122                           FacesContext.getCurrentInstance());
123     }    
124 
125     public static FacesMessage getMessage(FacesMessage.Severity severity,
126                                           String messageId,
127                                           Object[] args,
128                                           FacesContext facesContext)
129     {
130         FacesMessage message = getMessage(facesContext, messageId, args);
131         message.setSeverity(severity);
132 
133         return message;
134     }
135 
136     public static FacesMessage getMessage(String bundleBaseName,
137             FacesMessage.Severity severity,
138             String messageId,
139             Object[] args,
140             FacesContext facesContext)
141     {
142         FacesMessage message = getMessage(bundleBaseName, facesContext, messageId, args);
143         message.setSeverity(severity);
144         
145         return message;
146     }
147 
148     public static void addMessage(FacesMessage.Severity severity,
149                                   String messageId,
150                                   Object[] args)
151     {
152         addMessage(severity, messageId, args, null, FacesContext.getCurrentInstance());
153     }
154 
155     public static void addMessage(String bundleBaseName, 
156             FacesMessage.Severity severity,
157             String messageId,
158             Object[] args)
159     {
160         addMessage(bundleBaseName, severity, messageId, args, null, FacesContext.getCurrentInstance());
161     }
162 
163     public static void addMessage(FacesMessage.Severity severity,
164                                   String messageId,
165                                   Object[] args,
166                                   FacesContext facesContext)
167     {
168         addMessage(severity, messageId, args, null, facesContext);
169     }
170 
171     public static void addMessage(String bundleBaseName, 
172             FacesMessage.Severity severity,
173             String messageId,
174             Object[] args,
175             FacesContext facesContext)
176     {
177         addMessage(bundleBaseName, severity, messageId, args, null, facesContext);
178     }
179 
180     public static void addMessage(FacesMessage.Severity severity,
181                                   String messageId,
182                                   Object[] args,
183                                   String forClientId)
184     {
185         addMessage(severity, messageId, args, forClientId, FacesContext.getCurrentInstance());
186     }
187 
188     public static void addMessage(String bundleBaseName,
189             FacesMessage.Severity severity,
190             String messageId,
191             Object[] args,
192             String forClientId)
193     {
194         addMessage(bundleBaseName, severity, messageId, args, forClientId, FacesContext.getCurrentInstance());
195     }
196 
197     public static void addMessage(FacesMessage.Severity severity,
198                                   String messageId,
199                                   Object[] args,
200                                   String forClientId,
201                                   FacesContext facesContext)
202     {
203         if(log.isTraceEnabled()) {
204           log.trace("adding message " + messageId + " for clientId " + forClientId);
205         }
206         facesContext.addMessage(forClientId,
207                                 getMessage(severity, messageId, args, facesContext));
208     }
209 
210     public static void addMessage(String bundleBaseName,
211             FacesMessage.Severity severity,
212             String messageId,
213             Object[] args,
214             String forClientId,
215             FacesContext facesContext)
216     {
217         if(log.isTraceEnabled()) {
218         log.trace("adding message " + messageId + " for clientId " + forClientId);
219         }
220         facesContext.addMessage(forClientId,
221                   getMessage(bundleBaseName, severity, messageId, args, facesContext));
222     }
223 
224     /***
225      * Uses <code>MessageFormat</code> and the supplied parameters to fill in the param placeholders in the String.
226      *
227      * @param locale The <code>Locale</code> to use when performing the substitution.
228      * @param msgtext The original parameterized String.
229      * @param params The params to fill in the String with.
230      * @return The updated String.
231      */
232     public static String substituteParams(Locale locale, String msgtext, Object params[])
233     {
234         String localizedStr = null;
235         if(params == null || msgtext == null)
236             return msgtext;
237 
238         if(locale != null)
239         {
240             MessageFormat mf = new MessageFormat(msgtext,locale);            
241             localizedStr = mf.format(params);
242         }
243         return localizedStr;
244     }
245 
246     public static FacesMessage getMessage(String messageId, Object params[])
247     {
248         Locale locale = getCurrentLocale();
249         return getMessage(locale, messageId, params);
250     }
251 
252     public static FacesMessage getMessageFromBundle(String bundleBaseName, String messageId, Object params[])
253     {
254         Locale locale = null;
255         FacesContext context = FacesContext.getCurrentInstance();
256         if(context != null && context.getViewRoot() != null)
257         {
258             locale = context.getViewRoot().getLocale();
259             if(locale == null)
260                 locale = Locale.getDefault();
261         } else
262         {
263             locale = Locale.getDefault();
264         }
265         return getMessageFromBundle(bundleBaseName, context , locale, messageId, params);
266     }
267 
268     public static FacesMessage getMessage(Locale locale, String messageId, Object params[])
269     {
270         String summary = null;
271         String detail = null;
272         String bundleName = getApplication().getMessageBundle();
273         ResourceBundle bundle = null;
274 
275         if (bundleName != null)
276         {
277             try
278             {
279                 bundle = ResourceBundle.getBundle(bundleName, locale, org.apache.myfaces.shared.util.ClassUtils.getCurrentLoader(bundleName));
280                 summary = bundle.getString(messageId);
281             }
282             catch (MissingResourceException e) {
283                 // NoOp
284             }
285         }
286 
287         if (summary == null)
288         {
289             try
290             {
291                 bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, org.apache.myfaces.shared.util.ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
292                 if(bundle == null)
293                 {
294                     throw new NullPointerException();
295                 }
296                 summary = bundle.getString(messageId);
297             }
298             catch(MissingResourceException e) {
299                 // NoOp
300             }
301         }
302 
303         if(summary == null)
304         {
305             summary = messageId;
306         }
307 
308         if (bundle == null)
309         {
310             throw new NullPointerException(
311                 "Unable to locate ResourceBundle: bundle is null");
312         }
313         if (params != null && locale != null)
314         {
315             try
316             {
317                 detail = bundle.getString(messageId + DETAIL_SUFFIX);
318             }
319             catch(MissingResourceException e) {
320                 // NoOp
321             }
322             return new ParametrizableFacesMessage(summary, detail, params, locale);
323         }
324         else
325         {
326             summary = substituteParams(locale, summary, params);
327             try
328             {
329                 detail = substituteParams(locale,
330                     bundle.getString(messageId + DETAIL_SUFFIX), params);
331             }
332             catch(MissingResourceException e) {
333                 // NoOp
334             }
335             return new FacesMessage(summary, detail);
336         }
337     }
338     
339     public static FacesMessage getMessageFromBundle(String bundleBaseName, FacesContext context, Locale locale, String messageId, Object params[])
340     {
341         String summary = null;
342         String detail = null;
343         String bundleName = context.getApplication().getMessageBundle();
344         ResourceBundle bundle = null;
345 
346         if (bundleName != null)
347         {
348             try
349             {
350                 bundle = ResourceBundle.getBundle(bundleName, locale, org.apache.myfaces.shared.util.ClassUtils.getCurrentLoader(bundleName));
351                 summary = bundle.getString(messageId);
352             }
353             catch (MissingResourceException e) {
354                 // NoOp
355             }
356         }
357 
358         if (summary == null)
359         {
360             try
361             {
362                 bundle = ResourceBundle.getBundle(bundleBaseName, locale, org.apache.myfaces.shared.util.ClassUtils.getCurrentLoader(bundleBaseName));
363                 if(bundle == null)
364                 {
365                     throw new NullPointerException();
366                 }
367                 summary = bundle.getString(messageId);
368             }
369             catch(MissingResourceException e) {
370                 // NoOp
371             }
372         }
373         
374         if (summary == null)
375         {
376             try
377             {
378                 bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, org.apache.myfaces.shared.util.ClassUtils.getCurrentLoader(DEFAULT_BUNDLE));
379                 if(bundle == null)
380                 {
381                     throw new NullPointerException();
382                 }
383                 summary = bundle.getString(messageId);
384             }
385             catch(MissingResourceException e) {
386                 // NoOp
387             }
388         }
389 
390         if(summary == null)
391         {
392             summary = messageId;
393         }
394 
395         if (bundle == null)
396         {
397             throw new NullPointerException(
398                 "Unable to locate ResourceBundle: bundle is null");
399         }
400         
401         if (params != null && locale != null)
402         {
403             try
404             {
405                 detail = bundle.getString(messageId + DETAIL_SUFFIX);
406             }
407             catch(MissingResourceException e) {
408                 // NoOp
409             }
410             return new ParametrizableFacesMessage(summary, detail, params, locale);
411         }
412         else
413         {
414             summary = substituteParams(locale, summary, params);
415             try
416             {
417                 detail = substituteParams(locale,
418                     bundle.getString(messageId + DETAIL_SUFFIX), params);
419             }
420             catch(MissingResourceException e) {
421                 // NoOp
422             }
423             return new FacesMessage(summary, detail);
424         }
425     }
426 
427     /***
428      *  Retrieve the message from a specific bundle. It does not look on application message bundle
429      * or default message bundle. If it is required to look on those bundles use getMessageFromBundle instead
430      * 
431      * @param bundleBaseName baseName of ResourceBundle to load localized messages
432      * @param messageId id of message
433      * @param params parameters to set at localized message
434      * @return generated FacesMessage
435      */
436     public static FacesMessage getMessage(String bundleBaseName, String messageId, Object params[])
437     {
438         return getMessage(bundleBaseName, getCurrentLocale(), messageId, params);
439     }
440     
441     /***
442      * 
443      * @return  currently applicable Locale for this request.
444      */
445     public static Locale getCurrentLocale() {
446         return getCurrentLocale(FacesContext.getCurrentInstance());
447     }
448     
449     public static Locale getCurrentLocale(FacesContext context) {
450         Locale locale;
451         if(context != null && context.getViewRoot() != null)
452         {
453             locale = context.getViewRoot().getLocale();
454             if(locale == null)
455                 locale = Locale.getDefault();
456         }
457         else
458         {
459             locale = Locale.getDefault();
460         }
461         
462         return locale;
463     }
464 
465     /***
466      * @param severity severity of message
467      * @param bundleBaseName baseName of ResourceBundle to load localized messages
468      * @param messageId id of message
469      * @param params parameters to set at localized message
470      * @return generated FacesMessage
471      */
472     public static FacesMessage getMessage(FacesMessage.Severity severity, String bundleBaseName, String messageId, Object params[])
473     {
474       FacesMessage msg = getMessage(bundleBaseName, messageId, params);
475       msg.setSeverity(severity);
476 
477       return msg;
478     }
479 
480     /***
481      *  Retrieve the message from a specific bundle. It does not look on application message bundle
482      * or default message bundle. If it is required to look on those bundles use getMessageFromBundle instead
483      * 
484      * @param bundleBaseName baseName of ResourceBundle to load localized messages
485      * @param locale current locale
486      * @param messageId id of message
487      * @param params parameters to set at localized message
488      * @return generated FacesMessage
489      */
490     public static FacesMessage getMessage(String bundleBaseName, Locale locale, String messageId, Object params[])
491     {
492       if (bundleBaseName == null)
493       {
494           throw new NullPointerException(
495               "Unable to locate ResourceBundle: bundle is null");
496       }
497 
498       ResourceBundle bundle = ResourceBundle.getBundle(bundleBaseName, locale);
499 
500       return getMessage(bundle, messageId, params);
501     }
502     /***
503      * @param bundle ResourceBundle to load localized messages
504      * @param messageId id of message
505      * @param params parameters to set at localized message
506      * @return generated FacesMessage
507      */
508     public static FacesMessage getMessage(ResourceBundle bundle, String messageId, Object params[])
509     {
510 
511       String summary = null;
512       String detail = null;
513 
514       try
515       {
516           summary = bundle.getString(messageId);
517       }
518       catch (MissingResourceException e) {
519         // NoOp
520       }
521 
522 
523       if(summary == null)
524       {
525           summary = messageId;
526       }
527 
528       summary = substituteParams(bundle.getLocale(), summary, params);
529 
530       try
531       {
532           detail = substituteParams(bundle.getLocale(),
533               bundle.getString(messageId + DETAIL_SUFFIX), params);
534       }
535       catch(MissingResourceException e) {
536         // NoOp
537       }
538 
539       return new FacesMessage(summary, detail);
540     }
541 
542     /***
543      *
544      * @param context
545      * @param messageId
546      * @return generated FacesMessage
547      */
548     public static FacesMessage getMessage(FacesContext context, String messageId)
549     {
550         return getMessage(context, messageId, ((Object []) (null)));
551     }
552     
553     public static FacesMessage getMessage(String bundleBaseName, FacesContext context, String messageId)
554     {
555         return getMessage(bundleBaseName, context, messageId, ((Object []) (null)));
556     }
557 
558     /***
559      *
560      * @param context
561      * @param messageId
562      * @param params
563      * @return generated FacesMessage
564      */
565     public static FacesMessage getMessage(FacesContext context, String messageId, Object params[])
566     {
567         if(context == null || messageId == null)
568             throw new NullPointerException(" context " + context + " messageId " + messageId);
569         Locale locale = getCurrentLocale(context);
570         if(null == locale)
571             throw new NullPointerException(" locale " + locale);
572         FacesMessage message = getMessage(locale, messageId, params);
573         if(message != null)
574         {
575             return message;
576         } else
577         {
578             // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
579             // but similar behavior above does not.  The methods should probably behave
580             locale = Locale.getDefault();
581             return getMessage(locale, messageId, params);
582         }
583     }
584     
585     public static FacesMessage getMessage(String bundleBaseName, FacesContext context, String messageId, Object params[])
586     {
587         if(context == null || messageId == null)
588             throw new NullPointerException(" context " + context + " messageId " + messageId);
589         Locale locale = getCurrentLocale(context);
590         if(null == locale)
591             throw new NullPointerException(" locale " + locale);
592         FacesMessage message = getMessageFromBundle(bundleBaseName, context, locale, messageId, params);
593         if(message != null)
594         {
595             return message;
596         } else
597         {
598             // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
599             // but similar behavior above does not.  The methods should probably behave
600             locale = Locale.getDefault();
601             return getMessageFromBundle(bundleBaseName, context, locale, messageId, params);
602         }
603     }
604     
605     public static Object getLabel(FacesContext facesContext, UIComponent component) {
606         Object label = component.getAttributes().get("label");
607         if(label != null)
608             return label;
609         
610         ValueExpression expression = component.getValueExpression("label");
611         if(expression != null)
612             return expression;
613         
614         //If no label is not specified, use clientId
615         return component.getClientId( facesContext );
616     }
617 
618     private static Application getApplication()
619     {
620         FacesContext context = FacesContext.getCurrentInstance();
621         if(context != null)
622         {
623             return context.getApplication();
624         } else
625         {
626             ApplicationFactory afactory = (ApplicationFactory)FactoryFinder.getFactory("javax.faces.application.ApplicationFactory");
627             return afactory.getApplication();
628         }
629     }
630 }