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