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 logger = 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         final 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             return true;
154         if (obj == null)
155             return false;
156         if (getClass() != obj.getClass())
157             return false;
158         final _ValueBindingToValueExpression other = (_ValueBindingToValueExpression)obj;
159         if (_transient != other._transient)
160             return false;
161         if (_valueBinding == null)
162         {
163             if (other._valueBinding != null)
164                 return false;
165         }
166         else if (!_valueBinding.equals(other._valueBinding))
167             return false;
168         return true;
169     }
170 
171     @Override
172     public boolean isLiteralText()
173     {
174         return false;
175     }
176 
177     @Override
178     public String getExpressionString()
179     {
180         return getNotNullValueBinding().getExpressionString();
181     }
182 
183     @Override
184     public Class<?> getExpectedType()
185     {
186         if (_valueBinding != null)
187         {
188             try
189             {
190                 Object value = getNotNullValueBinding().getValue(FacesContext.getCurrentInstance());
191                 if (value != null)
192                 {
193                     return value.getClass();
194                 }
195             }
196             catch (Throwable e)
197             {
198                 logger.log(Level.WARNING, "Could not determine expected type for '" + _valueBinding.getExpressionString() + "': "
199                         + e.getMessage(), e);
200             }
201         }
202         return null;
203     }
204 
205     public void restoreState(FacesContext context, Object state)
206     {
207         if (state instanceof ValueBinding)
208         {
209             _valueBinding = (ValueBinding)state;
210         }
211         else if (state != null)
212         {
213             Object[] stateArray = (Object[])state;
214             _valueBinding = (ValueBinding)_ClassUtils.newInstance((String)stateArray[0], ValueBinding.class);
215             ((StateHolder)_valueBinding).restoreState(context, stateArray[1]);
216         }
217     }
218 
219     public Object saveState(FacesContext context)
220     {
221         if (!_transient)
222         {
223             if (_valueBinding instanceof StateHolder)
224             {
225                 Object[] state = new Object[2];
226                 state[0] = _valueBinding.getClass().getName();
227                 state[1] = ((StateHolder)_valueBinding).saveState(context);
228                 return state;
229             }
230             return _valueBinding;
231         }
232         return null;
233     }
234 
235     public void setTransient(boolean newTransientValue)
236     {
237         _transient = newTransientValue;
238     }
239 
240     public boolean isTransient()
241     {
242         return _transient;
243     }
244 
245     private FacesContext getFacesContext(ELContext context)
246     {
247         if (context == null)
248         {
249             throw new IllegalArgumentException("el context must not be null.");
250         }
251         
252         FacesContext facesContext = (FacesContext)context.getContext(FacesContext.class);
253         if (facesContext == null)
254         {
255             throw new IllegalStateException("faces context not available in el context.");
256         }
257         
258         return facesContext;
259     }
260 
261     private <T> T invoke(Invoker<T> invoker)
262     {
263         try
264         {
265             return invoker.invoke();
266         }
267         catch (javax.faces.el.PropertyNotFoundException e)
268         {
269             throw new PropertyNotFoundException(e.getMessage(), e);
270         }
271         catch (EvaluationException e)
272         {
273             throw new ELException(e.getMessage(), e);
274         }
275     }
276 
277     private interface Invoker<T>
278     {
279         T invoke();
280     }
281 }