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  
20  package org.apache.myfaces.tobago.util;
21  
22  import org.apache.commons.beanutils.ConstructorUtils;
23  import org.apache.myfaces.tobago.application.LabelValueExpressionFacesMessage;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import javax.el.ValueExpression;
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 to create and add {@link FacesMessage} object to the context.
38   * The message will be internationalized with a bundle in the following order:
39   * <ol>
40   * <li>Application bundle</li>
41   * <li>Tobago bundle</li>
42   * <li>Default JSF bundle</li>
43   * </ol>
44   */
45  public class MessageUtils {
46  
47    private static final Logger LOG = LoggerFactory.getLogger(MessageUtils.class);
48  
49    private static final String DETAIL_SUFFIX = "_detail";
50  
51    public static void addMessage(
52        FacesContext facesContext, UIComponent component, FacesMessage.Severity severity,
53        String messageId, Object[] args) {
54      facesContext.addMessage(component.getClientId(facesContext),
55          getMessage(facesContext, facesContext.getViewRoot().getLocale(), severity, messageId, args));
56    }
57  
58    public static FacesMessage getMessage(
59        FacesContext facesContext, Locale locale,
60        FacesMessage.Severity severity, String messageId, Object... args) {
61  
62      ResourceBundle appBundle = getApplicationBundle(facesContext, locale);
63      String summary = getBundleString(appBundle, messageId);
64      String detail = getBundleString(appBundle, messageId + DETAIL_SUFFIX);
65  
66      if (summary == null || detail == null) {
67        ResourceBundle tobagoBundle = getTobagoBundle();
68        if (summary == null) {
69          summary = getBundleString(tobagoBundle, messageId);
70        }
71        if (detail == null) {
72          detail = getBundleString(tobagoBundle, messageId + DETAIL_SUFFIX);
73        }
74  
75        if (summary == null || detail == null) {
76          ResourceBundle defBundle = getDefaultBundle(facesContext, locale);
77          if (summary == null) {
78            summary = getBundleString(defBundle, messageId);
79          }
80          if (detail == null) {
81            detail = getBundleString(defBundle, messageId + DETAIL_SUFFIX);
82          }
83        }
84      }
85  
86      if (summary == null && detail == null) {
87        //Neither detail nor summary found
88        facesContext.getExternalContext().log("No message with id " + messageId + " found in any bundle");
89        return new FacesMessage(severity, messageId, null);
90      }
91  
92      if (args != null && args.length > 0) {
93        MessageFormat format;
94        if (summary != null) {
95          format = new MessageFormat(summary, locale);
96          summary = format.format(args);
97        }
98  
99        if (detail != null) {
100         format = new MessageFormat(detail, locale);
101         detail = format.format(args);
102       }
103     }
104     return new LabelValueExpressionFacesMessage(severity, summary, detail);
105   }
106 
107   private static String getBundleString(ResourceBundle bundle, String key) {
108     try {
109       return bundle == null ? null : bundle.getString(key);
110     } catch (MissingResourceException e) {
111       return null;
112     }
113   }
114 
115   private static ResourceBundle getApplicationBundle(FacesContext facesContext, Locale locale) {
116     String bundleName = facesContext.getApplication().getMessageBundle();
117     return bundleName != null ? getBundle(facesContext, locale, bundleName) : null;
118   }
119 
120   private static ResourceBundle getTobagoBundle() {
121     // XXX This is ugly, can be removed after merging tobago-jsf-compat to tobago-core
122     try {
123       Class clazz = Class.forName("org.apache.myfaces.tobago.context.TobagoResourceBundle");
124       Object bundle = ConstructorUtils.invokeConstructor(clazz, new Object[0]);
125       LOG.error("*********************************************************************************************");
126       LOG.error("*********************************************************************************************");
127       LOG.error("*********************************************************************************************");
128       LOG.error("just created: " + bundle + " " + System.identityHashCode(bundle));
129       LOG.error("*********************************************************************************************");
130       LOG.error("*********************************************************************************************");
131       LOG.error("*********************************************************************************************");
132       return (ResourceBundle) bundle;
133     } catch (Exception e) {
134       LOG.error("Can't create TobagoResourceBundle, but it should be in the core.", e);
135       return null; // should not be possible.
136     }
137   }
138 
139   private static ResourceBundle getDefaultBundle(FacesContext facesContext, Locale locale) {
140     return getBundle(facesContext, locale, FacesMessage.FACES_MESSAGES);
141   }
142 
143   private static ResourceBundle getBundle(FacesContext facesContext, Locale locale, String bundleName) {
144     try {
145       return ResourceBundle.getBundle(bundleName, locale, MessageUtils.class.getClassLoader());
146     } catch (MissingResourceException ignore2) {
147       try {
148         return ResourceBundle.getBundle(bundleName, locale, Thread.currentThread().getContextClassLoader());
149       } catch (MissingResourceException damned) {
150         facesContext.getExternalContext().log("resource bundle " + bundleName + " could not be found");
151         return null;
152       }
153     }
154   }
155 
156   public static String getLabel(FacesContext facesContext, UIComponent component) {
157     Object label = component.getAttributes().get("label");
158     if (label != null) {
159       return label.toString();
160     }
161     final ValueExpression expression = component.getValueExpression("label");
162     if (expression != null) {
163       return expression.getExpressionString();
164     }
165     return component.getClientId(facesContext);
166   }
167 
168   /**
169    * @deprecated
170    */
171   @Deprecated
172   public static String getFormatedMessage(String message, Locale locale, Object... args) {
173     if (args != null && args.length > 0 && message != null) {
174       MessageFormat format = new MessageFormat(message, locale);
175       return format.format(args);
176     }
177     return message;
178   }
179 }