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.unified.resolver;
20  
21  import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
22  
23  import javax.el.ELContext;
24  import javax.el.ELException;
25  import javax.el.ELResolver;
26  import javax.el.PropertyNotFoundException;
27  import javax.el.PropertyNotWritableException;
28  import javax.faces.component.UIViewRoot;
29  import javax.faces.context.ExternalContext;
30  import javax.faces.context.FacesContext;
31  import java.beans.FeatureDescriptor;
32  import java.util.ArrayList;
33  import java.util.Iterator;
34  import java.util.List;
35  import java.util.Map;
36  
37  /**
38   * See JSF 1.2 spec section 5.6.2.7
39   * 
40   * @author Stan Silvert
41   */
42  public class ScopedAttributeResolver extends ELResolver
43  {
44  
45      /**
46       * Creates a new instance of ScopedAttributeResolver
47       */
48      public ScopedAttributeResolver()
49      {
50      }
51  
52      @Override
53      public void setValue(final ELContext context, final Object base, final Object property, final Object value)
54          throws NullPointerException, PropertyNotFoundException, PropertyNotWritableException, ELException
55      {
56          if (base != null)
57          {
58              return;
59          }
60  
61          if (property == null)
62          {
63              throw new PropertyNotFoundException();
64          }
65  
66          final Map<String, Object> scopedMap = findScopedMap(facesContext(context), property);
67          if (scopedMap != null)
68          {
69              scopedMap.put((String)property, value);
70          }
71          else
72          {
73              externalContext(context).getRequestMap().put((String)property, value);
74          }
75  
76          context.setPropertyResolved(true);
77      }
78  
79      @Override
80      public boolean isReadOnly(final ELContext context, final Object base, final Object property)
81          throws NullPointerException, PropertyNotFoundException, ELException
82      {
83          if (base == null)
84          {
85              context.setPropertyResolved(true);
86          }
87  
88          return false;
89      }
90  
91      @Override
92      public Object getValue(final ELContext context, final Object base, final Object property)
93          throws NullPointerException, PropertyNotFoundException, ELException
94      {
95          if (base != null)
96          {
97              return null;
98          }
99  
100         if (property == null)
101         {
102             throw new PropertyNotFoundException();
103         }
104 
105         context.setPropertyResolved(true);
106 
107         final Map<String, Object> scopedMap = findScopedMap(facesContext(context), property);
108         if (scopedMap != null)
109         {
110             return scopedMap.get(property);
111         }
112 
113         return null;
114     }
115 
116     @Override
117     public Class<?> getType(final ELContext context, final Object base, final Object property)
118         throws NullPointerException, PropertyNotFoundException, ELException
119     {
120 
121         if (base != null)
122         {
123             return null;
124         }
125         if (property == null)
126         {
127             throw new PropertyNotFoundException();
128         }
129 
130         context.setPropertyResolved(true);
131         return Object.class;
132     }
133 
134     @Override
135     public Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext context, final Object base)
136     {
137 
138         if (base != null)
139         {
140             return null;
141         }
142 
143         final List<FeatureDescriptor> descriptorList = new ArrayList<FeatureDescriptor>();
144         final ExternalContext extContext = externalContext(context);
145         addDescriptorsToList(descriptorList, extContext.getRequestMap());
146         addDescriptorsToList(descriptorList, extContext.getSessionMap());
147         addDescriptorsToList(descriptorList, extContext.getApplicationMap());
148 
149         return descriptorList.iterator();
150     }
151 
152     @Override
153     public Class<?> getCommonPropertyType(final ELContext context, final Object base)
154     {
155 
156         if (base != null)
157         {
158             return null;
159         }
160 
161         return String.class;
162     }
163 
164     // side effect: modifies the list
165     private static void addDescriptorsToList(final List<FeatureDescriptor> descriptorList,
166                                              final Map<String, Object> scopeMap)
167     {
168         for (Object name : scopeMap.keySet())
169         {
170             String strName = (String)name;
171             Class<?> runtimeType = scopeMap.get(strName).getClass();
172             descriptorList.add(makeDescriptor(strName, runtimeType));
173         }
174     }
175 
176     private static FeatureDescriptor makeDescriptor(final String name, final Class<?> runtimeType)
177     {
178         FeatureDescriptor fd = new FeatureDescriptor();
179         fd.setValue(ELResolver.RESOLVABLE_AT_DESIGN_TIME, Boolean.TRUE);
180         fd.setValue(ELResolver.TYPE, runtimeType);
181         fd.setName(name);
182         fd.setDisplayName(name);
183         fd.setShortDescription(name);
184         fd.setExpert(false);
185         fd.setHidden(false);
186         fd.setPreferred(true);
187         return fd;
188     }
189 
190     // returns null if not found
191     private static Map<String, Object> findScopedMap(final FacesContext facesContext, final Object property)
192     {
193         if (facesContext == null)
194         {
195             return null;
196         }
197         
198         final ExternalContext extContext = facesContext.getExternalContext();
199         if (extContext == null)
200         {
201             return null;
202         }
203 
204         final boolean startup = (extContext instanceof StartupServletExternalContextImpl);
205         Map<String, Object> scopedMap;
206 
207         // request scope (not available at startup)
208         if (!startup)
209         {
210             scopedMap = extContext.getRequestMap();
211             if (scopedMap.containsKey(property))
212             {
213                 return scopedMap;
214             }
215         }
216 
217         // jsf 2.0 view scope
218         UIViewRoot root = facesContext.getViewRoot();
219         if (root != null)
220         {
221             scopedMap = root.getViewMap(false);
222             if (scopedMap != null && scopedMap.containsKey(property))
223             {
224                 return scopedMap;
225             }
226         }
227 
228         // session scope (not available at startup)
229         if (!startup)
230         {
231             scopedMap = extContext.getSessionMap();
232             if (scopedMap.containsKey(property))
233             {
234                 return scopedMap;
235             }
236         }
237 
238         // application scope
239         scopedMap = extContext.getApplicationMap();
240         if (scopedMap.containsKey(property))
241         {
242             return scopedMap;
243         }
244 
245         // not found
246         return null;
247     }
248 
249     // get the FacesContext from the ELContext
250     private static FacesContext facesContext(final ELContext context)
251     {
252         return (FacesContext)context.getContext(FacesContext.class);
253     }
254 
255     private static ExternalContext externalContext(final ELContext context)
256     {
257         FacesContext facesContext = facesContext(context);
258         if (facesContext != null)
259         {
260             return facesContext(context).getExternalContext();
261         }
262 
263         return null;
264     }
265 
266 }