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 javax.faces.component;
21  
22  import java.util.logging.Level;
23  import java.util.logging.Logger;
24  
25  import javax.el.ELContext;
26  import javax.el.ELException;
27  import javax.el.PropertyNotFoundException;
28  import javax.el.PropertyNotWritableException;
29  import javax.el.ValueExpression;
30  import javax.faces.context.FacesContext;
31  import javax.faces.el.EvaluationException;
32  import javax.faces.el.ValueBinding;
33  
34  
35  /**
36   * Wraps a ValueBinding inside a ValueExpression. Also allows access to the original ValueBinding object.
37   * 
38   * Although ValueExpression implements Serializable, this class implements StateHolder instead.
39   * 
40   * ATTENTION: If you make changes to this class, treat {@link _ValueBindingToValueExpression} accordingly.
41   * 
42   * @author Stan Silvert
43   * @see javax.faces.component._ValueBindingToValueExpression
44   */
45  class _ValueBindingToValueExpression extends ValueExpression implements StateHolder
46  {
47      private static final long serialVersionUID = 8071429285360496554L;
48  
49      //private static final Log logger = LogFactory.getLog(_ValueBindingToValueExpression.class);
50      private static final Logger log = Logger.getLogger(_ValueBindingToValueExpression.class.getName());
51  
52      private ValueBinding _valueBinding;
53  
54      private boolean _transient;
55  
56      /**
57       * No-arg constructor used during restoreState
58       */
59      protected _ValueBindingToValueExpression()
60      {
61      }
62  
63      private ValueBinding getNotNullValueBinding()
64      {
65          if (_valueBinding == null)
66          {
67              throw new IllegalStateException("value binding is null");
68          }
69          return _valueBinding;
70      }
71  
72      /** Creates a new instance of ValueBindingToValueExpression */
73      public _ValueBindingToValueExpression(ValueBinding valueBinding)
74      {
75          if (valueBinding == null)
76          {
77              throw new IllegalArgumentException("value binding must not be null");
78          }
79          this._valueBinding = valueBinding;
80      }
81  
82      public ValueBinding getValueBinding()
83      {
84          return _valueBinding;
85      }
86  
87      @Override
88      public boolean isReadOnly(final ELContext context) throws NullPointerException, PropertyNotFoundException,
89          ELException
90      {
91          return invoke(new Invoker<Boolean>()
92          {
93              public Boolean invoke()
94              {
95                  return getNotNullValueBinding().isReadOnly(getFacesContext(context));
96              }
97          });
98      }
99  
100     @Override
101     public Object getValue(final ELContext context) throws NullPointerException, PropertyNotFoundException, ELException
102     {
103         return invoke(new Invoker<Object>()
104         {
105             public Object invoke()
106             {
107                 return getNotNullValueBinding().getValue(getFacesContext(context));
108             }
109         });
110     }
111 
112     @Override
113     public Class<?> getType(final ELContext context) throws NullPointerException, PropertyNotFoundException,
114         ELException
115     {
116         return invoke(new Invoker<Class<?>>()
117         {
118             public Class<?> invoke()
119             {
120                 return getNotNullValueBinding().getType(getFacesContext(context));
121             }
122         });
123     }
124 
125     @Override
126     public void setValue(final ELContext context, final Object value) throws NullPointerException,
127         PropertyNotFoundException, PropertyNotWritableException, ELException
128     {
129         invoke(new Invoker<Object>()
130         {
131             public Object invoke()
132             {
133                 getNotNullValueBinding().setValue(getFacesContext(context), value);
134                 return null;
135             }
136         });
137     }
138 
139     @Override
140     public int hashCode()
141     {
142         int prime = 31;
143         int result = 1;
144         result = prime * result + (_transient ? 1231 : 1237);
145         result = prime * result + ((_valueBinding == null) ? 0 : _valueBinding.hashCode());
146         return result;
147     }
148 
149     @Override
150     public boolean equals(Object obj)
151     {
152         if (this == obj)
153         {
154             return true;
155         }
156         if (obj == null)
157         {
158             return false;
159         }
160         if (getClass() != obj.getClass())
161         {
162             return false;
163         }
164         _ValueBindingToValueExpression other = (_ValueBindingToValueExpression)obj;
165         if (_transient != other._transient)
166         {
167             return false;
168         }
169         if (_valueBinding == null)
170         {
171             if (other._valueBinding != null)
172             {
173                 return false;
174             }
175         }
176         else if (!_valueBinding.equals(other._valueBinding))
177         {
178             return false;
179         }
180         return true;
181     }
182 
183     @Override
184     public boolean isLiteralText()
185     {
186         return false;
187     }
188 
189     @Override
190     public String getExpressionString()
191     {
192         return getNotNullValueBinding().getExpressionString();
193     }
194 
195     @Override
196     public Class<?> getExpectedType()
197     {
198         if (_valueBinding != null)
199         {
200             try
201             {
202                 Object value = getNotNullValueBinding().getValue(FacesContext.getCurrentInstance());
203                 if (value != null)
204                 {
205                     return value.getClass();
206                 }
207             }
208             catch (Throwable e)
209             {
210                 log.log(Level.WARNING, "Could not determine expected type for '"
211                         + _valueBinding.getExpressionString() + "': "
212                         + e.getMessage(), e);
213             }
214         }
215         return null;
216     }
217 
218     public void restoreState(FacesContext context, Object state)
219     {
220         if (state instanceof ValueBinding)
221         {
222             _valueBinding = (ValueBinding)state;
223         }
224         else if (state != null)
225         {
226             Object[] stateArray = (Object[])state;
227             _valueBinding = (ValueBinding)_ClassUtils.newInstance((String)stateArray[0], ValueBinding.class);
228             ((StateHolder)_valueBinding).restoreState(context, stateArray[1]);
229         }
230     }
231 
232     public Object saveState(FacesContext context)
233     {
234         if (!_transient)
235         {
236             if (_valueBinding instanceof StateHolder)
237             {
238                 Object[] state = new Object[2];
239                 state[0] = _valueBinding.getClass().getName();
240                 state[1] = ((StateHolder)_valueBinding).saveState(context);
241                 return state;
242             }
243             return _valueBinding;
244         }
245         return null;
246     }
247 
248     public void setTransient(boolean newTransientValue)
249     {
250         _transient = newTransientValue;
251     }
252 
253     public boolean isTransient()
254     {
255         return _transient;
256     }
257 
258     private FacesContext getFacesContext(ELContext context)
259     {
260         if (context == null)
261         {
262             throw new IllegalArgumentException("el context must not be null.");
263         }
264         
265         FacesContext facesContext = (FacesContext)context.getContext(FacesContext.class);
266         if (facesContext == null)
267         {
268             throw new IllegalStateException("faces context not available in el context.");
269         }
270         
271         return facesContext;
272     }
273 
274     private <T> T invoke(Invoker<T> invoker)
275     {
276         try
277         {
278             return invoker.invoke();
279         }
280         catch (javax.faces.el.PropertyNotFoundException e)
281         {
282             throw new PropertyNotFoundException(e.getMessage(), e);
283         }
284         catch (EvaluationException e)
285         {
286             throw new ELException(e.getMessage(), e);
287         }
288     }
289 
290     private interface Invoker<T>
291     {
292         T invoke();
293     }
294 }