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;
20  
21  import java.lang.reflect.Array;
22  import java.util.List;
23  
24  import javax.el.ELContext;
25  import javax.el.ELException;
26  import javax.el.ELResolver;
27  import javax.faces.context.FacesContext;
28  import javax.faces.el.EvaluationException;
29  import javax.faces.el.PropertyNotFoundException;
30  import javax.faces.el.PropertyResolver;
31  
32  /**
33   * @author Manfred Geiler (latest modification by $Author$)
34   * @author Anton Koinov
35   * @version $Revision$ $Date$
36   */
37  @SuppressWarnings("deprecation")
38  public final class PropertyResolverImpl extends PropertyResolver
39  {
40      // ~ Public PropertyResolver Methods
41      // ----------------------------------------
42  
43      @Override
44      public Object getValue(final Object base, final Object property) throws EvaluationException,
45          PropertyNotFoundException
46      {
47          if (base == null)
48          {
49              return null;
50          }
51          if (property == null)
52          {
53              return null;
54          }
55          return invokeResolver(new ResolverInvoker<Object>(base, property)
56          {
57              @Override
58              public Object invoke(ELResolver resolver, ELContext context)
59              {
60                  return getELResolver().getValue(getELContext(), base, property);
61              }
62          });
63      }
64  
65      @Override
66      public Object getValue(final Object base, final int index) throws EvaluationException, PropertyNotFoundException
67      {
68          return getValue(base, Integer.valueOf(index));
69      }
70  
71      @Override
72      public void setValue(final Object base, final Object property, final Object newValue) throws EvaluationException,
73          PropertyNotFoundException
74      {
75          if (base == null || property == null || isReadOnly (base, property))
76          {
77              throw new PropertyNotFoundException();
78          }
79  
80          invokeResolver(new ResolverInvoker<Object>(base, property)
81          {
82              @Override
83              public Object invoke(ELResolver resolver, ELContext context)
84              {
85                  resolver.setValue(context, base, property, newValue);
86                  return null;
87              }
88  
89              @Override
90              String getMessage()
91              {
92                  return super.getMessage() + " newValue: '" + newValue + "'";
93              }
94          });
95      }
96  
97      @Override
98      public void setValue(Object base, int index, Object newValue) throws EvaluationException, PropertyNotFoundException
99      {
100         if (base == null)
101         {
102             throw new PropertyNotFoundException();
103         }
104 
105         Class baseType = base.getClass();
106         if (base instanceof Object[])
107         {
108             if (index < 0 || index >= ((Object[])base).length)
109             {
110                 throw new PropertyNotFoundException();
111             }
112             setValue(base, Integer.valueOf(index), newValue);
113         }
114         else if (base instanceof List)
115         {
116             if (index < 0 || index >= ((List<?>)base).size())
117             {
118                 throw new PropertyNotFoundException();
119             }
120             setValue(base, Integer.valueOf(index), newValue);
121         }
122         else if (baseType.isArray())
123         {
124             if (index < 0 || index >= Array.getLength(base))
125             {
126                 throw new PropertyNotFoundException();
127             }
128             Array.set(base, index, getFacesContext().getApplication().
129                 getExpressionFactory().coerceToType(newValue, baseType.getComponentType()));
130         }
131         else
132         {
133             setValue(base, Integer.valueOf(index), newValue);
134         }
135 
136     }
137 
138     @Override
139     public boolean isReadOnly(final Object base, final Object property)
140     {
141         return invokeResolver(new ResolverInvoker<Boolean>(base, property)
142         {
143             @Override
144             public Boolean invoke(ELResolver resolver, ELContext context)
145             {
146                 return Boolean.valueOf(getELResolver().isReadOnly(getELContext(), base, property));
147             }
148         });
149     }
150 
151     @Override
152     public boolean isReadOnly(final Object base, final int index)
153     {
154         return isReadOnly(base, Integer.valueOf(index));
155     }
156 
157     @Override
158     public Class getType(final Object base, final Object property)
159     {
160         if (base == null || property == null)
161         {
162             throw new PropertyNotFoundException();
163         }
164 
165         return invokeResolver(new ResolverInvoker<Class<?>>(base, property)
166         {
167             @Override
168             public Class<?> invoke(final ELResolver resolver, final ELContext context)
169             {
170                 return resolver.getType(context, base, property);
171             }
172         });
173     }
174 
175     @Override
176     public Class getType(Object base, int index)
177     {
178         if (base == null)
179         {
180             throw new PropertyNotFoundException();
181         }
182 
183         if (base instanceof Object[])
184         {
185             if (index < 0 || index >= ((Object[])base).length)
186             {
187                 throw new PropertyNotFoundException();
188             }
189         }
190         else if (base instanceof List)
191         {
192             if (index < 0 || index >= ((List<?>)base).size())
193             {
194                 throw new PropertyNotFoundException();
195             }
196         }
197 
198         return getType(base, Integer.valueOf(index));
199     }
200 
201     // ~ Internal Helper Methods
202     // ------------------------------------------------
203 
204     ELContext getELContext()
205     {
206         return getFacesContext().getELContext();
207     }
208 
209     ELResolver getELResolver()
210     {
211         return getFacesContext().getApplication().getELResolver();
212     }
213 
214     FacesContext getFacesContext()
215     {
216         return FacesContext.getCurrentInstance();
217     }
218 
219     <T> T invokeResolver(ResolverInvoker<T> invoker) throws EvaluationException, PropertyNotFoundException
220     {
221         try
222         {
223             return invoker.invoke(getELResolver(), getELContext());
224         }
225         catch (javax.el.PropertyNotFoundException e)
226         {
227             throw new PropertyNotFoundException("property not found: " + invoker.getMessage() + ": " + e.getMessage(),
228                 e);
229         }
230         catch (ELException e)
231         {
232             throw new EvaluationException("exception: " + invoker.getMessage() + ": " + e.getMessage(), e);
233         }
234         catch (RuntimeException e)
235         {
236             throw new RuntimeException("runtime exception: " + invoker.getMessage() + ": " + e.getMessage(), e);
237         }
238     }
239 
240     abstract static class ResolverInvoker<T>
241     {
242         private final Object _base;
243         private final Object _property;
244 
245         ResolverInvoker(final Object base, final Object property)
246         {
247             _base = base;
248             _property = property;
249         }
250 
251         abstract T invoke(ELResolver resolver, ELContext context);
252 
253         String getMessage()
254         {
255             return "base: '" + _base + "' property/index: '" + _property + "'";
256         }
257     }
258 }