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: lu4242 $)
46   * @author Manfred Geiler
47   * @author Sean Schofield
48   * @author Stpehan Strittmatter
49   * @version $Revision: 1003673 $ $Date: 2010-10-01 17:11:09 -0500 (Fri, 01 Oct 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         StringBuffer b = new StringBuffer(100);
237         MessageFormat mf = new MessageFormat(msgtext);
238         if(locale != null)
239         {
240             mf.setLocale(locale);
241             b.append(mf.format(((Object) (params))));
242             localizedStr = b.toString();
243         }
244         return localizedStr;
245     }
246 
247     public static FacesMessage getMessage(String messageId, Object params[])
248     {
249         Locale locale = getCurrentLocale();
250         return getMessage(locale, messageId, params);
251     }
252 
253     public static FacesMessage getMessageFromBundle(String bundleBaseName, String messageId, Object params[])
254     {
255         Locale locale = null;
256         FacesContext context = FacesContext.getCurrentInstance();
257         if(context != null && context.getViewRoot() != null)
258         {
259             locale = context.getViewRoot().getLocale();
260             if(locale == null)
261                 locale = Locale.getDefault();
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, getCurrentLoader(bundleName));
281                 summary = bundle.getString(messageId);
282             }
283             catch (MissingResourceException e) {
284                 // NoOp
285             }
286         }
287 
288         if (summary == null)
289         {
290             try
291             {
292                 bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, getCurrentLoader(DEFAULT_BUNDLE));
293                 if(bundle == null)
294                 {
295                     throw new NullPointerException();
296                 }
297                 summary = bundle.getString(messageId);
298             }
299             catch(MissingResourceException e) {
300                 // NoOp
301             }
302         }
303 
304         if(summary == null)
305         {
306             summary = messageId;
307         }
308 
309         if (bundle == null)
310         {
311             throw new NullPointerException(
312                 "Unable to locate ResourceBundle: bundle is null");
313         }
314         if (params != null && locale != null)
315         {
316             try
317             {
318                 detail = bundle.getString(messageId + DETAIL_SUFFIX);
319             }
320             catch(MissingResourceException e) {
321                 // NoOp
322             }
323             return new ParametrizableFacesMessage(summary, detail, params, locale);
324         }
325         else
326         {
327             summary = substituteParams(locale, summary, params);
328             try
329             {
330                 detail = substituteParams(locale,
331                     bundle.getString(messageId + DETAIL_SUFFIX), params);
332             }
333             catch(MissingResourceException e) {
334                 // NoOp
335             }
336             return new FacesMessage(summary, detail);
337         }
338     }
339     
340     public static FacesMessage getMessageFromBundle(String bundleBaseName, FacesContext context, Locale locale, String messageId, Object params[])
341     {
342         String summary = null;
343         String detail = null;
344         String bundleName = context.getApplication().getMessageBundle();
345         ResourceBundle bundle = null;
346 
347         if (bundleName != null)
348         {
349             try
350             {
351                 bundle = ResourceBundle.getBundle(bundleName, locale, getCurrentLoader(bundleName));
352                 summary = bundle.getString(messageId);
353             }
354             catch (MissingResourceException e) {
355                 // NoOp
356             }
357         }
358 
359         if (summary == null)
360         {
361             try
362             {
363                 bundle = ResourceBundle.getBundle(bundleBaseName, locale, getCurrentLoader(bundleBaseName));
364                 if(bundle == null)
365                 {
366                     throw new NullPointerException();
367                 }
368                 summary = bundle.getString(messageId);
369             }
370             catch(MissingResourceException e) {
371                 // NoOp
372             }
373         }
374         
375         if (summary == null)
376         {
377             try
378             {
379                 bundle = ResourceBundle.getBundle(DEFAULT_BUNDLE, locale, getCurrentLoader(DEFAULT_BUNDLE));
380                 if(bundle == null)
381                 {
382                     throw new NullPointerException();
383                 }
384                 summary = bundle.getString(messageId);
385             }
386             catch(MissingResourceException e) {
387                 // NoOp
388             }
389         }
390 
391         if(summary == null)
392         {
393             summary = messageId;
394         }
395 
396         if (bundle == null)
397         {
398             throw new NullPointerException(
399                 "Unable to locate ResourceBundle: bundle is null");
400         }
401         
402         if (params != null && locale != null)
403         {
404             try
405             {
406                 detail = bundle.getString(messageId + DETAIL_SUFFIX);
407             }
408             catch(MissingResourceException e) {
409                 // NoOp
410             }
411             return new ParametrizableFacesMessage(summary, detail, params, locale);
412         }
413         else
414         {
415             summary = substituteParams(locale, summary, params);
416             try
417             {
418                 detail = substituteParams(locale,
419                     bundle.getString(messageId + DETAIL_SUFFIX), params);
420             }
421             catch(MissingResourceException e) {
422                 // NoOp
423             }
424             return new FacesMessage(summary, detail);
425         }
426     }
427 
428     /**
429      *  Retrieve the message from a specific bundle. It does not look on application message bundle
430      * or default message bundle. If it is required to look on those bundles use getMessageFromBundle instead
431      * 
432      * @param bundleBaseName baseName of ResourceBundle to load localized messages
433      * @param messageId id of message
434      * @param params parameters to set at localized message
435      * @return generated FacesMessage
436      */
437     public static FacesMessage getMessage(String bundleBaseName, String messageId, Object params[])
438     {
439         return getMessage(bundleBaseName, getCurrentLocale(), messageId, params);
440     }
441     
442     /**
443      * 
444      * @return  currently applicable Locale for this request.
445      */
446     public static Locale getCurrentLocale() {
447         return getCurrentLocale(FacesContext.getCurrentInstance());
448     }
449     
450     public static Locale getCurrentLocale(FacesContext context) {
451         Locale locale;
452         if(context != null && context.getViewRoot() != null)
453         {
454             locale = context.getViewRoot().getLocale();
455             if(locale == null)
456                 locale = Locale.getDefault();
457         }
458         else
459         {
460             locale = Locale.getDefault();
461         }
462         
463         return locale;
464     }
465 
466     /**
467      * @param severity severity of message
468      * @param bundleBaseName baseName of ResourceBundle to load localized messages
469      * @param messageId id of message
470      * @param params parameters to set at localized message
471      * @return generated FacesMessage
472      */
473     public static FacesMessage getMessage(FacesMessage.Severity severity, String bundleBaseName, String messageId, Object params[])
474     {
475       FacesMessage msg = getMessage(bundleBaseName, messageId, params);
476       msg.setSeverity(severity);
477 
478       return msg;
479     }
480 
481     /**
482      *  Retrieve the message from a specific bundle. It does not look on application message bundle
483      * or default message bundle. If it is required to look on those bundles use getMessageFromBundle instead
484      * 
485      * @param bundleBaseName baseName of ResourceBundle to load localized messages
486      * @param locale current locale
487      * @param messageId id of message
488      * @param params parameters to set at localized message
489      * @return generated FacesMessage
490      */
491     public static FacesMessage getMessage(String bundleBaseName, Locale locale, String messageId, Object params[])
492     {
493       if (bundleBaseName == null)
494       {
495           throw new NullPointerException(
496               "Unable to locate ResourceBundle: bundle is null");
497       }
498 
499       ResourceBundle bundle = ResourceBundle.getBundle(bundleBaseName, locale);
500 
501       return getMessage(bundle, messageId, params);
502     }
503     /**
504      * @param bundle ResourceBundle to load localized messages
505      * @param messageId id of message
506      * @param params parameters to set at localized message
507      * @return generated FacesMessage
508      */
509     public static FacesMessage getMessage(ResourceBundle bundle, String messageId, Object params[])
510     {
511 
512       String summary = null;
513       String detail = null;
514 
515       try
516       {
517           summary = bundle.getString(messageId);
518       }
519       catch (MissingResourceException e) {
520         // NoOp
521       }
522 
523 
524       if(summary == null)
525       {
526           summary = messageId;
527       }
528 
529       summary = substituteParams(bundle.getLocale(), summary, params);
530 
531       try
532       {
533           detail = substituteParams(bundle.getLocale(),
534               bundle.getString(messageId + DETAIL_SUFFIX), params);
535       }
536       catch(MissingResourceException e) {
537         // NoOp
538       }
539 
540       return new FacesMessage(summary, detail);
541     }
542 
543     /**
544      *
545      * @param context
546      * @param messageId
547      * @return generated FacesMessage
548      */
549     public static FacesMessage getMessage(FacesContext context, String messageId)
550     {
551         return getMessage(context, messageId, ((Object []) (null)));
552     }
553     
554     public static FacesMessage getMessage(String bundleBaseName, FacesContext context, String messageId)
555     {
556         return getMessage(bundleBaseName, context, messageId, ((Object []) (null)));
557     }
558 
559     /**
560      *
561      * @param context
562      * @param messageId
563      * @param params
564      * @return generated FacesMessage
565      */
566     public static FacesMessage getMessage(FacesContext context, String messageId, Object params[])
567     {
568         if(context == null || messageId == null)
569             throw new NullPointerException(" context " + context + " messageId " + messageId);
570         Locale locale = getCurrentLocale(context);
571         if(null == locale)
572             throw new NullPointerException(" locale " + locale);
573         FacesMessage message = getMessage(locale, messageId, params);
574         if(message != null)
575         {
576             return message;
577         } else
578         {
579             // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
580             // but similar behavior above does not.  The methods should probably behave
581             locale = Locale.getDefault();
582             return getMessage(locale, messageId, params);
583         }
584     }
585     
586     public static FacesMessage getMessage(String bundleBaseName, FacesContext context, String messageId, Object params[])
587     {
588         if(context == null || messageId == null)
589             throw new NullPointerException(" context " + context + " messageId " + messageId);
590         Locale locale = getCurrentLocale(context);
591         if(null == locale)
592             throw new NullPointerException(" locale " + locale);
593         FacesMessage message = getMessageFromBundle(bundleBaseName, context, locale, messageId, params);
594         if(message != null)
595         {
596             return message;
597         } else
598         {
599             // TODO /FIX:  Note that this has fallback behavior to default Locale for message,
600             // but similar behavior above does not.  The methods should probably behave
601             locale = Locale.getDefault();
602             return getMessageFromBundle(bundleBaseName, context, locale, messageId, params);
603         }
604     }
605     
606     public static Object getLabel(FacesContext facesContext, UIComponent component) {
607         Object label = component.getAttributes().get("label");
608         if(label != null)
609             return label;
610         
611         ValueExpression expression = component.getValueExpression("label");
612         if(expression != null)
613             return expression;
614         
615         //If no label is not specified, use clientId
616         return component.getClientId( facesContext );
617     }
618 
619     private static Application getApplication()
620     {
621         FacesContext context = FacesContext.getCurrentInstance();
622         if(context != null)
623         {
624             return context.getApplication();
625         } else
626         {
627             ApplicationFactory afactory = (ApplicationFactory)FactoryFinder.getFactory("javax.faces.application.ApplicationFactory");
628             return afactory.getApplication();
629         }
630     }
631     
632     private static ClassLoader getCurrentLoader(Object defaultObject)
633     {
634         ClassLoader loader = Thread.currentThread().getContextClassLoader();
635         if(loader == null)
636         {
637             loader = defaultObject.getClass().getClassLoader();
638         }
639         return loader;
640     }
641     
642 }