gt: 	  if (_propMap.get(propName) != null)
context: /*
   * Copyright (c) 1998-2010 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 javax.el;
  
  import java.beans.BeanInfo;
  import java.beans.FeatureDescriptor;
  import java.beans.IntrospectionException;
  import java.beans.Introspector;
  import java.beans.PropertyDescriptor;
  import java.lang.ref.SoftReference;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.WeakHashMap;
  import java.util.logging.Logger;
  
  /**
   * Resolves properties based on beans.
   */
  public class BeanELResolver extends ELResolver {
    private final static Logger log
      = Logger.getLogger(BeanELResolver.class.getName());
  
    private static WeakHashMap<Class,SoftReference<BeanProperties>> _classMap
      = new WeakHashMap<Class,SoftReference<BeanProperties>>();
    
    private final boolean _isReadOnly;
    
    public BeanELResolver()
    {
      _isReadOnly = false;
    }
    
    public BeanELResolver(boolean isReadOnly)
    {
      _isReadOnly = isReadOnly;
    }
  
    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base)
    {
      if (base == null)
        return null;
      
      return Object.class;
    }
  
    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context,
  							   Object base)
    {
      if (base == null)
        return null;
  
      Class cl = base.getClass();
      BeanProperties props = getProps(cl);
  
      if (props == null) {
        if (cl.isArray()
  	  || Collection.class.isAssignableFrom(cl)
  	  || Map.class.isAssignableFrom(cl)) {
  	return null;
        }
  	  
        props = new BeanProperties(cl);
        setProps(cl, props);
      }
  
      ArrayList<FeatureDescriptor> descriptors
        = new ArrayList<FeatureDescriptor>();
  
      for (BeanProperty prop : props.getProperties()) {
        descriptors.add(prop.getDescriptor());
      }
  
      return descriptors.iterator();
    }
  
    /**
     * If the base object is not null, returns the most general type of the
     * property
     *
     * @param context
     * @param base
     * @param property
     * @return
     */
    @Override
    public Class<?> getType(ELContext context,
                            Object base,
                            Object property)
    {
      if (base == null || property == null)
        return null;
  
      if (!(property instanceof String))
        return null;
  
      String fieldName = (String) property;
  
      if (fieldName.length() == 0)
        return null;
  
      Class cl = base.getClass();
      BeanProperties props = getProps(cl);
  
      if (props == null) {
        if (cl.isArray()
            || Collection.class.isAssignableFrom(cl)
            || Map.class.isAssignableFrom(cl)) {
          return null;
        }
  
        props = new BeanProperties(cl);
        setProps(cl, props);
      }
  
      BeanProperty prop = props.getBeanProperty(fieldName);
  
      context.setPropertyResolved(true);
  
      if (prop == null || prop.getWriteMethod() == null)
        throw new PropertyNotFoundException("'" +
                                            property +
                                            "' is an unknown bean property of '" +
                                            base.getClass().getName() +
                                            "'");
  
      return prop.getWriteMethod().getParameterTypes()[0];
    }
  
    @Override
    public Object getValue(ELContext context,
  			 Object base,
  			 Object property)
    {
      if (base == null || property == null)
        return null;
  
      String fieldName = String.valueOf(property);
  
      if (fieldName.length() == 0)
        return null;
  
      Class cl = base.getClass();
      BeanProperties props = getProps(cl);
  
      if (props == null) {
        if (cl.isArray()
  	  || Collection.class.isAssignableFrom(cl)
  	  || Map.class.isAssignableFrom(cl)) {
  	return null;
        }
  	  
        props = new BeanProperties(cl);
        setProps(cl, props);
      }
  
      BeanProperty prop = props.getBeanProperty(fieldName);
  
      context.setPropertyResolved(true);
  
      if (prop == null || prop.getReadMethod() == null)
        throw new PropertyNotFoundException("'" + property + "' is an unknown bean property of '" + base.getClass().getName() + "'");
  
      try {
        return prop.getReadMethod().invoke(base);
      } catch (IllegalAccessException e) {
        throw new ELException(e);
      } catch (InvocationTargetException e) {
        throw new ELException(e.getCause());
      }
    }
  
    @Override
    public boolean isReadOnly(ELContext env,
  			    Object base,
  			    Object property)
    {
      if (base == null)
        return false;
      
      BeanProperties props = getProp(env, base, property);
  
      if (props != null) {
        env.setPropertyResolved(true);
  
        if (_isReadOnly)
  	return true;
  
        BeanProperty prop = props.getBeanProperty((String) property);
        
        return prop != null && prop.isReadOnly();
      }
  
      throw new PropertyNotFoundException("'" + property + "' is an unknown bean property of '" + base.getClass().getName() + "'");
    }
  
    @Override
    public void setValue(ELContext context,
  		       Object base,
  		       Object property,
  		       Object value)
    {
      if (base == null)
        return;
  
      String fieldName = String.valueOf(property);
  
      if (fieldName.length() == 0)
        return;
  
      Class cl = base.getClass();
      BeanProperties props = getProps(cl);
  
      if (props == null) {
        if (cl.isArray()
  	  || Collection.class.isAssignableFrom(cl)
  	  || Map.class.isAssignableFrom(cl)) {
  	return;
        }
  	  
        props = new BeanProperties(cl);
        setProps(cl, props);
      }
  
      BeanProperty prop = props.getBeanProperty(fieldName);
  
      context.setPropertyResolved(true);
  
      if (prop == null)
        throw new PropertyNotFoundException(fieldName);
      else if (prop.getWriteMethod() == null)
        throw new PropertyNotWritableException(fieldName);
  
      try {
        prop.getWriteMethod().invoke(base, value);
      } catch (IllegalAccessException e) {
        throw new ELException(e);
      } catch (InvocationTargetException e) {
        throw new ELException(e.getCause());
      }
    }
  
    private BeanProperties getProp(ELContext context,
  				 Object base,
  				 Object property)
    {
      if (base == null || ! (property instanceof String))
        return null;
  
      String fieldName = (String) property;
  
      if (fieldName.length() == 0)
        return null;
  
      Class cl = base.getClass();
      BeanProperties props = getProps(cl);
  
      if (props == null) {
        if (cl.isArray()
  	  || Collection.class.isAssignableFrom(cl)
  	  || Map.class.isAssignableFrom(cl)) {
  	return null;
        }
  	  
        props = new BeanProperties(cl);
        setProps(cl, props);
      }
  
      return props;
    }
  
    static BeanProperties getProps(Class cl)
    {
      synchronized (_classMap) {
        SoftReference<BeanProperties> ref = _classMap.get(cl);
  
        if (ref != null)
  	return ref.get();
        else
  	return null;
      }
    }
  
    static void setProps(Class cl, BeanProperties props)
    {
      synchronized (_classMap) {
        _classMap.put(cl, new SoftReference<BeanProperties>(props));
      }
    }
  
    protected static final class BeanProperties
    {
      private Class _base;
  
      private HashMap<String,BeanProperty> _propMap
        = new HashMap<String,BeanProperty>();
      
      public BeanProperties(Class<?> baseClass)
      {
        _base = baseClass;
  
        try {
  	BeanInfo info = Introspector.getBeanInfo(baseClass);
  
  	for (PropertyDescriptor descriptor : info.getPropertyDescriptors()) {
  	  _propMap.put(descriptor.getName(),
  		       new BeanProperty(baseClass, descriptor));
  	}
  
  	Method []methods = baseClass.getMethods();
  
  	for (int i = 0; i < methods.length; i++) {
  	  Method method = methods[i];
  
  	  String name = method.getName();
  
  	  if (method.getParameterTypes().length != 0)
  	    continue;
  
  	  if (! Modifier.isPublic(method.getModifiers()))
  	    continue;
  
  	  if (Modifier.isStatic(method.getModifiers()))
  	    continue;
  
  	  String propName;
  	  if (name.startsWith("get"))
  	    propName = Introspector.decapitalize(name.substring(3));
  	  else if (name.startsWith("is"))
  	    propName = Introspector.decapitalize(name.substring(2));
  	  else
  	    continue;
  
  