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