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 javax.el.ELContext;
23  import javax.el.ELException;
24  import javax.el.PropertyNotFoundException;
25  import javax.el.PropertyNotWritableException;
26  import javax.el.ValueExpression;
27  import javax.faces.context.FacesContext;
28  import javax.faces.el.EvaluationException;
29  import javax.faces.el.ValueBinding;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  /**
35   * Wraps a ValueBinding inside a ValueExpression. Also allows access to the original ValueBinding object.
36   * 
37   * Although ValueExpression implements Serializable, this class implements StateHolder instead.
38   * 
39   * ATTENTION: If you make changes to this class, treat {@link _ValueBindingToValueExpression} accordingly.
40   * 
41   * @author Stan Silvert
42   * @see javax.faces.component._ValueBindingToValueExpression
43   */
44  @SuppressWarnings("deprecation")
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  
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         final 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             return true;
153         if (obj == null)
154             return false;
155         if (getClass() != obj.getClass())
156             return false;
157         final _ValueBindingToValueExpression other = (_ValueBindingToValueExpression) obj;
158         if (_transient != other._transient)
159             return false;
160         if (_valueBinding == null)
161         {
162             if (other._valueBinding != null)
163                 return false;
164         }
165         else if (!_valueBinding.equals(other._valueBinding))
166             return false;
167         return true;
168     }
169 
170     @Override
171     public boolean isLiteralText()
172     {
173         return false;
174     }
175 
176     @Override
177     public String getExpressionString()
178     {
179         return getNotNullValueBinding().getExpressionString();
180     }
181 
182     @Override
183     public Class<?> getExpectedType()
184     {
185         if (_valueBinding != null)
186         {
187             try
188             {
189                 Object value = getNotNullValueBinding().getValue(FacesContext.getCurrentInstance());
190                 if (value != null)
191                 {
192                     return value.getClass();
193                 }
194             }
195             catch (Throwable e)
196             {
197                 logger.warn("Could not determine expected type for '" + _valueBinding.getExpressionString() + "': "
198                         + e.getMessage(), e);
199             }
200         }
201         return null;
202     }
203 
204     public void restoreState(FacesContext context, Object state)
205     {
206         if (state instanceof ValueBinding)
207         {
208             _valueBinding = (ValueBinding) state;
209         }
210         else if (state != null)
211         {
212             Object[] stateArray = (Object[]) state;
213             _valueBinding = (ValueBinding) _ClassUtils.newInstance((String) stateArray[0], ValueBinding.class);
214             ((StateHolder) _valueBinding).restoreState(context, stateArray[1]);
215         }
216     }
217 
218     public Object saveState(FacesContext context)
219     {
220         if (!_transient)
221         {
222             if (_valueBinding instanceof StateHolder)
223             {
224                 Object[] state = new Object[2];
225                 state[0] = _valueBinding.getClass().getName();
226                 state[1] = ((StateHolder) _valueBinding).saveState(context);
227                 return state;
228             }
229             return _valueBinding;
230         }
231         return null;
232     }
233 
234     public void setTransient(boolean newTransientValue)
235     {
236         _transient = newTransientValue;
237     }
238 
239     public boolean isTransient()
240     {
241         return _transient;
242     }
243 
244     private FacesContext getFacesContext(ELContext context)
245     {
246         if (context == null)
247         {
248             throw new IllegalArgumentException("el context must not be null.");
249         }
250         FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
251         if (context == null)
252         {
253             throw new IllegalStateException("faces context not available in el context.");
254         }
255         return facesContext;
256     }
257 
258     private <T> T invoke(Invoker<T> invoker)
259     {
260         try
261         {
262             return invoker.invoke();
263         }
264         catch (javax.faces.el.PropertyNotFoundException e)
265         {
266             throw new PropertyNotFoundException(e.getMessage(), e);
267         }
268         catch (EvaluationException e)
269         {
270             throw new ELException(e.getMessage(), e);
271         }
272     }
273 
274     private interface Invoker<T>
275     {
276         T invoke();
277     }
278 }