/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.jsf.el; import com.caucho.jsf.cfg.*; import com.caucho.util.*; import com.caucho.config.el.*; import javax.el.*; import javax.faces.component.*; import javax.faces.context.*; import java.beans.FeatureDescriptor; import java.util.*; /** * Variable resolution for JSF variables */ public class FacesContextELResolver extends CompositeELResolver { private static final L10N L = new L10N(FacesContextELResolver.class); private static final ArrayList<FeatureDescriptor> _implicitFeatureDescriptors = new ArrayList<FeatureDescriptor>(); private ELResolver []_customResolvers; /* private final ImplicitObjectELResolver _implicitResolver = new ImplicitObjectELResolver(); private final ScopedAttributeELResolver _attrResolver = new ScopedAttributeELResolver(); */ private final MapELResolver _mapResolver = new MapELResolver(); private final ListELResolver _listResolver = new ListELResolver(); private final ArrayELResolver _arrayResolver = new ArrayELResolver(); private final JsfResourceBundleELResolver _jsfBundleResolver; private final BeanELResolver _beanResolver = new BeanELResolver(); private final ResourceBundleELResolver _bundleResolver = new ResourceBundleELResolver(); private final CandiElResolver _cdiResolver = new CandiElResolver(); private final ManagedBeanELResolver _managedBeanResolver = new ManagedBeanELResolver(); public FacesContextELResolver(ELResolver []customResolvers, JsfResourceBundleELResolver jsfBundleResolver) { _customResolvers = customResolvers; _jsfBundleResolver = jsfBundleResolver; } public void addManagedBean(String name, ManagedBeanConfig managedBean) { _managedBeanResolver.addManagedBean(name, managedBean); } public ManagedBeanELResolver getManagedBeanResolver() { return _managedBeanResolver; } public ELResolver getResourceBundleResolver() { return _jsfBundleResolver; } public void addELResolver(ELResolver elResolver) { ELResolver []elResolvers = new ELResolver[_customResolvers.length + 1]; System.arraycopy(_customResolvers, 0, elResolvers, 0, _customResolvers.length); elResolvers[elResolvers.length - 1] = elResolver; _customResolvers = elResolvers; } public ELResolver []getCustomResolvers() { return _customResolvers; } @Override public Class<?> getCommonPropertyType(ELContext env, Object base) { Class common = null; if (base == null) common = String.class; for (int i = 0; i < _customResolvers.length; i++) { common = common(common, _customResolvers[i].getCommonPropertyType(env, base)); } common = common(common, _mapResolver.getCommonPropertyType(env, base)); common = common(common, _listResolver.getCommonPropertyType(env, base)); common = common(common, _arrayResolver.getCommonPropertyType(env, base)); common = common(common, _beanResolver.getCommonPropertyType(env, base)); common = common(common, _jsfBundleResolver.getCommonPropertyType(env, base)); common = common(common, _bundleResolver.getCommonPropertyType(env, base)); return common; } private static Class common(Class a, Class b) { if (a == null) return b; else if (b == null) return a; else if (a.isAssignableFrom(b)) return a; else if (b.isAssignableFrom(a)) return b; else // XXX: return Object.class; } @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext env, Object base) { ArrayList<FeatureDescriptor> descriptors = new ArrayList<FeatureDescriptor>(); if (base == null) descriptors.addAll(_implicitFeatureDescriptors); for (int i = 0; i < _customResolvers.length; i++) { addDescriptors(descriptors, _customResolvers[i].getFeatureDescriptors(env, base)); } if (base == null) { addDescriptors(descriptors, _cdiResolver.getFeatureDescriptors(env, base)); addDescriptors(descriptors, _managedBeanResolver.getFeatureDescriptors(env, base)); addDescriptors(descriptors, _jsfBundleResolver.getFeatureDescriptors(env, base)); } addDescriptors(descriptors, _mapResolver.getFeatureDescriptors(env, base)); addDescriptors(descriptors, _beanResolver.getFeatureDescriptors(env, base)); addDescriptors(descriptors, _jsfBundleResolver.getFeatureDescriptors(env, base)); /* addDescriptors(descriptors, _implicitResolver.getFeatureDescriptors(env, base)); addDescriptors(descriptors, _attrResolver.getFeatureDescriptors(env, base)); */ return descriptors.iterator(); } private void addDescriptors(ArrayList<FeatureDescriptor> descriptors, Iterator<FeatureDescriptor> iter) { if (iter == null) return; while (iter.hasNext()) { FeatureDescriptor desc = iter.next(); descriptors.add(desc); } } @Override public Class getType(ELContext env, Object base, Object property) { env.setPropertyResolved(false); for (int i = 0; i < _customResolvers.length; i++) { Class type = _customResolvers[i].getType(env, base, property); if (env.isPropertyResolved()) return type; } if (base != null) { if (base instanceof Map) return _mapResolver.getType(env, base, property); else if (base instanceof List) return _listResolver.getType(env, base, property); else if (base.getClass().isArray()) return _arrayResolver.getType(env, base, property); else if (base instanceof ResourceBundle) return _bundleResolver.getType(env, base, property); else return _beanResolver.getType(env, base, property); } else if (base == null && property instanceof String) { ImplicitObjectExpr expr = ImplicitObjectExpr.create((String) property); if (expr != null) { env.setPropertyResolved(true); return Object.class; } Class type = _jsfBundleResolver.getType(env, base, property); if (env.isPropertyResolved()) return type; } Object value = getValue(env, base, property); if (value != null) return value.getClass(); else return null; } @Override public Object getValue(ELContext env, Object base, Object property) { env.setPropertyResolved(false); if (base == null && property instanceof String) { ImplicitObjectExpr expr = ImplicitObjectExpr.create((String) property); if (expr != null) { env.setPropertyResolved(true); return expr.getValue(env); } Object value = _jsfBundleResolver.getValue(env, base, property); if (env.isPropertyResolved()) return value; } for (int i = 0; i < _customResolvers.length; i++) { Object value = _customResolvers[i].getValue(env, base, property); if (env.isPropertyResolved()) return value; } if (base != null) { if (base instanceof Map) return _mapResolver.getValue(env, base, property); else if (base instanceof List) return _listResolver.getValue(env, base, property); else if (base.getClass().isArray()) return _arrayResolver.getValue(env, base, property); else if (base instanceof ResourceBundle) return _bundleResolver.getValue(env, base, property); else return _beanResolver.getValue(env, base, property); } else if (property instanceof String) { FacesContext facesContext = (FacesContext) env.getContext(FacesContext.class); ExternalContext ec = facesContext.getExternalContext(); Object value = ec.getRequestMap().get(property); if (value != null) { env.setPropertyResolved(true); return value; } value = ec.getSessionMap().get(property); if (value != null) { env.setPropertyResolved(true); return value; } value = ec.getApplicationMap().get(property); if (value != null) { env.setPropertyResolved(true); return value; } value = _cdiResolver.getValue(env, base, property); if (env.isPropertyResolved()) return value; value = _managedBeanResolver.getValue(env, base, property); if (env.isPropertyResolved()) return value; return null; } else return null; } @Override public boolean isReadOnly(ELContext env, Object base, Object property) { env.setPropertyResolved(false); for (int i = 0; i < _customResolvers.length; i++) { boolean readOnly = _customResolvers[i].isReadOnly(env, base, property); if (env.isPropertyResolved()) return readOnly; } if (base != null) { if (base instanceof Map) { env.setPropertyResolved(true); return _mapResolver.isReadOnly(env, base, property); } else if (base instanceof List) { env.setPropertyResolved(true); return _listResolver.isReadOnly(env, base, property); } else if (base.getClass().isArray()) { env.setPropertyResolved(true); return _arrayResolver.isReadOnly(env, base, property); } else if (base instanceof ResourceBundle) { env.setPropertyResolved(true); return _jsfBundleResolver.isReadOnly(env, base, property); } else { env.setPropertyResolved(true); return _beanResolver.isReadOnly(env, base, property); } } else if (base == null && property instanceof String) { ImplicitObjectExpr expr = ImplicitObjectExpr.create((String) property); if (expr != null) { env.setPropertyResolved(true); return true; } boolean value = _jsfBundleResolver.isReadOnly(env, base, property); if (env.isPropertyResolved()) return value; } for (int i = 0; i < _customResolvers.length; i++) { boolean value = _customResolvers[i].isReadOnly(env, base, property); if (env.isPropertyResolved()) return value; } env.setPropertyResolved(true); return false; } public void setValue(ELContext env, Object base, Object property, Object value) { env.setPropertyResolved(false); for (int i = 0; i < _customResolvers.length; i++) { _customResolvers[i].setValue(env, base, property, value); if (env.isPropertyResolved()) return; } if (base != null) { if (base instanceof Map) _mapResolver.setValue(env, base, property, value); else if (base instanceof List) _listResolver.setValue(env, base, property, value); else if (base.getClass().isArray()) _arrayResolver.setValue(env, base, property, value); else if (base instanceof ResourceBundle) _jsfBundleResolver.setValue(env, base, property, value); else _beanResolver.setValue(env, base, property, value); } else if (property instanceof String) { String key = (String) property; ImplicitObjectExpr expr = ImplicitObjectExpr.create(key); if (expr != null) throw new PropertyNotWritableException(key); _jsfBundleResolver.setValue(env, base, property, value); if (env.isPropertyResolved()) return; FacesContext facesContext = (FacesContext) env.getContext(FacesContext.class); ExternalContext ec = facesContext.getExternalContext(); Object oldValue = ec.getRequestMap().get(key); if (oldValue != null) { ec.getRequestMap().put(key, value); env.setPropertyResolved(true); return; } oldValue = ec.getSessionMap().get(key); if (oldValue != null) { ec.getSessionMap().put(key, value); env.setPropertyResolved(true); return; } oldValue = ec.getApplicationMap().get(key); if (oldValue != null) { ec.getApplicationMap().put(key, value); env.setPropertyResolved(true); return; } ec.getRequestMap().put(key, value); env.setPropertyResolved(true); return; } } private static void addDescriptor(String name, Class type) { FeatureDescriptor desc = new FeatureDescriptor(); desc.setName(name); desc.setDisplayName(name); desc.setExpert(false); desc.setHidden(false); desc.setPreferred(true); desc.setValue(ELResolver.RESOLVABLE_AT_DESIGN_TIME, Boolean.TRUE); desc.setValue(ELResolver.TYPE, type); _implicitFeatureDescriptors.add(desc); } static { addDescriptor("application", Object.class); addDescriptor("applicationScope", Map.class); addDescriptor("cookie", Map.class); addDescriptor("facesContext", FacesContext.class); addDescriptor("header", Map.class); addDescriptor("headerValues", Map.class); addDescriptor("initParam", Map.class); addDescriptor("param", Map.class); addDescriptor("paramValues", Map.class); addDescriptor("request", Object.class); addDescriptor("requestScope", Map.class); addDescriptor("resource", Object.class); addDescriptor("session", Object.class); addDescriptor("sessionScope", Map.class); addDescriptor("view", UIViewRoot.class); } }