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.extensions.validator.core.validation.message.resolver;
20  
21  import org.apache.myfaces.extensions.validator.core.ExtValContext;
22  import org.apache.myfaces.extensions.validator.core.CustomInformation;
23  import org.apache.myfaces.extensions.validator.core.ExtValCoreConfiguration;
24  import org.apache.myfaces.extensions.validator.core.el.ELHelper;
25  import org.apache.myfaces.extensions.validator.internal.UsageInformation;
26  import org.apache.myfaces.extensions.validator.internal.UsageCategory;
27  import org.apache.myfaces.extensions.validator.util.ExtValUtils;
28  
29  import java.util.Locale;
30  import java.util.MissingResourceException;
31  import java.util.ResourceBundle;
32  import java.util.logging.Logger;
33  import java.util.logging.Level;
34  
35  /**
36   * MessageResolver which uses property files.
37   * Subclasses just have to provide the package to look at.
38   * An implementation can also provide a custom name which is e.g. configured via web.xml.
39   *
40   * @since 1.x.1
41   */
42  @UsageInformation({UsageCategory.INTERNAL, UsageCategory.CUSTOMIZABLE})
43  public abstract class AbstractValidationErrorMessageResolver implements MessageResolver
44  {
45      public static final String MISSING_RESOURCE_MARKER = "???";
46  
47      protected final Logger logger = Logger.getLogger(getClass().getName());
48  
49      private static boolean deactivateDefaultConvention = ExtValCoreConfiguration.get().deactivateDefaultConvention();
50      private static ResourceBundle defaultBundle = null;
51      private String messageBundleBaseName;
52      //with jsf 1.1 only available if there is a custom bean
53      private String messageBundleVarName;
54  
55      private ELHelper elHelper = ExtValUtils.getELHelper();
56  
57      protected AbstractValidationErrorMessageResolver()
58      {
59          logger.fine(getClass().getName() + " instantiated");
60      }
61  
62      public String getMessage(String key, Locale locale)
63      {
64          if (key == null || key.equals(""))
65          {
66              return null;
67          }
68  
69          if(key.contains(" "))
70          {
71              if(key.endsWith("_detail"))
72              {
73                  key = key.substring(0, key.length() - 7);
74              }
75              return key;
76          }
77  
78          String customMessage = null;
79  
80          try
81          {
82              customMessage = tryToFindCustomMessage(key, locale);
83          }
84          catch (Exception e)
85          {
86              //do nothing
87          }
88  
89          if (customMessage != null)
90          {
91              return customMessage;
92          }
93  
94          /*
95           * try to use the convention for the message bundle
96           */
97          try
98          {
99              customMessage = tryToUseMessageBundleConvention(key, locale);
100         }
101         catch (Exception e)
102         {
103             //do nothing
104         }
105 
106         if (customMessage != null)
107         {
108             return customMessage;
109         }
110 
111         /*
112          * no message bundle or message found (with the convention)?
113          */
114 
115         //try to load custom messages
116         try
117         {
118             customMessage = tryToFindCustomMessageInCustomResourceBundle(key, locale);
119         }
120         catch (Exception e)
121         {
122             //do nothing - it was just a try
123         }
124 
125         return determineMessage(key, locale, customMessage);
126     }
127 
128     private String tryToFindCustomMessage(String key, Locale locale)
129     {
130         ResourceBundle resourceBundle;
131         String customMessage = null;
132 
133         //only in case of a ValidationErrorMessageResolver which is configured as bean
134         if (this.messageBundleBaseName != null)
135         {
136             resourceBundle = ResourceBundle.getBundle(this.messageBundleBaseName, locale);
137             if (resourceBundle != null)
138             {
139                 customMessage = resourceBundle.getString(key);
140             }
141             else
142             {
143                 logger.warning("message bundle " + this.messageBundleBaseName + " not found");
144             }
145         }
146 
147         //only in case of a ValidationErrorMessageResolver which is configured as bean
148         if (this.messageBundleVarName != null && customMessage == null)
149         {
150             resourceBundle = (ResourceBundle) this.elHelper.getBean(messageBundleVarName);
151 
152             if (resourceBundle != null)
153             {
154                 customMessage = resourceBundle.getString(key);
155             }
156             else
157             {
158                 logger.warning("message bundle var name " + this.messageBundleVarName + " not found");
159             }
160         }
161 
162         return customMessage;
163     }
164 
165     private String tryToUseMessageBundleConvention(String key, Locale locale)
166     {
167         if (!deactivateDefaultConvention && isDefaultMessageBundleConventionActive())
168         {
169             if (defaultBundle == null)
170             {
171                 try
172                 {
173                     defaultBundle = ResourceBundle.getBundle(ExtValContext.getContext().getInformationProviderBean()
174                         .get(CustomInformation.MESSAGE_BUNDLE_NAME), locale);
175                 }
176                 catch (Exception e)
177                 {
178                     //do nothing
179                     deactivateDefaultConvention = true;
180                 }
181             }
182 
183             if (defaultBundle != null)
184             {
185                 return defaultBundle.getString(key);
186             }
187         }
188 
189         return null;
190     }
191 
192     private String tryToFindCustomMessageInCustomResourceBundle(String key, Locale locale)
193     {
194         ResourceBundle resourceBundle = tryToLoadCustomResourceBundle(locale);
195 
196         if (resourceBundle != null)
197         {
198             try
199             {
200                 return resourceBundle.getString(key);
201             }
202             catch (MissingResourceException e)
203             {
204                 logger.log(Level.FINEST, "no custom message for " + key + " within " + getCustomBaseName(), e);
205             }
206         }
207         return null;
208     }
209 
210     private ResourceBundle tryToLoadCustomResourceBundle(Locale locale)
211     {
212         String customBaseName = getCustomBaseName();
213 
214         if(customBaseName != null)
215         {
216             return ResourceBundle.getBundle(customBaseName, locale);
217         }
218         return null;
219     }
220 
221     private String determineMessage(String key, Locale locale, String customMessage)
222     {
223         //use custom name (if possible) otherwise: fallback to default message (if possible)
224         try
225         {
226             return (customMessage != null) ? customMessage
227                     : (getBaseName() != null) ? ResourceBundle.getBundle(getBaseName(), locale).getString(key) : null;
228         }
229         catch (MissingResourceException e)
230         {
231             return MISSING_RESOURCE_MARKER + key + MISSING_RESOURCE_MARKER;
232         }
233     }
234 
235     protected boolean isDefaultMessageBundleConventionActive()
236     {
237         return true;
238     }
239 
240     protected abstract String getBaseName();
241 
242     protected String getCustomBaseName()
243     {
244         return null;
245     }
246 
247     public void setMessageBundleBaseName(String messageBundleBaseName)
248     {
249         this.messageBundleBaseName = messageBundleBaseName;
250     }
251 
252     public void setMessageBundleVarName(String messageBundleVarName)
253     {
254         this.messageBundleVarName = messageBundleVarName;
255     }
256 }