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.validator;
20  
21  import java.io.Serializable;
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  
29  import javax.el.ValueExpression;
30  import javax.faces.application.FacesMessage;
31  import javax.faces.component.StateHolder;
32  import javax.faces.context.FacesContext;
33  import javax.faces.validator.Validator;
34  
35  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
36  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFValidator;
37  import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
38  import org.apache.myfaces.tomahawk.util.Constants;
39  
40  /**
41   * Base validator implementation for Apache MyFaces Commons Validators.
42   *
43   */
44  @JSFValidator(
45     configExcluded = true,
46     tagClass = "org.apache.myfaces.validator.ValidatorBaseTag",
47     tagHandler = "org.apache.myfaces.validator.ValidatorBaseTagHandler")
48  public abstract class ValidatorBase implements StateHolder, Validator {
49  
50      private String _summaryMessage = null;
51      private String _detailMessage = null;
52      private boolean _transient = false;
53  
54      /**
55       *
56       * 
57       * @return  The summary message to be displayed
58       */
59      @JSFProperty
60      public String getSummaryMessage()
61      {
62          if (_summaryMessage != null) return _summaryMessage;
63          ValueExpression expression = getValueExpression("summaryMessage");
64          return expression != null ? getStringValue(getFacesContext(), expression) : null;
65      }
66  
67      /**
68       *
69       * @param message   The summary message to be displayed.
70       */
71      public void setSummaryMessage(String message) {
72          _summaryMessage = message;
73      }
74  
75      /**
76       *
77       * 
78       * @return  The message.
79       * @deprecated Use getDetailMessage()
80       */
81      @JSFProperty
82      public String getMessage() {
83          return getDetailMessage();
84      }
85  
86      /**
87       *
88       * @param message  The detail message to be displayed.
89       * @deprecated Use setDetailMessage()
90       */
91      public void setMessage(String message) {
92          setDetailMessage(message);
93      }
94  
95  
96      /**
97       *
98       * 
99       * @return  The detail message.
100      */
101     @JSFProperty
102     public String getDetailMessage() {
103         if (_detailMessage != null) return _detailMessage;
104         ValueExpression vb = getValueExpression("detailMessage");
105         return vb != null ? getStringValue(getFacesContext(), vb) : null;
106     }
107 
108     /**
109      *
110      * @param message  The detail message to be displayed.
111      */
112     public void setDetailMessage(String message) {
113         _detailMessage = message;
114     }
115 
116 
117     /**
118      * @param context
119      */
120     public Object saveState(FacesContext context) {
121         Object[] state = new Object[3];
122         state[0] = _summaryMessage;
123         state[1] = _detailMessage;
124         state[2] = saveValueExpressionMap(context);
125         return state;
126     }
127 
128     public void restoreState(FacesContext context, Object state) {
129         Object[] values = (Object[]) state;
130         _summaryMessage = (String) values[0];
131         _detailMessage = (String) values[1];
132         restoreValueExpressionMap(context, values[2]);
133     }
134 
135     public boolean isTransient() {
136         return _transient;
137     }
138 
139     public void setTransient(boolean newTransientValue) {
140         _transient = newTransientValue;
141     }
142 
143     // Utility methods
144 
145     /**
146      * @param defaultMessage The default message we would expect.
147      * @param args Arguments for parsing this message.
148      * @return FacesMessage
149      */
150     protected FacesMessage getFacesMessage(String defaultMessage, Object[] args) {
151         FacesMessage msg;
152 
153         if (getSummaryMessage() == null && getDetailMessage() == null)
154         {
155             msg = MessageUtils.getMessage(Constants.TOMAHAWK_DEFAULT_BUNDLE, FacesMessage.SEVERITY_ERROR, defaultMessage, args);
156         } else {
157             Locale locale = MessageUtils.getCurrentLocale();
158             String summaryText = MessageUtils.substituteParams(locale, getSummaryMessage(), args);
159             String detailText = MessageUtils.substituteParams(locale, getDetailMessage(), args);
160             msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryText, detailText);
161         }
162         return msg;
163     }
164 
165     // --------------------- borrowed from UIComponentBase ------------
166 
167     private Map _valueExpressionMap = null;
168 
169     public ValueExpression getValueExpression(String name)
170     {
171         if (name == null) throw new NullPointerException("name");
172         if (_valueExpressionMap == null)
173         {
174             return null;
175         }
176         else
177         {
178             return (ValueExpression)_valueExpressionMap.get(name);
179         }
180     }
181 
182     public void setValueExpression(String name,
183                                 ValueExpression binding)
184     {
185         if (name == null) throw new NullPointerException("name");
186         if (_valueExpressionMap == null)
187         {
188             _valueExpressionMap = new HashMap();
189         }
190         _valueExpressionMap.put(name, binding);
191     }
192 
193     private Object saveValueExpressionMap(FacesContext context)
194     {
195         if (_valueExpressionMap != null)
196         {
197             int initCapacity = (_valueExpressionMap.size() * 4 + 3) / 3;
198             HashMap stateMap = new HashMap(initCapacity);
199             for (Iterator it = _valueExpressionMap.entrySet().iterator(); it.hasNext(); )
200             {
201                 Map.Entry entry = (Map.Entry)it.next();
202                 stateMap.put(entry.getKey(),
203                              saveAttachedState(context, entry.getValue()));
204             }
205             return stateMap;
206         }
207         else
208         {
209             return null;
210         }
211     }
212 
213     private void restoreValueExpressionMap(FacesContext context, Object stateObj)
214     {
215         if (stateObj != null)
216         {
217             Map stateMap = (Map)stateObj;
218             int initCapacity = (stateMap.size() * 4 + 3) / 3;
219             _valueExpressionMap = new HashMap(initCapacity);
220             for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
221             {
222                 Map.Entry entry = (Map.Entry)it.next();
223                 _valueExpressionMap.put(entry.getKey(),
224                                      restoreAttachedState(context, entry.getValue()));
225             }
226         }
227         else
228         {
229             _valueExpressionMap = null;
230         }
231     }
232 
233     /**
234      * Serializes objects which are "attached" to this component but which are
235      * not UIComponent children of it. Examples are validator and listener
236      * objects. To be precise, it returns an object which implements
237      * java.io.Serializable, and which when serialized will persist the
238      * state of the provided object.
239      * <p>
240      * If the attachedObject is a List then every object in the list is saved
241      * via a call to this method, and the returned wrapper object contains
242      * a List object.
243      * <p>
244      * If the object implements StateHolder then the object's saveState is
245      * called immediately, and a wrapper is returned which contains both
246      * this saved state and the original class name. However in the case
247      * where the StateHolder.isTransient method returns true, null is
248      * returned instead.
249      * <p>
250      * If the object implements java.io.Serializable then the object is simply
251      * returned immediately; standard java serialization will later be used
252      * to store this object.
253      * <p>
254      * In all other cases, a wrapper is returned which simply stores the type
255      * of the provided object. When deserialized, a default instance of that
256      * type will be recreated.
257      */
258     public static Object saveAttachedState(FacesContext context,
259                                            Object attachedObject)
260     {
261         if (attachedObject == null) return null;
262         if (attachedObject instanceof List)
263         {
264             List lst = new ArrayList(((List)attachedObject).size());
265             for (Iterator it = ((List)attachedObject).iterator(); it.hasNext(); )
266             {
267                 lst.add(saveAttachedState(context, it.next()));
268             }
269             return new AttachedListStateWrapper(lst);
270         }
271         else if (attachedObject instanceof StateHolder)
272         {
273             if (((StateHolder)attachedObject).isTransient())
274             {
275                 return null;
276             }
277             else
278             {
279                 return new AttachedStateWrapper(attachedObject.getClass(),
280                                                  ((StateHolder)attachedObject).saveState(context));
281             }
282         }
283         else if (attachedObject instanceof Serializable)
284         {
285             return attachedObject;
286         }
287         else
288         {
289             return new AttachedStateWrapper(attachedObject.getClass(), null);
290         }
291     }
292 
293     public static Object restoreAttachedState(FacesContext context,
294                                               Object stateObj)
295             throws IllegalStateException
296     {
297         if (context == null) throw new NullPointerException("context");
298         if (stateObj == null) return null;
299         if (stateObj instanceof AttachedListStateWrapper)
300         {
301             List lst = ((AttachedListStateWrapper)stateObj).getWrappedStateList();
302             List restoredList = new ArrayList(lst.size());
303             for (Iterator it = lst.iterator(); it.hasNext(); )
304             {
305                 restoredList.add(restoreAttachedState(context, it.next()));
306             }
307             return restoredList;
308         }
309         else if (stateObj instanceof AttachedStateWrapper)
310         {
311             Class clazz = ((AttachedStateWrapper)stateObj).getClazz();
312             Object restoredObject;
313             try
314             {
315                 restoredObject = clazz.newInstance();
316             }
317             catch (InstantiationException e)
318             {
319                 throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() + " (missing no-args constructor?)", e);
320             }
321             catch (IllegalAccessException e)
322             {
323                 throw new RuntimeException(e);
324             }
325             if (restoredObject instanceof StateHolder)
326             {
327                 Object wrappedState = ((AttachedStateWrapper)stateObj).getWrappedStateObject();
328                 ((StateHolder)restoredObject).restoreState(context, wrappedState);
329             }
330             return restoredObject;
331         }
332         else
333         {
334             return stateObj;
335         }
336     }
337 
338 
339     protected FacesContext getFacesContext()
340     {
341         return FacesContext.getCurrentInstance();
342     }
343     protected String getStringValue(FacesContext context, ValueExpression vb)
344     {
345         Object value = vb.getValue(context.getELContext());
346         if (value != null)
347         {
348             return value.toString();
349         }
350         return null;
351     }
352 }