You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/05/05 22:08:17 UTC

[03/51] [partial] FLEX-34306 - [BlazeDS] Make the BlazeDS build run on Windows machines - Added some mkdir commands to the ANT Build.java - Did some fine-tuning to resolve some compile errors

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/4f6a3052/modules/core/src/flex/messaging/io/BeanProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/io/BeanProxy.java b/modules/core/src/flex/messaging/io/BeanProxy.java
old mode 100755
new mode 100644
index f15c642..1774b69
--- a/modules/core/src/flex/messaging/io/BeanProxy.java
+++ b/modules/core/src/flex/messaging/io/BeanProxy.java
@@ -1,940 +1,940 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package flex.messaging.io;
-
-import flex.messaging.MessageException;
-import flex.messaging.io.amf.ASObject;
-import flex.messaging.log.Log;
-import flex.messaging.log.Logger;
-import flex.messaging.util.ClassUtil;
-import flex.messaging.util.ExceptionUtil;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.AbstractCollection;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * Uses Bean introspection to collect the properties for a given instance.
- *
- * @author Peter Farland
- */
-public class BeanProxy extends AbstractProxy
-{
-    static final long serialVersionUID = 7365078101695257715L;
-
-    private static final int FAILED_PROPERTY_READ_ERROR = 10021;
-    private static final int FAILED_PROPERTY_WRITE_ERROR = 10022;
-    private static final int NON_READABLE_PROPERTY_ERROR = 10023;
-    private static final int NON_WRITABLE_PROPERTY_ERROR = 10024;
-    private static final int UNKNOWN_PROPERTY_ERROR = 10025;
-
-    protected static final Map<Class, List<String>> rwPropertyNamesCache = new IdentityHashMap<Class, List<String>>();
-    protected static final Map<Class, Map<String, BeanProperty>> rwBeanPropertyCache = new IdentityHashMap<Class, Map<String, BeanProperty>>();
-    protected static final Map<Class, PropertyDescriptorCacheEntry> rwPropertyDescriptorCache = new IdentityHashMap<Class, PropertyDescriptorCacheEntry>();
-
-    protected static final Map<Class, List<String>> roPropertyNamesCache = new IdentityHashMap<Class, List<String>>();
-    protected static final Map<Class, Map<String, BeanProperty>> roBeanPropertyCache = new IdentityHashMap<Class, Map<String, BeanProperty>>();
-    protected static final Map<Class, PropertyDescriptorCacheEntry> roPropertyDescriptorCache = new IdentityHashMap<Class, PropertyDescriptorCacheEntry>();
-
-    protected boolean cacheProperties = true;
-    protected boolean cachePropertiesDescriptors = true;
-    protected Class stopClass = Object.class;
-
-    protected static final Map ignoreProperties = new HashMap();
-    static
-    {
-        initializeIgnoreProperties();
-    }
-
-    private static void initializeIgnoreProperties()
-    {
-        addIgnoreProperty(AbstractMap.class, "empty");
-        addIgnoreProperty(AbstractCollection.class, "empty");
-        addIgnoreProperty(ASObject.class, "type");
-        addIgnoreProperty(Throwable.class, "stackTrace");
-        addIgnoreProperty(File.class, "parentFile");
-        addIgnoreProperty(File.class, "canonicalFile");
-        addIgnoreProperty(File.class, "absoluteFile");
-    }
-
-    /**
-     * Constructor.
-     */
-    public BeanProxy()
-    {
-        this(null);
-    }
-
-    /**
-     * Construct a new BeanProxy with the provided default instance.
-     *
-     * @param defaultInstance defines the alias if provided
-     */
-    public BeanProxy(Object defaultInstance)
-    {
-        super(defaultInstance);
-
-        // Override default behavior here... standard Map implementations
-        // are treated as anonymous Objects, i.e. without an alias.
-        if (defaultInstance != null)
-            alias = getClassName(defaultInstance);
-    }
-
-    /** {@inheritDoc} */
-    public String getAlias(Object instance)
-    {
-        return getClassName(instance);
-    }
-
-    /** {@inheritDoc} */
-    public List getPropertyNames(Object instance)
-    {
-        if (instance == null)
-            return null;
-
-        Class c = instance.getClass();
-        List<String> propertyNames = null;
-
-        // Look up property names in cache if we don't have a custom serialization descriptor
-        if (descriptor == null)
-        {
-            if (getIncludeReadOnly())
-            {
-                synchronized (roPropertyNamesCache)
-                {
-                    propertyNames = roPropertyNamesCache.get(c);
-                }
-            }
-            else
-            {
-                synchronized (rwPropertyNamesCache)
-                {
-                    propertyNames = rwPropertyNamesCache.get(c);
-                }
-            }
-        }
-
-        if (propertyNames != null)
-            return propertyNames;
-
-        // Make a copy of the property names to return
-        propertyNames = new ArrayList<String>(getBeanProperties(instance).keySet());
-
-        // Store property names in cache if we are caching properties
-        // and we don't have a custom serialization descriptor
-        if (cacheProperties && descriptor == null)
-        {
-            if (getIncludeReadOnly())
-            {
-                synchronized (roPropertyNamesCache)
-                {
-                    roPropertyNamesCache.put(c, propertyNames);
-                }
-            }
-            else
-            {
-                synchronized (rwPropertyNamesCache)
-                {
-                    rwPropertyNamesCache.put(c, propertyNames);
-                }
-            }
-        }
-        return propertyNames;
-    }
-
-
-    /** {@inheritDoc} */
-    public Class getType(Object instance, String propertyName)
-    {
-        if (instance == null || propertyName == null)
-            return null;
-
-        BeanProperty bp = getBeanProperty(instance, propertyName);
-        return bp == null? null : bp.getType();
-    }
-
-    /** {@inheritDoc} */
-    public Object getValue(Object instance, String propertyName)
-    {
-        if (instance == null || propertyName == null)
-            return null;
-
-        BeanProperty bp = getBeanProperty(instance, propertyName);
-        if (bp != null)
-            return getBeanValue(instance, bp);
-
-        SerializationContext context = getSerializationContext();
-        if (!ignorePropertyErrors(context))
-        {
-            // Property '{propertyName}' not found on class '{alias}'.
-            MessageException ex = new MessageException();
-            ex.setMessage(UNKNOWN_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
-            throw ex;
-        }
-        return null;
-    }
-
-    /**
-     * Gets the value specified by the BeanProperty.
-     * @param instance Object to get the value from
-     * @param bp the property to get
-     * @return the value of the property if it exists
-     */
-    protected final Object getBeanValue(Object instance, BeanProperty bp)
-    {
-        String propertyName = bp.getName();
-        if (bp.isRead())
-        {
-            try
-            {
-                Object value = bp.get(instance);
-                if (value != null && descriptor != null)
-                {
-                    SerializationDescriptor subDescriptor = (SerializationDescriptor)descriptor.get(propertyName);
-                    if (subDescriptor != null)
-                    {
-                        PropertyProxy subProxy = PropertyProxyRegistry.getProxyAndRegister(value);
-                        subProxy = (PropertyProxy)subProxy.clone();
-                        subProxy.setDescriptor(subDescriptor);
-                        subProxy.setDefaultInstance(value);
-                        value = subProxy;
-                    }
-                }
-                return value;
-            }
-            catch (Exception e)
-            {
-                SerializationContext context = getSerializationContext();
-
-                // Log failed property set errors
-                if (Log.isWarn() && logPropertyErrors(context))
-                {
-                    Logger log = Log.getLogger(LOG_CATEGORY);
-                    log.warn("Failed to get property {0} on type {1}.",
-                             new Object[] {propertyName, getAlias(instance)}, e);
-                }
-
-                if (!ignorePropertyErrors(context))
-                {
-                    // Failed to get property '{propertyName}' on type '{className}'.
-                    MessageException ex = new MessageException();
-                    ex.setMessage(FAILED_PROPERTY_READ_ERROR, new Object[] {propertyName, getAlias(instance)});
-                    ex.setRootCause(e);
-                    throw ex;
-                }
-            }
-        }
-        else
-        {
-            SerializationContext context = getSerializationContext();
-            if (!ignorePropertyErrors(context))
-            {
-                //Property '{propertyName}' not readable from class '{alias}'.
-                MessageException ex = new MessageException();
-                ex.setMessage(NON_READABLE_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
-                throw ex;
-            }
-        }
-        return null;
-    }
-
-    /** {@inheritDoc} */
-    public void setValue(Object instance, String propertyName, Object value)
-    {
-        BeanProperty bp = getBeanProperty(instance, propertyName);
-
-        if (bp != null)
-        {
-            if (bp.isWrite())
-            {
-                try
-                {
-                    Class desiredPropClass = bp.getType();
-                    TypeMarshaller marshaller = TypeMarshallingContext.getTypeMarshaller();
-                    value = marshaller.convert(value, desiredPropClass);
-                    ClassUtil.validateAssignment(instance, propertyName, value);
-                    bp.set(instance, value);
-                }
-                catch (Exception e)
-                {
-                    SerializationContext context = getSerializationContext();
-
-                    // Log ignore failed property set errors
-                    if (Log.isWarn() && logPropertyErrors(context))
-                    {
-                        Logger log = Log.getLogger(LOG_CATEGORY);
-                        log.warn("Failed to set property {0} on type {1}.",
-                                new Object[] {propertyName, getAlias(instance)}, e);
-                    }
-
-                    if (!ignorePropertyErrors(context))
-                    {
-                        // Failed to get property '{propertyName}' on type '{className}'.
-                        MessageException ex = new MessageException();
-                        ex.setMessage(FAILED_PROPERTY_WRITE_ERROR, new Object[] {propertyName, getAlias(instance)});
-                        ex.setRootCause(e);
-                        throw ex;
-                    }
-                }
-            }
-            else
-            {
-                SerializationContext context = getSerializationContext();
-
-                if (Log.isWarn() && logPropertyErrors(context))
-                {
-                    Logger log = Log.getLogger(LOG_CATEGORY);
-                    log.warn("Property {0} not writable on class {1}",
-                            new Object[] {propertyName, getAlias(instance)});
-                }
-
-                if (!ignorePropertyErrors(context))
-                {
-                    //Property '{propertyName}' not writable on class '{alias}'.
-                    MessageException ex = new MessageException();
-                    ex.setMessage(NON_WRITABLE_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
-                    throw ex;
-                }
-            }
-        }
-        else
-        {
-            SerializationContext context = getSerializationContext();
-
-            if (Log.isWarn() && logPropertyErrors(context))
-            {
-                Logger log = Log.getLogger(LOG_CATEGORY);
-                log.warn("Ignoring set property {0} for type {1} as a setter could not be found.",
-                            new Object[] {propertyName, getAlias(instance)});
-            }
-
-            if (!ignorePropertyErrors(context))
-            {
-                // Property '{propertyName}' not found on class '{alias}'.
-                MessageException ex = new MessageException();
-                ex.setMessage(UNKNOWN_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
-                throw ex;
-            }
-        }
-    }
-
-    /**
-     * Are we ignoring property errors?
-     * @param context serialization paramters.
-     * @return true if ignoring property errors.
-     */
-    protected boolean ignorePropertyErrors(SerializationContext context)
-    {
-        return context.ignorePropertyErrors;
-    }
-
-    /**
-     * Should we log property errors?
-     * @param context serialization parameters.
-     * @return true if we should log property errors.
-     */
-    protected boolean logPropertyErrors(SerializationContext context)
-    {
-        return context.logPropertyErrors;
-    }
-
-    /**
-     * Determins the classname for both normal types via Class.getName() and
-     * virtual types via ASObject.getType(). Virtual types starting
-     * with the special ">" token are also handled and the underlying
-     * className is returned.
-     *
-     * @param instance the object to examine.
-     * @return the classname to use for instances of this type
-     */
-    protected String getClassName(Object instance)
-    {
-        String className;
-
-        if (instance instanceof ASObject)
-        {
-            className = ((ASObject)instance).getType();
-        }
-        else if (instance instanceof ClassAlias)
-        {
-            className = ((ClassAlias)instance).getAlias();
-        }
-        else
-        {
-            className = instance.getClass().getName();
-            // If there's an alias, use that as the class name.
-            ClassAliasRegistry registry = ClassAliasRegistry.getRegistry();
-            String aliasedClass = registry.getClassName(className);
-            className = (aliasedClass == null)? className : aliasedClass;
-        }
-
-        return className;
-    }
-
-    /**
-     * Return a map of properties for a object.
-     * @param instance object to examine.
-     * @return a map of Strings to BeanProperty objects.
-     */
-    protected Map<String, BeanProperty> getBeanProperties(Object instance)
-    {
-        Class c = instance.getClass();
-        Map<String, BeanProperty> props;
-
-        // look up instance class in cache if we don't have a custom descriptor.
-        if (descriptor == null)
-        {
-            if (getIncludeReadOnly())
-            {
-                synchronized (roBeanPropertyCache)
-                {
-                    props = roBeanPropertyCache.get(c);
-                }
-            }
-            else
-            {
-                synchronized (rwBeanPropertyCache)
-                {
-                    props = roBeanPropertyCache.get(c);
-
-                }
-            }
-            if (props != null)
-                return props;
-        }
-
-        props = new HashMap<String, BeanProperty>();
-        PropertyDescriptor[] pds = getPropertyDescriptors(c);
-        if (pds == null)
-            return null;
-
-        List excludes = null;
-        if (descriptor != null)
-        {
-            excludes = descriptor.getExcludesForInstance(instance);
-            if (excludes == null) // For compatibility with older implementations
-                excludes = descriptor.getExcludes();
-        }
-
-        // Add standard bean properties first
-        for (PropertyDescriptor pd : pds)
-        {
-            String propertyName = pd.getName();
-            Method readMethod = pd.getReadMethod();
-            Method writeMethod = pd.getWriteMethod();
-
-            // If there's a public read method but no writeMethod and includeReadOnly
-            // flag is off, then skip the property.
-            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) && !getIncludeReadOnly() && writeMethod == null)
-                continue;
-
-            // Skip excluded and ignored properties as well.
-            if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
-                continue;
-
-            // Ensure we don't include Object getClass() property, possibly returned (incorrectly) by custom BeanInfos
-            if (getIncludeReadOnly() && writeMethod == null && "class".equals(propertyName))
-                continue;
-
-            // Skip any classloader properties
-            final Class<?> type = pd.getPropertyType();
-            if (type != null && ClassLoader.class.isAssignableFrom(type))
-                continue;
-
-            props.put(propertyName, new BeanProperty(propertyName, pd.getPropertyType(),
-                    readMethod, writeMethod, null));
-        }
-
-        // Then add public fields to list if property does not already exist
-        Field[] fields = instance.getClass().getFields();
-        for (Field field : fields)
-        {
-            String propertyName = field.getName();
-            int modifiers = field.getModifiers();
-            if (isPublicField(modifiers) && !props.containsKey(propertyName))
-            {
-                // Skip excluded and ignored properties.
-                if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
-                    continue;
-
-                props.put(propertyName, new BeanProperty(propertyName, field.getType(), null, null, field));
-            }
-        }
-
-        // Update the cache if we don't have a custom serialization descriptor and we are caching.
-        if (descriptor == null && cacheProperties)
-        {
-            if (getIncludeReadOnly())
-            {
-                synchronized (roBeanPropertyCache)
-                {
-                    roBeanPropertyCache.put(c, props);
-                }
-            }
-            else
-            {
-                synchronized (rwBeanPropertyCache)
-                {
-                    roBeanPropertyCache.put(c, props);
-
-                }
-            }
-        }
-
-        return props;
-    }
-
-    /**
-     * Return true if this property is write only, which means we cannot get a value for it.
-     *
-     * @param instance the instance
-     * @param propertyName the property name
-     * @return true if there is a way to write but not read the property
-     */
-    public boolean isWriteOnly(Object instance, String propertyName)
-    {
-        if (instance == null || propertyName == null)
-            return false;
-
-        BeanProperty bp = getBeanProperty(instance, propertyName);
-        return bp != null && bp.isWrite() && !bp.isRead();
-    }
-
-    /**
-     * Return a specific property descriptor for a named property.
-     * @param instance the object to use.
-     * @param propertyName the property to get.
-     * @return a descriptor for the property.
-     */
-    protected final BeanProperty getBeanProperty(Object instance, String propertyName)
-    {
-        Class c = instance.getClass();
-        Map props;
-
-        // It is faster to use the BeanProperty cache if we are going to cache it.
-        if (descriptor == null && cacheProperties)
-        {
-            props = getBeanProperties(instance);
-            return props == null? null : (BeanProperty)props.get(propertyName);
-        }
-
-        // Otherwise, just build up the property we are asked for
-        PropertyDescriptorCacheEntry pce =  getPropertyDescriptorCacheEntry(c);
-        if (pce == null)
-            return null;
-
-        Object pType = pce.propertiesByName.get(propertyName);
-        if (pType == null)
-            return null;
-
-        List excludes = null;
-        if (descriptor != null)
-        {
-            excludes = descriptor.getExcludesForInstance(instance);
-            if (excludes == null) // For compatibility with older implementations
-                excludes = descriptor.getExcludes();
-        }
-
-        if (pType instanceof PropertyDescriptor)
-        {
-            PropertyDescriptor pd = (PropertyDescriptor) pType;
-
-            Method readMethod = pd.getReadMethod();
-            Method writeMethod = pd.getWriteMethod();
-
-            // If there's a public read method but no writeMethod and includeReadOnly
-            // flag is off, then skip the property.
-            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) && !getIncludeReadOnly() && writeMethod == null)
-                return null;
-
-            // Skip excluded and ignored properties as well.
-            if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
-                return null;
-
-            return new BeanProperty(propertyName, pd.getPropertyType(), readMethod, writeMethod, null);
-        }
-        else if (pType instanceof Field)
-        {
-            Field field = (Field) pType;
-
-            String pName = field.getName();
-            int modifiers = field.getModifiers();
-            if (isPublicField(modifiers) && pName.equals(propertyName))
-            {
-                // Skip excluded and ignored properties.
-                return ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))?
-                        null : new BeanProperty(propertyName, field.getType(), null, null, field);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Return an array of JavaBean property descriptors for a class.
-     * @param c the class to examine.
-     * @return an array ot JavaBean PropertyDescriptors.
-     */
-    private PropertyDescriptor [] getPropertyDescriptors(Class c)
-    {
-        PropertyDescriptorCacheEntry pce = getPropertyDescriptorCacheEntry(c);
-        return pce == null? null : pce.propertyDescriptors;
-    }
-
-    /**
-     * Return an entry from the property descriptor cache for a class.
-     * @param c the class
-     * @return a descriptor cache entry or null
-     */
-    private PropertyDescriptorCacheEntry getPropertyDescriptorCacheEntry(Class c)
-    {
-        PropertyDescriptorCacheEntry pce;
-        if (getIncludeReadOnly())
-        {
-            synchronized (roPropertyDescriptorCache)
-            {
-                pce = roPropertyDescriptorCache.get(c);
-            }
-        }
-        else
-        {
-            synchronized (rwPropertyDescriptorCache)
-            {
-                pce = rwPropertyDescriptorCache.get(c);
-            }
-        }
-        
-        try
-        {
-            if (pce == null)
-            {
-                BeanInfo beanInfo = Introspector.getBeanInfo(c, stopClass);
-                pce = new PropertyDescriptorCacheEntry();
-                pce.propertyDescriptors = beanInfo.getPropertyDescriptors();
-                pce.propertiesByName = createPropertiesByNameMap(pce.propertyDescriptors, c.getFields());
-                if (cachePropertiesDescriptors)
-                {
-                    if (getIncludeReadOnly())
-                    {
-                        synchronized (roPropertyDescriptorCache)
-                        {
-                            roPropertyDescriptorCache.put(c, pce);
-                        }
-                    }
-                    else
-                    {
-                        synchronized (rwPropertyDescriptorCache)
-                        {
-                            rwPropertyDescriptorCache.put(c, pce);
-                        }
-                    }
-                }
-            }
-        }
-        catch (IntrospectionException ex)
-        {
-            // Log failed property set errors
-            if (Log.isError())
-            {
-                Logger log = Log.getLogger(LOG_CATEGORY);
-                log.error("Failed to introspect object of type: " + c + " error: " + ExceptionUtil.toString(ex));
-            }
-
-            // Return an empty descriptor rather than crashing
-            pce = new PropertyDescriptorCacheEntry();
-            pce.propertyDescriptors = new PropertyDescriptor[0];
-            pce.propertiesByName = new TreeMap();
-        }
-        return pce;
-    }
-
-    private Map createPropertiesByNameMap(PropertyDescriptor [] pds, Field [] fields)
-    {
-        Map m = new HashMap(pds.length);
-        for (PropertyDescriptor pd : pds)
-        {
-            Method readMethod = pd.getReadMethod();
-            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) &&
-                    (getIncludeReadOnly() || pd.getWriteMethod() != null))
-                m.put(pd.getName(), pd);
-        }
-        for (Field field : fields)
-        {
-            if (isPublicField(field.getModifiers()) && !m.containsKey(field.getName()))
-                m.put(field.getName(), field);
-        }
-        return m;
-    }
-
-    /**
-     * Is this property on the ignore list for this class?
-     * @param c the class.
-     * @param propertyName the property name.
-     * @return true if we should ignore this property.
-     */
-    public static boolean isPropertyIgnored(Class c, String propertyName)
-    {
-        boolean result = false;
-        Set propertyOwners = (Set)ignoreProperties.get(propertyName);
-        if (propertyOwners != null)
-        {
-            while (c != null)
-            {
-                if (propertyOwners.contains(c))
-                {
-                    result = true;
-                    break;
-                }
-                c = c.getSuperclass();
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Add a property to the ignore list for this class.
-     * @param c the class.
-     * @param propertyName the property to ignore.
-     */
-    public static void addIgnoreProperty(Class c, String propertyName)
-    {
-        synchronized(ignoreProperties)
-        {
-            Set propertyOwners = (Set)ignoreProperties.get(propertyName);
-            if (propertyOwners == null)
-            {
-                propertyOwners = new HashSet();
-                ignoreProperties.put(propertyName, propertyOwners);
-            }
-            propertyOwners.add(c);
-        }
-    }
-
-    /**
-     * Do the provided modifiers indicate that this is public?
-     * @param modifiers the flags to check
-     * @return true if public but not final, static or transient.
-     */
-    public static boolean isPublicField(int modifiers)
-    {
-        return (Modifier.isPublic(modifiers) && !Modifier.isFinal(modifiers)
-                && !Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers));
-    }
-
-    /**
-     * Do the provided modifiers indicate that this is public?
-     * @param modifiers the flags to check
-     * @return true if public but not static.
-     */
-    public static boolean isPublicAccessor(int modifiers)
-    {
-        return (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers));
-    }
-
-    /**
-     * A class that holds information about a bean property.
-     */
-    protected static class BeanProperty
-    {
-        private String name;
-        private Class type;
-        private Method readMethod, writeMethod;
-        private Field field;
-
-        protected BeanProperty(String name, Class type, Method read, Method write, Field field)
-        {
-            this.name = name;
-            this.type = type;
-            this.writeMethod = write;
-            this.readMethod = read;
-            this.field = field;
-        }
-
-        /**
-         * The name of the property..
-         * @return the name.
-         */
-        public String getName()
-        {
-            return name;
-        }
-
-        /**
-         * The type of the property.
-         * @return the type
-         */
-        public Class getType()
-        {
-            return type;
-        }
-
-        /**
-         * Is there a setter for this property?
-         * @return true if there is a write method.
-         */
-        public boolean isWrite()
-        {
-            return writeMethod != null || field != null;
-        }
-
-        /**
-         * Is there a getter for this property?
-         * @return true if there is a read method.
-         */
-        public boolean isRead()
-        {
-            return readMethod != null || field != null;
-        }
-
-        /**
-         * Returns the Class object that declared the public field or getter function.
-         * @return an object of the declaring class for the read method or null if the read method is undefined.
-         */
-        public Class getReadDeclaringClass()
-        {
-            if (readMethod != null)
-                return readMethod.getDeclaringClass();
-            if (field != null)
-                return field.getDeclaringClass();
-            return null;
-        }
-
-        /**
-         * Return a class that represents the type of the property.
-         * @return the type of the property or null if there is no read method defined.
-         */
-        public Class getReadType()
-        {
-            if (readMethod != null)
-                return readMethod.getReturnType();
-            if (field != null)
-                return field.getType();
-            return null;
-        }
-
-        /**
-         *
-         * Returns a string indicating the setter or field name of the property.
-         * The setter is prefixed by 'method ', or the field is prefixed by 'field '.
-         * @return A string suitable for debugging.
-         */
-        public String getWriteName()
-        {
-            if (writeMethod != null)
-                return "method " + writeMethod.getName();
-            if (field != null)
-                return "field " + field.getName();
-            return null;
-        }
-
-        /**
-         * Set the property of the object to the specified value.
-         * @param bean the bean to set the property on.
-         * @param value the value to set.
-         * @throws IllegalAccessException if no access.
-         * @throws InvocationTargetException if the setter throws an exception.
-         */
-        public void set(Object bean, Object value) throws IllegalAccessException,
-                InvocationTargetException
-        {
-            if (writeMethod != null)
-                writeMethod.invoke(bean, value);
-            else if (field != null)
-                field.set(bean, value);
-            else
-                throw new MessageException("Setter not found for property " + name);
-        }
-
-        /**
-         * Get the value of this property from the specified object.
-         * @param bean the object to retrieve the value from
-         * @return the value of the property.
-         * @throws IllegalAccessException if no access.
-         * @throws InvocationTargetException if the getter throws an exception.
-         */
-        public Object get(Object bean) throws IllegalAccessException, InvocationTargetException
-        {
-            Object obj = null;
-            if (readMethod != null)
-                obj = readMethod.invoke(bean, (Object[])null);
-            else if (field != null)
-                obj = field.get(bean);
-            return obj;
-        }
-    }
-
-    /**
-     * Clears all static caches.
-     */
-    public static void clear()
-    {
-        synchronized(ignoreProperties)
-        {
-            ignoreProperties.clear();
-            initializeIgnoreProperties();  // reset to original state
-        }
-        synchronized(rwPropertyNamesCache)
-        {
-            rwPropertyNamesCache.clear();
-        }
-        synchronized(rwBeanPropertyCache)
-        {
-            rwBeanPropertyCache.clear();
-        }
-        synchronized(rwPropertyDescriptorCache)
-        {
-            rwPropertyDescriptorCache.clear();
-        }
-        synchronized(roPropertyNamesCache)
-        {
-            roPropertyNamesCache.clear();
-        }
-        synchronized(roBeanPropertyCache)
-        {
-            roBeanPropertyCache.clear();
-        }
-        synchronized(roPropertyDescriptorCache)
-        {
-            roPropertyDescriptorCache.clear();
-        }
-    }
-
-    /**
-     * A cache entry.
-     */
-    protected static class PropertyDescriptorCacheEntry
-    {
-        PropertyDescriptor [] propertyDescriptors;
-        Map propertiesByName;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.io;
+
+import flex.messaging.MessageException;
+import flex.messaging.io.amf.ASObject;
+import flex.messaging.log.Log;
+import flex.messaging.log.Logger;
+import flex.messaging.util.ClassUtil;
+import flex.messaging.util.ExceptionUtil;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Uses Bean introspection to collect the properties for a given instance.
+ *
+ * @author Peter Farland
+ */
+public class BeanProxy extends AbstractProxy
+{
+    static final long serialVersionUID = 7365078101695257715L;
+
+    private static final int FAILED_PROPERTY_READ_ERROR = 10021;
+    private static final int FAILED_PROPERTY_WRITE_ERROR = 10022;
+    private static final int NON_READABLE_PROPERTY_ERROR = 10023;
+    private static final int NON_WRITABLE_PROPERTY_ERROR = 10024;
+    private static final int UNKNOWN_PROPERTY_ERROR = 10025;
+
+    protected static final Map<Class, List<String>> rwPropertyNamesCache = new IdentityHashMap<Class, List<String>>();
+    protected static final Map<Class, Map<String, BeanProperty>> rwBeanPropertyCache = new IdentityHashMap<Class, Map<String, BeanProperty>>();
+    protected static final Map<Class, PropertyDescriptorCacheEntry> rwPropertyDescriptorCache = new IdentityHashMap<Class, PropertyDescriptorCacheEntry>();
+
+    protected static final Map<Class, List<String>> roPropertyNamesCache = new IdentityHashMap<Class, List<String>>();
+    protected static final Map<Class, Map<String, BeanProperty>> roBeanPropertyCache = new IdentityHashMap<Class, Map<String, BeanProperty>>();
+    protected static final Map<Class, PropertyDescriptorCacheEntry> roPropertyDescriptorCache = new IdentityHashMap<Class, PropertyDescriptorCacheEntry>();
+
+    protected boolean cacheProperties = true;
+    protected boolean cachePropertiesDescriptors = true;
+    protected Class stopClass = Object.class;
+
+    protected static final Map ignoreProperties = new HashMap();
+    static
+    {
+        initializeIgnoreProperties();
+    }
+
+    private static void initializeIgnoreProperties()
+    {
+        addIgnoreProperty(AbstractMap.class, "empty");
+        addIgnoreProperty(AbstractCollection.class, "empty");
+        addIgnoreProperty(ASObject.class, "type");
+        addIgnoreProperty(Throwable.class, "stackTrace");
+        addIgnoreProperty(File.class, "parentFile");
+        addIgnoreProperty(File.class, "canonicalFile");
+        addIgnoreProperty(File.class, "absoluteFile");
+    }
+
+    /**
+     * Constructor.
+     */
+    public BeanProxy()
+    {
+        this(null);
+    }
+
+    /**
+     * Construct a new BeanProxy with the provided default instance.
+     *
+     * @param defaultInstance defines the alias if provided
+     */
+    public BeanProxy(Object defaultInstance)
+    {
+        super(defaultInstance);
+
+        // Override default behavior here... standard Map implementations
+        // are treated as anonymous Objects, i.e. without an alias.
+        if (defaultInstance != null)
+            alias = getClassName(defaultInstance);
+    }
+
+    /** {@inheritDoc} */
+    public String getAlias(Object instance)
+    {
+        return getClassName(instance);
+    }
+
+    /** {@inheritDoc} */
+    public List getPropertyNames(Object instance)
+    {
+        if (instance == null)
+            return null;
+
+        Class c = instance.getClass();
+        List<String> propertyNames = null;
+
+        // Look up property names in cache if we don't have a custom serialization descriptor
+        if (descriptor == null)
+        {
+            if (getIncludeReadOnly())
+            {
+                synchronized (roPropertyNamesCache)
+                {
+                    propertyNames = roPropertyNamesCache.get(c);
+                }
+            }
+            else
+            {
+                synchronized (rwPropertyNamesCache)
+                {
+                    propertyNames = rwPropertyNamesCache.get(c);
+                }
+            }
+        }
+
+        if (propertyNames != null)
+            return propertyNames;
+
+        // Make a copy of the property names to return
+        propertyNames = new ArrayList<String>(getBeanProperties(instance).keySet());
+
+        // Store property names in cache if we are caching properties
+        // and we don't have a custom serialization descriptor
+        if (cacheProperties && descriptor == null)
+        {
+            if (getIncludeReadOnly())
+            {
+                synchronized (roPropertyNamesCache)
+                {
+                    roPropertyNamesCache.put(c, propertyNames);
+                }
+            }
+            else
+            {
+                synchronized (rwPropertyNamesCache)
+                {
+                    rwPropertyNamesCache.put(c, propertyNames);
+                }
+            }
+        }
+        return propertyNames;
+    }
+
+
+    /** {@inheritDoc} */
+    public Class getType(Object instance, String propertyName)
+    {
+        if (instance == null || propertyName == null)
+            return null;
+
+        BeanProperty bp = getBeanProperty(instance, propertyName);
+        return bp == null? null : bp.getType();
+    }
+
+    /** {@inheritDoc} */
+    public Object getValue(Object instance, String propertyName)
+    {
+        if (instance == null || propertyName == null)
+            return null;
+
+        BeanProperty bp = getBeanProperty(instance, propertyName);
+        if (bp != null)
+            return getBeanValue(instance, bp);
+
+        SerializationContext context = getSerializationContext();
+        if (!ignorePropertyErrors(context))
+        {
+            // Property '{propertyName}' not found on class '{alias}'.
+            MessageException ex = new MessageException();
+            ex.setMessage(UNKNOWN_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
+            throw ex;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the value specified by the BeanProperty.
+     * @param instance Object to get the value from
+     * @param bp the property to get
+     * @return the value of the property if it exists
+     */
+    protected final Object getBeanValue(Object instance, BeanProperty bp)
+    {
+        String propertyName = bp.getName();
+        if (bp.isRead())
+        {
+            try
+            {
+                Object value = bp.get(instance);
+                if (value != null && descriptor != null)
+                {
+                    SerializationDescriptor subDescriptor = (SerializationDescriptor)descriptor.get(propertyName);
+                    if (subDescriptor != null)
+                    {
+                        PropertyProxy subProxy = PropertyProxyRegistry.getProxyAndRegister(value);
+                        subProxy = (PropertyProxy)subProxy.clone();
+                        subProxy.setDescriptor(subDescriptor);
+                        subProxy.setDefaultInstance(value);
+                        value = subProxy;
+                    }
+                }
+                return value;
+            }
+            catch (Exception e)
+            {
+                SerializationContext context = getSerializationContext();
+
+                // Log failed property set errors
+                if (Log.isWarn() && logPropertyErrors(context))
+                {
+                    Logger log = Log.getLogger(LOG_CATEGORY);
+                    log.warn("Failed to get property {0} on type {1}.",
+                             new Object[] {propertyName, getAlias(instance)}, e);
+                }
+
+                if (!ignorePropertyErrors(context))
+                {
+                    // Failed to get property '{propertyName}' on type '{className}'.
+                    MessageException ex = new MessageException();
+                    ex.setMessage(FAILED_PROPERTY_READ_ERROR, new Object[] {propertyName, getAlias(instance)});
+                    ex.setRootCause(e);
+                    throw ex;
+                }
+            }
+        }
+        else
+        {
+            SerializationContext context = getSerializationContext();
+            if (!ignorePropertyErrors(context))
+            {
+                //Property '{propertyName}' not readable from class '{alias}'.
+                MessageException ex = new MessageException();
+                ex.setMessage(NON_READABLE_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
+                throw ex;
+            }
+        }
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public void setValue(Object instance, String propertyName, Object value)
+    {
+        BeanProperty bp = getBeanProperty(instance, propertyName);
+
+        if (bp != null)
+        {
+            if (bp.isWrite())
+            {
+                try
+                {
+                    Class desiredPropClass = bp.getType();
+                    TypeMarshaller marshaller = TypeMarshallingContext.getTypeMarshaller();
+                    value = marshaller.convert(value, desiredPropClass);
+                    ClassUtil.validateAssignment(instance, propertyName, value);
+                    bp.set(instance, value);
+                }
+                catch (Exception e)
+                {
+                    SerializationContext context = getSerializationContext();
+
+                    // Log ignore failed property set errors
+                    if (Log.isWarn() && logPropertyErrors(context))
+                    {
+                        Logger log = Log.getLogger(LOG_CATEGORY);
+                        log.warn("Failed to set property {0} on type {1}.",
+                                new Object[] {propertyName, getAlias(instance)}, e);
+                    }
+
+                    if (!ignorePropertyErrors(context))
+                    {
+                        // Failed to get property '{propertyName}' on type '{className}'.
+                        MessageException ex = new MessageException();
+                        ex.setMessage(FAILED_PROPERTY_WRITE_ERROR, new Object[] {propertyName, getAlias(instance)});
+                        ex.setRootCause(e);
+                        throw ex;
+                    }
+                }
+            }
+            else
+            {
+                SerializationContext context = getSerializationContext();
+
+                if (Log.isWarn() && logPropertyErrors(context))
+                {
+                    Logger log = Log.getLogger(LOG_CATEGORY);
+                    log.warn("Property {0} not writable on class {1}",
+                            new Object[] {propertyName, getAlias(instance)});
+                }
+
+                if (!ignorePropertyErrors(context))
+                {
+                    //Property '{propertyName}' not writable on class '{alias}'.
+                    MessageException ex = new MessageException();
+                    ex.setMessage(NON_WRITABLE_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
+                    throw ex;
+                }
+            }
+        }
+        else
+        {
+            SerializationContext context = getSerializationContext();
+
+            if (Log.isWarn() && logPropertyErrors(context))
+            {
+                Logger log = Log.getLogger(LOG_CATEGORY);
+                log.warn("Ignoring set property {0} for type {1} as a setter could not be found.",
+                            new Object[] {propertyName, getAlias(instance)});
+            }
+
+            if (!ignorePropertyErrors(context))
+            {
+                // Property '{propertyName}' not found on class '{alias}'.
+                MessageException ex = new MessageException();
+                ex.setMessage(UNKNOWN_PROPERTY_ERROR, new Object[] {propertyName, getAlias(instance)});
+                throw ex;
+            }
+        }
+    }
+
+    /**
+     * Are we ignoring property errors?
+     * @param context serialization paramters.
+     * @return true if ignoring property errors.
+     */
+    protected boolean ignorePropertyErrors(SerializationContext context)
+    {
+        return context.ignorePropertyErrors;
+    }
+
+    /**
+     * Should we log property errors?
+     * @param context serialization parameters.
+     * @return true if we should log property errors.
+     */
+    protected boolean logPropertyErrors(SerializationContext context)
+    {
+        return context.logPropertyErrors;
+    }
+
+    /**
+     * Determins the classname for both normal types via Class.getName() and
+     * virtual types via ASObject.getType(). Virtual types starting
+     * with the special ">" token are also handled and the underlying
+     * className is returned.
+     *
+     * @param instance the object to examine.
+     * @return the classname to use for instances of this type
+     */
+    protected String getClassName(Object instance)
+    {
+        String className;
+
+        if (instance instanceof ASObject)
+        {
+            className = ((ASObject)instance).getType();
+        }
+        else if (instance instanceof ClassAlias)
+        {
+            className = ((ClassAlias)instance).getAlias();
+        }
+        else
+        {
+            className = instance.getClass().getName();
+            // If there's an alias, use that as the class name.
+            ClassAliasRegistry registry = ClassAliasRegistry.getRegistry();
+            String aliasedClass = registry.getClassName(className);
+            className = (aliasedClass == null)? className : aliasedClass;
+        }
+
+        return className;
+    }
+
+    /**
+     * Return a map of properties for a object.
+     * @param instance object to examine.
+     * @return a map of Strings to BeanProperty objects.
+     */
+    protected Map<String, BeanProperty> getBeanProperties(Object instance)
+    {
+        Class c = instance.getClass();
+        Map<String, BeanProperty> props;
+
+        // look up instance class in cache if we don't have a custom descriptor.
+        if (descriptor == null)
+        {
+            if (getIncludeReadOnly())
+            {
+                synchronized (roBeanPropertyCache)
+                {
+                    props = roBeanPropertyCache.get(c);
+                }
+            }
+            else
+            {
+                synchronized (rwBeanPropertyCache)
+                {
+                    props = roBeanPropertyCache.get(c);
+
+                }
+            }
+            if (props != null)
+                return props;
+        }
+
+        props = new HashMap<String, BeanProperty>();
+        PropertyDescriptor[] pds = getPropertyDescriptors(c);
+        if (pds == null)
+            return null;
+
+        List excludes = null;
+        if (descriptor != null)
+        {
+            excludes = descriptor.getExcludesForInstance(instance);
+            if (excludes == null) // For compatibility with older implementations
+                excludes = descriptor.getExcludes();
+        }
+
+        // Add standard bean properties first
+        for (PropertyDescriptor pd : pds)
+        {
+            String propertyName = pd.getName();
+            Method readMethod = pd.getReadMethod();
+            Method writeMethod = pd.getWriteMethod();
+
+            // If there's a public read method but no writeMethod and includeReadOnly
+            // flag is off, then skip the property.
+            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) && !getIncludeReadOnly() && writeMethod == null)
+                continue;
+
+            // Skip excluded and ignored properties as well.
+            if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
+                continue;
+
+            // Ensure we don't include Object getClass() property, possibly returned (incorrectly) by custom BeanInfos
+            if (getIncludeReadOnly() && writeMethod == null && "class".equals(propertyName))
+                continue;
+
+            // Skip any classloader properties
+            final Class<?> type = pd.getPropertyType();
+            if (type != null && ClassLoader.class.isAssignableFrom(type))
+                continue;
+
+            props.put(propertyName, new BeanProperty(propertyName, pd.getPropertyType(),
+                    readMethod, writeMethod, null));
+        }
+
+        // Then add public fields to list if property does not already exist
+        Field[] fields = instance.getClass().getFields();
+        for (Field field : fields)
+        {
+            String propertyName = field.getName();
+            int modifiers = field.getModifiers();
+            if (isPublicField(modifiers) && !props.containsKey(propertyName))
+            {
+                // Skip excluded and ignored properties.
+                if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
+                    continue;
+
+                props.put(propertyName, new BeanProperty(propertyName, field.getType(), null, null, field));
+            }
+        }
+
+        // Update the cache if we don't have a custom serialization descriptor and we are caching.
+        if (descriptor == null && cacheProperties)
+        {
+            if (getIncludeReadOnly())
+            {
+                synchronized (roBeanPropertyCache)
+                {
+                    roBeanPropertyCache.put(c, props);
+                }
+            }
+            else
+            {
+                synchronized (rwBeanPropertyCache)
+                {
+                    roBeanPropertyCache.put(c, props);
+
+                }
+            }
+        }
+
+        return props;
+    }
+
+    /**
+     * Return true if this property is write only, which means we cannot get a value for it.
+     *
+     * @param instance the instance
+     * @param propertyName the property name
+     * @return true if there is a way to write but not read the property
+     */
+    public boolean isWriteOnly(Object instance, String propertyName)
+    {
+        if (instance == null || propertyName == null)
+            return false;
+
+        BeanProperty bp = getBeanProperty(instance, propertyName);
+        return bp != null && bp.isWrite() && !bp.isRead();
+    }
+
+    /**
+     * Return a specific property descriptor for a named property.
+     * @param instance the object to use.
+     * @param propertyName the property to get.
+     * @return a descriptor for the property.
+     */
+    protected final BeanProperty getBeanProperty(Object instance, String propertyName)
+    {
+        Class c = instance.getClass();
+        Map props;
+
+        // It is faster to use the BeanProperty cache if we are going to cache it.
+        if (descriptor == null && cacheProperties)
+        {
+            props = getBeanProperties(instance);
+            return props == null? null : (BeanProperty)props.get(propertyName);
+        }
+
+        // Otherwise, just build up the property we are asked for
+        PropertyDescriptorCacheEntry pce =  getPropertyDescriptorCacheEntry(c);
+        if (pce == null)
+            return null;
+
+        Object pType = pce.propertiesByName.get(propertyName);
+        if (pType == null)
+            return null;
+
+        List excludes = null;
+        if (descriptor != null)
+        {
+            excludes = descriptor.getExcludesForInstance(instance);
+            if (excludes == null) // For compatibility with older implementations
+                excludes = descriptor.getExcludes();
+        }
+
+        if (pType instanceof PropertyDescriptor)
+        {
+            PropertyDescriptor pd = (PropertyDescriptor) pType;
+
+            Method readMethod = pd.getReadMethod();
+            Method writeMethod = pd.getWriteMethod();
+
+            // If there's a public read method but no writeMethod and includeReadOnly
+            // flag is off, then skip the property.
+            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) && !getIncludeReadOnly() && writeMethod == null)
+                return null;
+
+            // Skip excluded and ignored properties as well.
+            if ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))
+                return null;
+
+            return new BeanProperty(propertyName, pd.getPropertyType(), readMethod, writeMethod, null);
+        }
+        else if (pType instanceof Field)
+        {
+            Field field = (Field) pType;
+
+            String pName = field.getName();
+            int modifiers = field.getModifiers();
+            if (isPublicField(modifiers) && pName.equals(propertyName))
+            {
+                // Skip excluded and ignored properties.
+                return ((excludes != null && excludes.contains(propertyName)) || isPropertyIgnored(c, propertyName))?
+                        null : new BeanProperty(propertyName, field.getType(), null, null, field);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return an array of JavaBean property descriptors for a class.
+     * @param c the class to examine.
+     * @return an array ot JavaBean PropertyDescriptors.
+     */
+    private PropertyDescriptor [] getPropertyDescriptors(Class c)
+    {
+        PropertyDescriptorCacheEntry pce = getPropertyDescriptorCacheEntry(c);
+        return pce == null? null : pce.propertyDescriptors;
+    }
+
+    /**
+     * Return an entry from the property descriptor cache for a class.
+     * @param c the class
+     * @return a descriptor cache entry or null
+     */
+    private PropertyDescriptorCacheEntry getPropertyDescriptorCacheEntry(Class c)
+    {
+        PropertyDescriptorCacheEntry pce;
+        if (getIncludeReadOnly())
+        {
+            synchronized (roPropertyDescriptorCache)
+            {
+                pce = roPropertyDescriptorCache.get(c);
+            }
+        }
+        else
+        {
+            synchronized (rwPropertyDescriptorCache)
+            {
+                pce = rwPropertyDescriptorCache.get(c);
+            }
+        }
+        
+        try
+        {
+            if (pce == null)
+            {
+                BeanInfo beanInfo = Introspector.getBeanInfo(c, stopClass);
+                pce = new PropertyDescriptorCacheEntry();
+                pce.propertyDescriptors = beanInfo.getPropertyDescriptors();
+                pce.propertiesByName = createPropertiesByNameMap(pce.propertyDescriptors, c.getFields());
+                if (cachePropertiesDescriptors)
+                {
+                    if (getIncludeReadOnly())
+                    {
+                        synchronized (roPropertyDescriptorCache)
+                        {
+                            roPropertyDescriptorCache.put(c, pce);
+                        }
+                    }
+                    else
+                    {
+                        synchronized (rwPropertyDescriptorCache)
+                        {
+                            rwPropertyDescriptorCache.put(c, pce);
+                        }
+                    }
+                }
+            }
+        }
+        catch (IntrospectionException ex)
+        {
+            // Log failed property set errors
+            if (Log.isError())
+            {
+                Logger log = Log.getLogger(LOG_CATEGORY);
+                log.error("Failed to introspect object of type: " + c + " error: " + ExceptionUtil.toString(ex));
+            }
+
+            // Return an empty descriptor rather than crashing
+            pce = new PropertyDescriptorCacheEntry();
+            pce.propertyDescriptors = new PropertyDescriptor[0];
+            pce.propertiesByName = new TreeMap();
+        }
+        return pce;
+    }
+
+    private Map createPropertiesByNameMap(PropertyDescriptor [] pds, Field [] fields)
+    {
+        Map m = new HashMap(pds.length);
+        for (PropertyDescriptor pd : pds)
+        {
+            Method readMethod = pd.getReadMethod();
+            if (readMethod != null && isPublicAccessor(readMethod.getModifiers()) &&
+                    (getIncludeReadOnly() || pd.getWriteMethod() != null))
+                m.put(pd.getName(), pd);
+        }
+        for (Field field : fields)
+        {
+            if (isPublicField(field.getModifiers()) && !m.containsKey(field.getName()))
+                m.put(field.getName(), field);
+        }
+        return m;
+    }
+
+    /**
+     * Is this property on the ignore list for this class?
+     * @param c the class.
+     * @param propertyName the property name.
+     * @return true if we should ignore this property.
+     */
+    public static boolean isPropertyIgnored(Class c, String propertyName)
+    {
+        boolean result = false;
+        Set propertyOwners = (Set)ignoreProperties.get(propertyName);
+        if (propertyOwners != null)
+        {
+            while (c != null)
+            {
+                if (propertyOwners.contains(c))
+                {
+                    result = true;
+                    break;
+                }
+                c = c.getSuperclass();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Add a property to the ignore list for this class.
+     * @param c the class.
+     * @param propertyName the property to ignore.
+     */
+    public static void addIgnoreProperty(Class c, String propertyName)
+    {
+        synchronized(ignoreProperties)
+        {
+            Set propertyOwners = (Set)ignoreProperties.get(propertyName);
+            if (propertyOwners == null)
+            {
+                propertyOwners = new HashSet();
+                ignoreProperties.put(propertyName, propertyOwners);
+            }
+            propertyOwners.add(c);
+        }
+    }
+
+    /**
+     * Do the provided modifiers indicate that this is public?
+     * @param modifiers the flags to check
+     * @return true if public but not final, static or transient.
+     */
+    public static boolean isPublicField(int modifiers)
+    {
+        return (Modifier.isPublic(modifiers) && !Modifier.isFinal(modifiers)
+                && !Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers));
+    }
+
+    /**
+     * Do the provided modifiers indicate that this is public?
+     * @param modifiers the flags to check
+     * @return true if public but not static.
+     */
+    public static boolean isPublicAccessor(int modifiers)
+    {
+        return (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers));
+    }
+
+    /**
+     * A class that holds information about a bean property.
+     */
+    protected static class BeanProperty
+    {
+        private String name;
+        private Class type;
+        private Method readMethod, writeMethod;
+        private Field field;
+
+        protected BeanProperty(String name, Class type, Method read, Method write, Field field)
+        {
+            this.name = name;
+            this.type = type;
+            this.writeMethod = write;
+            this.readMethod = read;
+            this.field = field;
+        }
+
+        /**
+         * The name of the property..
+         * @return the name.
+         */
+        public String getName()
+        {
+            return name;
+        }
+
+        /**
+         * The type of the property.
+         * @return the type
+         */
+        public Class getType()
+        {
+            return type;
+        }
+
+        /**
+         * Is there a setter for this property?
+         * @return true if there is a write method.
+         */
+        public boolean isWrite()
+        {
+            return writeMethod != null || field != null;
+        }
+
+        /**
+         * Is there a getter for this property?
+         * @return true if there is a read method.
+         */
+        public boolean isRead()
+        {
+            return readMethod != null || field != null;
+        }
+
+        /**
+         * Returns the Class object that declared the public field or getter function.
+         * @return an object of the declaring class for the read method or null if the read method is undefined.
+         */
+        public Class getReadDeclaringClass()
+        {
+            if (readMethod != null)
+                return readMethod.getDeclaringClass();
+            if (field != null)
+                return field.getDeclaringClass();
+            return null;
+        }
+
+        /**
+         * Return a class that represents the type of the property.
+         * @return the type of the property or null if there is no read method defined.
+         */
+        public Class getReadType()
+        {
+            if (readMethod != null)
+                return readMethod.getReturnType();
+            if (field != null)
+                return field.getType();
+            return null;
+        }
+
+        /**
+         *
+         * Returns a string indicating the setter or field name of the property.
+         * The setter is prefixed by 'method ', or the field is prefixed by 'field '.
+         * @return A string suitable for debugging.
+         */
+        public String getWriteName()
+        {
+            if (writeMethod != null)
+                return "method " + writeMethod.getName();
+            if (field != null)
+                return "field " + field.getName();
+            return null;
+        }
+
+        /**
+         * Set the property of the object to the specified value.
+         * @param bean the bean to set the property on.
+         * @param value the value to set.
+         * @throws IllegalAccessException if no access.
+         * @throws InvocationTargetException if the setter throws an exception.
+         */
+        public void set(Object bean, Object value) throws IllegalAccessException,
+                InvocationTargetException
+        {
+            if (writeMethod != null)
+                writeMethod.invoke(bean, value);
+            else if (field != null)
+                field.set(bean, value);
+            else
+                throw new MessageException("Setter not found for property " + name);
+        }
+
+        /**
+         * Get the value of this property from the specified object.
+         * @param bean the object to retrieve the value from
+         * @return the value of the property.
+         * @throws IllegalAccessException if no access.
+         * @throws InvocationTargetException if the getter throws an exception.
+         */
+        public Object get(Object bean) throws IllegalAccessException, InvocationTargetException
+        {
+            Object obj = null;
+            if (readMethod != null)
+                obj = readMethod.invoke(bean, (Object[])null);
+            else if (field != null)
+                obj = field.get(bean);
+            return obj;
+        }
+    }
+
+    /**
+     * Clears all static caches.
+     */
+    public static void clear()
+    {
+        synchronized(ignoreProperties)
+        {
+            ignoreProperties.clear();
+            initializeIgnoreProperties();  // reset to original state
+        }
+        synchronized(rwPropertyNamesCache)
+        {
+            rwPropertyNamesCache.clear();
+        }
+        synchronized(rwBeanPropertyCache)
+        {
+            rwBeanPropertyCache.clear();
+        }
+        synchronized(rwPropertyDescriptorCache)
+        {
+            rwPropertyDescriptorCache.clear();
+        }
+        synchronized(roPropertyNamesCache)
+        {
+            roPropertyNamesCache.clear();
+        }
+        synchronized(roBeanPropertyCache)
+        {
+            roBeanPropertyCache.clear();
+        }
+        synchronized(roPropertyDescriptorCache)
+        {
+            roPropertyDescriptorCache.clear();
+        }
+    }
+
+    /**
+     * A cache entry.
+     */
+    protected static class PropertyDescriptorCacheEntry
+    {
+        PropertyDescriptor [] propertyDescriptors;
+        Map propertiesByName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/4f6a3052/modules/core/src/flex/messaging/io/ClassAlias.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/io/ClassAlias.java b/modules/core/src/flex/messaging/io/ClassAlias.java
old mode 100755
new mode 100644
index 6bc9407..5bf8cdc
--- a/modules/core/src/flex/messaging/io/ClassAlias.java
+++ b/modules/core/src/flex/messaging/io/ClassAlias.java
@@ -1,29 +1,29 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package flex.messaging.io;
-
-/**
- * A Class can implement this interface to customize the alias reported by
- * a BeanProxy when describing a complex object's traits. 
- */
-public interface ClassAlias
-{
-    /**
-     * The alias to use for this instance.  
-     */
-    public String getAlias();
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.io;
+
+/**
+ * A Class can implement this interface to customize the alias reported by
+ * a BeanProxy when describing a complex object's traits. 
+ */
+public interface ClassAlias
+{
+    /**
+     * The alias to use for this instance.  
+     */
+    public String getAlias();
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/4f6a3052/modules/core/src/flex/messaging/io/ClassAliasRegistry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/io/ClassAliasRegistry.java b/modules/core/src/flex/messaging/io/ClassAliasRegistry.java
old mode 100755
new mode 100644
index 3a6fa80..b97eaaa
--- a/modules/core/src/flex/messaging/io/ClassAliasRegistry.java
+++ b/modules/core/src/flex/messaging/io/ClassAliasRegistry.java
@@ -1,98 +1,98 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package flex.messaging.io;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A simple registry that maps an alias to a concrete class name. This registry
- * mimics the ActionScript 3 flash.net.registerClassAlias() functionality
- * of the Flash Player. The registry is checked when deserializing AMF object
- * types.
- */
-public class ClassAliasRegistry
-{
-    private Map aliasRegistry = new HashMap();
-    private static final ClassAliasRegistry registry = new ClassAliasRegistry();
-
-    /**
-     * Constructs an empty registry.
-     */
-    private ClassAliasRegistry()
-    {
-    }
-
-    /**
-     * Returns the registry singleton.
-     */
-    public static ClassAliasRegistry getRegistry()
-    {
-        return registry;
-    }
-
-    /**
-     * Looks for a concrete class name for an alias.
-     * 
-     * @param alias The alias used to search the registry. 
-     * @return a concrete class name, if registered for this alias, otherwise
-     * null.
-     */
-    public String getClassName(String alias)
-    {
-        return (String)aliasRegistry.get(alias);
-    }
-
-    /**
-     * Clears all items from the registry.
-     */
-    public void clear()
-    {
-        synchronized(aliasRegistry)
-        {
-            aliasRegistry.clear();
-        }
-    }
-
-    /**
-     * Registers a custom alias for a class name.
-     * 
-     * @param alias The alias for the class name.
-     * @param className The concrete class name.
-     */
-    public void registerAlias(String alias, String className)
-    {
-        synchronized(aliasRegistry)
-        {
-            aliasRegistry.put(alias, className);
-        }
-    }
-
-    /**
-     * Removes a class alias from the registry.
-     * 
-     * @param alias The alias to be removed from the registry.
-     */
-    public void unregisterAlias(String alias)
-    {
-        synchronized(aliasRegistry)
-        {
-            aliasRegistry.remove(alias);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package flex.messaging.io;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A simple registry that maps an alias to a concrete class name. This registry
+ * mimics the ActionScript 3 flash.net.registerClassAlias() functionality
+ * of the Flash Player. The registry is checked when deserializing AMF object
+ * types.
+ */
+public class ClassAliasRegistry
+{
+    private Map aliasRegistry = new HashMap();
+    private static final ClassAliasRegistry registry = new ClassAliasRegistry();
+
+    /**
+     * Constructs an empty registry.
+     */
+    private ClassAliasRegistry()
+    {
+    }
+
+    /**
+     * Returns the registry singleton.
+     */
+    public static ClassAliasRegistry getRegistry()
+    {
+        return registry;
+    }
+
+    /**
+     * Looks for a concrete class name for an alias.
+     * 
+     * @param alias The alias used to search the registry. 
+     * @return a concrete class name, if registered for this alias, otherwise
+     * null.
+     */
+    public String getClassName(String alias)
+    {
+        return (String)aliasRegistry.get(alias);
+    }
+
+    /**
+     * Clears all items from the registry.
+     */
+    public void clear()
+    {
+        synchronized(aliasRegistry)
+        {
+            aliasRegistry.clear();
+        }
+    }
+
+    /**
+     * Registers a custom alias for a class name.
+     * 
+     * @param alias The alias for the class name.
+     * @param className The concrete class name.
+     */
+    public void registerAlias(String alias, String className)
+    {
+        synchronized(aliasRegistry)
+        {
+            aliasRegistry.put(alias, className);
+        }
+    }
+
+    /**
+     * Removes a class alias from the registry.
+     * 
+     * @param alias The alias to be removed from the registry.
+     */
+    public void unregisterAlias(String alias)
+    {
+        synchronized(aliasRegistry)
+        {
+            aliasRegistry.remove(alias);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/4f6a3052/modules/core/src/flex/messaging/io/DictionaryProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/io/DictionaryProxy.java b/modules/core/src/flex/messaging/io/DictionaryProxy.java
old mode 100755
new mode 100644
index e579963..8a44bd3
--- a/modules/core/src/flex/messaging/io/DictionaryProxy.java
+++ b/modules/core/src/flex/messaging/io/DictionaryProxy.java
@@ -1,112 +1,112 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package flex.messaging.io;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.List;
-
-/**
- * Proxies serialization of a Dictionary and considers all keys as String based property 
- * names. Additionally, bean properties from the instance are also included and override 
- * any Dictionary entries with the same name.
- *  
- * @author Peter Farland
- */
-public class DictionaryProxy extends BeanProxy
-{
-    static final long serialVersionUID = 1501461889185692712L;
-
-    public DictionaryProxy()
-    {
-        super();
-        //dynamic = true;
-    }
-
-    public DictionaryProxy(Dictionary defaultInstance)
-    {
-        super(defaultInstance);
-    }
-
-    public List getPropertyNames(Object instance)
-    {
-        if (instance == null)
-            return null;
-
-        List propertyNames = null;
-        List excludes = null;
-
-        if (descriptor != null)
-        {
-            excludes = descriptor.getExcludesForInstance(instance);
-            if (excludes == null)
-                excludes = descriptor.getExcludes();
-        }
-
-        // Add all Dictionary keys as properties
-        if (instance instanceof Dictionary)
-        {
-            Dictionary dictionary = (Dictionary)instance;
-
-            propertyNames = new ArrayList(dictionary.size());
-
-            Enumeration keys = dictionary.keys();
-            while (keys.hasMoreElements())
-            {
-                Object key = keys.nextElement();
-                if (key != null)
-                {
-                    if (excludes != null && excludes.contains(key))
-                        continue;
-
-                    propertyNames.add(key.toString());
-                }
-            }
-        }
-
-        // Then, check for bean properties
-        List beanProperties = super.getPropertyNames(instance);
-        if (propertyNames == null)
-        {
-            propertyNames = beanProperties;
-        }
-        else
-        {
-            propertyNames.addAll(beanProperties);
-        }
-
-        return propertyNames;
-    }
-
-    public Object getValue(Object instance, String propertyName)
-    {
-        if (instance == null || propertyName == null)
-            return null;
-
-        // First, check for bean property
-        Object value = super.getValue(instance, propertyName);
-
-        // Then check for Dictionary entry
-        if (value == null && instance instanceof Dictionary)
-        {
-            Dictionary dictionary = (Dictionary)instance;
-            value = dictionary.get(propertyName);
-        }
-
-        return value; 
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.io;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * Proxies serialization of a Dictionary and considers all keys as String based property 
+ * names. Additionally, bean properties from the instance are also included and override 
+ * any Dictionary entries with the same name.
+ *  
+ * @author Peter Farland
+ */
+public class DictionaryProxy extends BeanProxy
+{
+    static final long serialVersionUID = 1501461889185692712L;
+
+    public DictionaryProxy()
+    {
+        super();
+        //dynamic = true;
+    }
+
+    public DictionaryProxy(Dictionary defaultInstance)
+    {
+        super(defaultInstance);
+    }
+
+    public List getPropertyNames(Object instance)
+    {
+        if (instance == null)
+            return null;
+
+        List propertyNames = null;
+        List excludes = null;
+
+        if (descriptor != null)
+        {
+            excludes = descriptor.getExcludesForInstance(instance);
+            if (excludes == null)
+                excludes = descriptor.getExcludes();
+        }
+
+        // Add all Dictionary keys as properties
+        if (instance instanceof Dictionary)
+        {
+            Dictionary dictionary = (Dictionary)instance;
+
+            propertyNames = new ArrayList(dictionary.size());
+
+            Enumeration keys = dictionary.keys();
+            while (keys.hasMoreElements())
+            {
+                Object key = keys.nextElement();
+                if (key != null)
+                {
+                    if (excludes != null && excludes.contains(key))
+                        continue;
+
+                    propertyNames.add(key.toString());
+                }
+            }
+        }
+
+        // Then, check for bean properties
+        List beanProperties = super.getPropertyNames(instance);
+        if (propertyNames == null)
+        {
+            propertyNames = beanProperties;
+        }
+        else
+        {
+            propertyNames.addAll(beanProperties);
+        }
+
+        return propertyNames;
+    }
+
+    public Object getValue(Object instance, String propertyName)
+    {
+        if (instance == null || propertyName == null)
+            return null;
+
+        // First, check for bean property
+        Object value = super.getValue(instance, propertyName);
+
+        // Then check for Dictionary entry
+        if (value == null && instance instanceof Dictionary)
+        {
+            Dictionary dictionary = (Dictionary)instance;
+            value = dictionary.get(propertyName);
+        }
+
+        return value; 
+    }
+}