1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.el.unified.resolver;
20
21 import java.beans.BeanInfo;
22 import java.beans.FeatureDescriptor;
23 import java.beans.PropertyDescriptor;
24 import java.lang.ref.WeakReference;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.WeakHashMap;
30
31 import javax.el.ELContext;
32 import javax.el.ELResolver;
33 import javax.el.ValueExpression;
34 import javax.faces.component.UIComponent;
35 import javax.faces.context.FacesContext;
36 import javax.faces.el.CompositeComponentExpressionHolder;
37
38 import org.apache.myfaces.shared.config.MyfacesConfig;
39 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
40
41
42
43
44
45 public final class CompositeComponentELResolver extends ELResolver
46 {
47 private static final String ATTRIBUTES_MAP = "attrs";
48
49 private static final String PARENT_COMPOSITE_COMPONENT = "parent";
50
51 private static final String COMPOSITE_COMPONENT_ATTRIBUTES_MAPS =
52 "org.apache.myfaces.COMPOSITE_COMPONENT_ATTRIBUTES_MAPS";
53
54 @Override
55 public Class<?> getCommonPropertyType(ELContext context, Object base)
56 {
57
58
59 return String.class;
60 }
61
62 @Override
63 public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context,
64 Object base)
65 {
66
67
68 return null;
69 }
70
71 @Override
72 public Class<?> getType(ELContext context, Object base, Object property)
73 {
74 if (base != null && property != null &&
75 base instanceof CompositeComponentAttributesMapWrapper &&
76 property instanceof String)
77 {
78 FacesContext facesContext = facesContext(context);
79 if (facesContext == null)
80 {
81 facesContext = FacesContext.getCurrentInstance();
82 }
83 if (facesContext == null)
84 {
85 return null;
86 }
87 if (!MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictJsf2CCELResolver())
88 {
89
90
91
92 Class<?> exprType = null;
93 Class<?> metaType = null;
94
95 CompositeComponentAttributesMapWrapper evalMap = (CompositeComponentAttributesMapWrapper) base;
96 ValueExpression ve = evalMap.getExpression((String) property);
97 if (ve != null)
98 {
99 exprType = ve.getType(context);
100 }
101
102 if (!"".equals(property))
103 {
104 if (evalMap._propertyDescriptors != null)
105 {
106 for (PropertyDescriptor pd : evalMap._propertyDescriptors)
107 {
108 if (property.equals(pd.getName()))
109 {
110 metaType = resolveType(context, pd);
111 break;
112 }
113 }
114 }
115 }
116 if (metaType != null)
117 {
118
119 if (exprType == null || exprType.isAssignableFrom(metaType))
120 {
121 context.setPropertyResolved(true);
122 return metaType;
123 }
124 }
125 return exprType;
126 }
127 }
128
129
130 return null;
131 }
132
133
134 private static Class<?> resolveType(ELContext context, PropertyDescriptor pd)
135 {
136 if (pd != null)
137 {
138 Object type = pd.getValue("type");
139 if (type != null)
140 {
141 type = ((ValueExpression)type).getValue(context);
142 if (type instanceof String)
143 {
144 try
145 {
146 type = FaceletViewDeclarationLanguage._javaTypeToClass((String)type);
147 }
148 catch (ClassNotFoundException e)
149 {
150 type = null;
151 }
152 }
153 return (Class<?>) type;
154 }
155 return pd.getPropertyType();
156 }
157
158 return null;
159 }
160
161 @Override
162 public Object getValue(ELContext context, Object base, Object property)
163 {
164
165
166
167 if ((base != null) && (base instanceof UIComponent)
168 && UIComponent.isCompositeComponent((UIComponent) base)
169 && (property != null))
170 {
171 String propName = property.toString();
172 UIComponent baseComponent = (UIComponent) base;
173
174 if (propName.equals(ATTRIBUTES_MAP))
175 {
176
177
178 context.setPropertyResolved(true);
179
180 return _getCompositeComponentAttributesMapWrapper(baseComponent, context);
181 }
182
183 else if (propName.equals(PARENT_COMPOSITE_COMPONENT))
184 {
185
186
187 context.setPropertyResolved(true);
188
189 return UIComponent.getCompositeComponentParent(baseComponent);
190 }
191 }
192
193
194
195 return null;
196 }
197
198 @SuppressWarnings("unchecked")
199 private Map<String, Object> _getCompositeComponentAttributesMapWrapper(
200 UIComponent baseComponent, ELContext elContext)
201 {
202 Map<Object, Object> contextMap = (Map<Object, Object>) facesContext(
203 elContext).getAttributes();
204
205
206
207
208
209
210
211
212 Map<UIComponent, WeakReference<Map<String, Object>>> compositeComponentAttributesMaps =
213 (Map<UIComponent, WeakReference<Map<String, Object>>>) contextMap
214 .get(COMPOSITE_COMPONENT_ATTRIBUTES_MAPS);
215
216 Map<String, Object> attributesMap = null;
217 WeakReference<Map<String, Object>> weakReference;
218 if (compositeComponentAttributesMaps != null)
219 {
220 weakReference = compositeComponentAttributesMaps.get(baseComponent);
221 if (weakReference != null)
222 {
223 attributesMap = weakReference.get();
224 }
225 if (attributesMap == null)
226 {
227
228 attributesMap = new CompositeComponentAttributesMapWrapper(
229 baseComponent);
230 compositeComponentAttributesMaps.put(baseComponent,
231 new WeakReference<Map<String, Object>>(attributesMap));
232 }
233 }
234 else
235 {
236
237 attributesMap = new CompositeComponentAttributesMapWrapper(
238 baseComponent);
239 compositeComponentAttributesMaps = new WeakHashMap<UIComponent, WeakReference<Map<String, Object>>>();
240 compositeComponentAttributesMaps.put(baseComponent,
241 new WeakReference<Map<String, Object>>(attributesMap));
242 contextMap.put(COMPOSITE_COMPONENT_ATTRIBUTES_MAPS,
243 compositeComponentAttributesMaps);
244 }
245 return attributesMap;
246 }
247
248
249 private static FacesContext facesContext(final ELContext context)
250 {
251 return (FacesContext)context.getContext(FacesContext.class);
252 }
253
254 @Override
255 public boolean isReadOnly(ELContext context, Object base, Object property)
256 {
257
258
259 return true;
260 }
261
262 @Override
263 public void setValue(ELContext context, Object base, Object property,
264 Object value)
265 {
266
267 }
268
269
270 private final class CompositeComponentAttributesMapWrapper
271 implements CompositeComponentExpressionHolder, Map<String, Object>
272 {
273
274 private final UIComponent _component;
275 private final BeanInfo _beanInfo;
276 private final Map<String, Object> _originalMap;
277 private final PropertyDescriptor [] _propertyDescriptors;
278
279 private CompositeComponentAttributesMapWrapper(UIComponent component)
280 {
281 this._component = component;
282 this._originalMap = component.getAttributes();
283 this._beanInfo = (BeanInfo) _originalMap.get(UIComponent.BEANINFO_KEY);
284 this._propertyDescriptors = _beanInfo.getPropertyDescriptors();
285 }
286
287 public ValueExpression getExpression(String name)
288 {
289 ValueExpression valueExpr = _component.getValueExpression(name);
290
291 return valueExpr;
292 }
293
294 public void clear()
295 {
296 _originalMap.clear();
297 }
298
299 public boolean containsKey(Object key)
300 {
301 return _originalMap.containsKey(key);
302 }
303
304 public boolean containsValue(Object value)
305 {
306 return _originalMap.containsValue(value);
307 }
308
309 public Set<java.util.Map.Entry<String, Object>> entrySet()
310 {
311 return _originalMap.entrySet();
312 }
313
314 public Object get(Object key)
315 {
316 Object obj = _originalMap.get(key);
317 if (obj != null)
318 {
319
320
321
322
323
324
325
326 return obj;
327 }
328 else
329 {
330 for (PropertyDescriptor attribute : _propertyDescriptors)
331 {
332 if (attribute.getName().equals(key))
333 {
334 obj = attribute.getValue("default");
335 break;
336 }
337 }
338
339
340
341 if (obj != null && obj instanceof ValueExpression)
342 {
343 return ((ValueExpression) obj).getValue(FacesContext.getCurrentInstance().getELContext());
344 }
345 else
346 {
347 return obj;
348 }
349 }
350 }
351
352 public boolean isEmpty()
353 {
354 return _originalMap.isEmpty();
355 }
356
357 public Set<String> keySet()
358 {
359 return _originalMap.keySet();
360 }
361
362 public Object put(String key, Object value)
363 {
364 ValueExpression valueExpression = _component.getValueExpression(key);
365
366
367 if (valueExpression != null)
368 {
369 valueExpression.setValue(FacesContext.getCurrentInstance().getELContext(), value);
370
371 return null;
372 }
373
374
375
376
377 return _originalMap.put(key, value);
378 }
379
380 public void putAll(Map<? extends String, ? extends Object> m)
381 {
382 for (String key : m.keySet())
383 {
384 put(key, m.get(key));
385 }
386 }
387
388 public Object remove(Object key)
389 {
390 return _originalMap.remove(key);
391 }
392
393 public int size()
394 {
395 return _originalMap.size();
396 }
397
398 public Collection<Object> values()
399 {
400 return _originalMap.values();
401 }
402 }
403 }