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.el.convert;
20  
21  import javax.el.ELContext;
22  import javax.el.ELException;
23  import javax.el.ELResolver;
24  import javax.el.ExpressionFactory;
25  import javax.el.PropertyNotFoundException;
26  import javax.el.PropertyNotWritableException;
27  import javax.faces.FactoryFinder;
28  import javax.faces.application.ApplicationFactory;
29  import javax.faces.context.FacesContext;
30  import javax.faces.el.EvaluationException;
31  import javax.faces.el.PropertyResolver;
32  import java.beans.FeatureDescriptor;
33  import java.util.Iterator;
34  import java.util.List;
35  import org.apache.myfaces.el.DefaultPropertyResolver;
36  
37  /**
38   * Wrapper that converts a VariableResolver into an ELResolver. See JSF 1.2 spec section 5.6.1.6
39   *
40   * @author Stan Silvert (latest modification by $Author$)
41   * @author Mathias Broekelmann
42   * @version $Revision$ $Date$
43   */
44  @SuppressWarnings("deprecation")
45  public final class PropertyResolverToELResolver extends ELResolver
46  {
47      private PropertyResolver propertyResolver;
48  
49      private ExpressionFactory expressionFactory;
50      
51      private boolean isDefaultLegacyPropertyResolver;
52  
53      /**
54       * Creates a new instance of PropertyResolverToELResolver
55       */
56      public PropertyResolverToELResolver(final PropertyResolver propertyResolver)
57      {
58          this.propertyResolver = propertyResolver;
59          this.isDefaultLegacyPropertyResolver = (propertyResolver instanceof DefaultPropertyResolver);
60      }
61  
62      @Override
63      public void setValue(final ELContext context, final Object base, final Object property, final Object value)
64          throws NullPointerException, PropertyNotFoundException, PropertyNotWritableException, ELException
65      {
66          if (isDefaultLegacyPropertyResolver)
67          {
68              return;
69          }
70          if (base == null || property == null)
71          {
72              return;
73          }
74  
75          try
76          {
77              context.setPropertyResolved(true);
78              if (needsCoersion(base))
79              {
80                  propertyResolver.setValue(base, coerceToInt(property), value);
81              }
82              else
83              {
84                  propertyResolver.setValue(base, property, value);
85              }
86              // see: https://issues.apache.org/jira/browse/MYFACES-1670
87              context.setPropertyResolved(
88                  FacesContext.getCurrentInstance().getELContext().isPropertyResolved());
89  
90          }
91          catch (javax.faces.el.PropertyNotFoundException e)
92          {
93              context.setPropertyResolved(false);
94              throw new PropertyNotFoundException(e.getMessage(), e);
95          }
96          catch (EvaluationException e)
97          {
98              context.setPropertyResolved(false);
99              throw new ELException(e.getMessage(), e);
100         }
101         catch (RuntimeException e)
102         {
103             context.setPropertyResolved(false);
104             throw e;
105         }
106     }
107 
108     @Override
109     public boolean isReadOnly(final ELContext context, final Object base, final Object property)
110             throws NullPointerException, PropertyNotFoundException, ELException
111     {
112         if (isDefaultLegacyPropertyResolver)
113         {
114             return false;
115         }
116         if (base == null || property == null)
117         {
118             return true;
119         }
120 
121         try
122         {
123             boolean result;
124             context.setPropertyResolved(true);
125             if (needsCoersion(base))
126             {
127                 result = propertyResolver.isReadOnly(base, coerceToInt(property));
128             }
129             else
130             {
131                 result = propertyResolver.isReadOnly(base, property);
132             }
133 
134             // see: https://issues.apache.org/jira/browse/MYFACES-1670
135             context.setPropertyResolved(
136                 FacesContext.getCurrentInstance().getELContext().isPropertyResolved());
137             return result;
138         }
139         catch (javax.faces.el.PropertyNotFoundException e)
140         {
141             context.setPropertyResolved(false);
142             throw new PropertyNotFoundException(e.getMessage(), e);
143         }
144         catch (EvaluationException e)
145         {
146             context.setPropertyResolved(false);
147             throw new ELException(e.getMessage(), e);
148         }
149         catch (RuntimeException e)
150         {
151             context.setPropertyResolved(false);
152             throw e;
153         }
154     }
155 
156     @Override
157     public Object getValue(final ELContext context, final Object base, final Object property)
158             throws NullPointerException, PropertyNotFoundException, ELException
159     {
160         if (isDefaultLegacyPropertyResolver)
161         {
162             return null;
163         }        
164         if (base == null || property == null)
165         {
166             return null;
167         }
168 
169         try
170         {
171             context.setPropertyResolved(true);
172             Object value;
173             if (needsCoersion(base))
174             {
175                 value = propertyResolver.getValue(base, coerceToInt(property));
176             }
177             else
178             {
179                 value = propertyResolver.getValue(base, property);
180             }
181 
182             // see: https://issues.apache.org/jira/browse/MYFACES-1670
183             context.setPropertyResolved(
184                 FacesContext.getCurrentInstance().getELContext().isPropertyResolved());
185 
186             return value;
187         }
188         catch (javax.faces.el.PropertyNotFoundException e)
189         {
190             context.setPropertyResolved(false);
191             throw new PropertyNotFoundException(e.getMessage(), e);
192         }
193         catch (EvaluationException e)
194         {
195             context.setPropertyResolved(false);
196             throw new ELException(e.getMessage(), e);
197         }
198         catch (RuntimeException e)
199         {
200             context.setPropertyResolved(false);
201             throw e;
202         }
203     }
204 
205     @Override
206     public Class<?> getType(final ELContext context, final Object base, final Object property)
207             throws NullPointerException, PropertyNotFoundException, ELException
208     {
209         if (isDefaultLegacyPropertyResolver)
210         {
211             return null;
212         }
213         if (base == null || property == null)
214         {
215             return null;
216         }
217 
218         try
219         {
220             context.setPropertyResolved(true);
221             Class<?> value;
222             if (needsCoersion(base))
223             {
224                 value = propertyResolver.getType(base, coerceToInt(property));
225             }
226             else
227             {
228                 value = propertyResolver.getType(base, property);
229             }
230 
231             // see: https://issues.apache.org/jira/browse/MYFACES-1670
232             context.setPropertyResolved(
233                 FacesContext.getCurrentInstance().getELContext().isPropertyResolved());
234 
235             return value;
236         }
237         catch (javax.faces.el.PropertyNotFoundException e)
238         {
239             context.setPropertyResolved(false);
240             throw new PropertyNotFoundException(e.getMessage(), e);
241         }
242         catch (EvaluationException e)
243         {
244             context.setPropertyResolved(false);
245             throw new ELException(e.getMessage(), e);
246         }
247         catch (RuntimeException e)
248         {
249             context.setPropertyResolved(false);
250             throw e;
251         }
252     }
253 
254     @Override
255     public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base)
256     {
257         return null;
258     }
259 
260     @Override
261     public Class<?> getCommonPropertyType(ELContext context, Object base)
262     {
263         if (isDefaultLegacyPropertyResolver)
264         {
265             return null;
266         }
267         if (base == null)
268         {
269             return null;
270         }
271 
272         return Object.class;
273     }
274 
275     private static boolean needsCoersion(Object base)
276     {
277         return (base instanceof List) || base.getClass().isArray();
278     }
279 
280     protected ExpressionFactory getExpressionFactory()
281     {
282         if (expressionFactory == null)
283         {
284             ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder
285                 .getFactory(FactoryFinder.APPLICATION_FACTORY);
286             expressionFactory = appFactory.getApplication().getExpressionFactory();
287         }
288         return expressionFactory;
289     }
290 
291     public void setExpressionFactory(ExpressionFactory expressionFactory)
292     {
293         this.expressionFactory = expressionFactory;
294     }
295 
296     private int coerceToInt(Object property)
297     {
298         return (Integer) getExpressionFactory().coerceToType(property, Integer.class);
299     }
300 
301 
302     public PropertyResolver getPropertyResolver()
303     {
304         return propertyResolver;
305     }
306 }