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