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