/*
 * 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.amfx;

import java.io.ByteArrayInputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.Dictionary;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.xml.sax.Attributes;

import flex.messaging.MessageException;
import flex.messaging.io.AbstractProxy;
import flex.messaging.io.ArrayCollection;
import flex.messaging.io.BeanProxy;
import flex.messaging.io.ClassAliasRegistry;
import flex.messaging.io.PropertyProxy;
import flex.messaging.io.PropertyProxyRegistry;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.SerializationException;
import flex.messaging.io.TypeMarshallingContext;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.ActionMessage;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.AmfTrace;
import flex.messaging.io.amf.MessageBody;
import flex.messaging.io.amf.MessageHeader;
import flex.messaging.util.ClassUtil;
import flex.messaging.util.Hex;
import flex.messaging.util.XMLUtil;

/**
 * Context for AMFX specific SAX handler.Contains start and end tag handlers for each of
 * the XML elements that occur in an AMFX request. The AmfxMessageDeserializer enforces
 * a naming convention for these handlers of xyz_start for the start handler and xyz_end
 * for the end handler of element xyz.
 *
 * Note that this context MUST be reset if reused between AMFX packet parsings.
 *
 * @see AmfxMessageDeserializer
 * @see AmfxOutput
 */
public class AmfxInput
{
    /**
     * This is the initial capacity that will be used for AMF arrays that have
     * length greater than 1024.
     */
    public static final int INITIAL_ARRAY_CAPACITY = 1024;

    private SerializationContext context;
    private BeanProxy beanproxy = new BeanProxy();

    private final ArrayList objectTable;
    private final ArrayList stringTable;
    private final ArrayList traitsTable;

    private StringBuffer text;

    private ActionMessage message;
    private MessageHeader currentHeader;
    private MessageBody currentBody;
    private Stack objectStack;
    private Stack proxyStack;
    private Stack arrayPropertyStack;
    private Stack ecmaArrayIndexStack;
    private Stack strictArrayIndexStack;
    private Stack dictionaryStack;
    private Stack traitsStack;
    private boolean isStringReference;
    private boolean isTraitProperty;

    /*
     *  DEBUG LOGGING
     */
    protected boolean isDebug;
    protected AmfTrace trace;

    /**
     * Constructor.
     * Construct an AmfxInput by passing in a <code>SerialziationContext</code> object
     *
     * @param context the <code>SerialziationContext</code> object
     */
    public AmfxInput(SerializationContext context)
    {
        this.context = context;

        stringTable = new ArrayList(64);
        objectTable = new ArrayList(64);
        traitsTable = new ArrayList(10);

        objectStack = new Stack();
        proxyStack = new Stack();
        arrayPropertyStack = new Stack();
        dictionaryStack = new Stack();
        strictArrayIndexStack = new Stack();
        ecmaArrayIndexStack = new Stack();
        traitsStack = new Stack();

        text = new StringBuffer(32);
    }

    /**
     * Reset the AmfxInput object.
     */
    public void reset()
    {
        stringTable.clear();
        objectTable.clear();
        traitsTable.clear();
        objectStack.clear();
        proxyStack.clear();
        arrayPropertyStack.clear();
        dictionaryStack.clear();
        traitsStack.clear();
        currentBody = null;
        currentHeader = null;

        TypeMarshallingContext marshallingContext = TypeMarshallingContext.getTypeMarshallingContext();
        marshallingContext.reset();
    }

    /**
     * Set Debug trace.
     *
     * @param trace current <code>AmfTrace</code> setting
     */
    public void setDebugTrace(AmfTrace trace)
    {
        this.trace = trace;
        isDebug = this.trace != null;
    }

    /**
     * Set Action Message.
     *
     * @param msg current <code>ActionMessage</code>
     */
    public void setActionMessage(ActionMessage msg)
    {
        message = msg;
    }

    /**
     * Read object from the AmfxInput object.
     *
     * @return currently return null, not supported
     * @throws IOException when reading the object has the IOException
     */
    public Object readObject() throws IOException
    {
        return null;
    }


    /**
     * Append a string to text.
     * XML Considerations
     *
     * @param s the String to append
     */
    public void text(String s)
    {
        text.append(s);
    }


    //
    // AMFX Message Structure
    //

    /**
     * Start the amfx process by setting the ActionMessage version.
     *
     * @param attributes current Attributes
     */
    public void start_amfx(Attributes attributes)
    {
        String ver = attributes.getValue("ver");
        int version = ActionMessage.CURRENT_VERSION;
        if (ver != null)
        {
            try
            {
                version = Integer.parseInt(ver);
            }
            catch (NumberFormatException ex)
            {
                throw new MessageException("Unknown version: " + ver);
            }
        }

        if (isDebug)
            trace.version(version);

        message.setVersion(version);
    }

    /**
     * End the Amfx process.
     *
     */
    public void end_amfx()
    {
    }

    /**
     * Start the process of message headers.
     *
     * @param attributes current Attributes
     */
    public void start_header(Attributes attributes)
    {
        if (currentHeader != null || currentBody != null)
            throw new MessageException("Unexpected header tag.");

        currentHeader = new MessageHeader();

        String name = attributes.getValue("name");
        currentHeader.setName(name);

        String mu = attributes.getValue("mustUnderstand");
        boolean mustUnderstand = false;
        if (mu != null)
        {
            mustUnderstand = Boolean.valueOf(mu).booleanValue();
            currentHeader.setMustUnderstand(mustUnderstand);
        }

        if (isDebug)
            trace.startHeader(name, mustUnderstand, message.getHeaderCount());
    }

    /**
     * End process of message headers.
     *
     */
    public void end_header()
    {
        message.addHeader(currentHeader);
        currentHeader = null;

        if (isDebug)
            trace.endHeader();
    }

    /**
     * Start process of the message body.
     *
     * @param attributes current Attributes
     */
    public void start_body(Attributes attributes)
    {
        if (currentBody != null || currentHeader != null)
            throw new MessageException("Unexpected body tag.");

        currentBody = new MessageBody();

        if (isDebug)
            trace.startMessage("", "", message.getBodyCount());
    }

    /**
     * End process of the message body.
     *
     */
    public void end_body()
    {
        message.addBody(currentBody);
        currentBody = null;

        if (isDebug)
            trace.endMessage();
    }


    //
    // ActionScript Types
    //

    /**
     * Start process of the Action Script type Array.
     *
     * @param attributes current Attributes
     */
    public void start_array(Attributes attributes)
    {
        int length = 10;
        String len = attributes.getValue("length");
        if (len != null)
        {
            try
            {
                len = len.trim();
                length = Integer.parseInt(len);
                if (length < 0)
                    throw new NumberFormatException();
            }
            catch (NumberFormatException ex)
            {
                throw new MessageException("Invalid array length: " + len);
            }
        }


        String ecma = attributes.getValue("ecma");
        boolean isECMA = "true".equalsIgnoreCase(ecma);

        Object array;
        boolean useListTemporarily = false;
        if (isECMA)
        {
            array = ClassUtil.createDefaultInstance(HashMap.class, null, true /*validate*/);
        }
        else
        {
            // Don't instantiate List/Array right away with the supplied size if it is more than
            // INITIAL_ARRAY_CAPACITY in case the supplied size has been tampered. This at least
            // requires the user to pass in the actual objects for the List/Array to grow beyond.
            if (context.legacyCollection || length > INITIAL_ARRAY_CAPACITY)
            {
                useListTemporarily = !context.legacyCollection;
                ClassUtil.validateCreation(ArrayList.class);
                int initialCapacity = length < INITIAL_ARRAY_CAPACITY? length : INITIAL_ARRAY_CAPACITY;
                array = new ArrayList(initialCapacity);
            }
            else
            {
                ClassUtil.validateCreation(Object[].class);
                array = new Object[length];
            }
        }

        array = setValue(array);

        ecmaArrayIndexStack.push(new int[]{0});
        strictArrayIndexStack.push(new int[]{0});

        objectTable.add(array);
        // Don't add the array to the object stack if the List is being used temporarily
        // for the length tampering detection. In that case, setValue method will add
        // an ObjectPropertyValueTuple to the object stack instead.
        if (!useListTemporarily)
            objectStack.push(array);
        proxyStack.push(null);

        if (isECMA)
        {
            if (isDebug)
                trace.startECMAArray(objectTable.size() - 1);
        }
        else
        {
            if (isDebug)
                trace.startAMFArray(objectTable.size() - 1);
        }
    }

    /**
     * End process of Action Script type Array.
     *
     */
    public void end_array()
    {
        try
        {
            Object obj = objectStack.pop();
            if (obj instanceof ObjectPropertyValueTuple)
            {
                // Means List was being used temporarily to guard against array length tampering.
                // Convert back to Object array and set it on the parent object using the proxy
                // and property saved in the tuple.
                ObjectPropertyValueTuple tuple = (ObjectPropertyValueTuple)obj;
                int objectId = objectTable.indexOf(tuple.value);
                Object newValue = ((ArrayList)tuple.value).toArray();
                objectTable.set(objectId, newValue);
                tuple.proxy.setValue(tuple.obj, tuple.property, newValue);
            }
            proxyStack.pop();
            ecmaArrayIndexStack.pop();
            strictArrayIndexStack.pop();
        }
        catch (EmptyStackException ex)
        {
            throw new MessageException("Unexpected end of array");
        }

        if (isDebug)
            trace.endAMFArray();
    }

    public void start_dictionary(Attributes attributes)
    {
        int length = 10;
        String len = attributes.getValue("length");
        if (len != null)
        {
            try
            {
                len = len.trim();
                length = Integer.parseInt(len);
                if (length < 0)
                    throw new NumberFormatException();
            }
            catch (NumberFormatException ex)
            {
                throw new MessageException("Invalid array length: " + len);
            }
        }

        Hashtable dictionary = (Hashtable)ClassUtil.createDefaultInstance(Hashtable.class, null, true /*validate*/);
        setValue(dictionary);

        objectTable.add(dictionary);
        objectStack.push(dictionary);
        proxyStack.push(null);

        if (isDebug)
            trace.startAMFDictionary(objectTable.size() - 1);
    }

    public void end_dictionary()
    {
        try
        {
            objectStack.pop();
            proxyStack.pop();
        }
        catch (EmptyStackException ex)
        {
            throw new MessageException("Unexpected end of dictionary");
        }

        if (isDebug)
            trace.endAMFDictionary();
    }

    // <bytearray>010F0A</bytearray>

    /**
     * Start process of the Action Script type ByteArray.
     *
     * @param attributes current Attributes
     */
    public void start_bytearray(Attributes attributes)
    {
        text.delete(0, text.length());
    }

    /**
     * End process of the Action Script type ByteArray.
     *
     */
    public void end_bytearray()
    {
        ClassUtil.validateCreation(byte[].class);

        String bs = text.toString().trim();

        Hex.Decoder decoder = new Hex.Decoder();
        decoder.decode(bs);
        byte[] value = decoder.drain();

        setValue(value);

        if (isDebug)
            trace.startByteArray(objectTable.size() - 1, bs.length());
    }

    /**
     * Start process of the Action Script type Date.
     *
     * @param attributes current Attributes
     */
    public void start_date(Attributes attributes)
    {
        text.delete(0, text.length());
    }

    /**
     * End process of the Action Script type Date.
     *
     */
    public void end_date()
    {
        ClassUtil.validateCreation(Date.class);

        String d = text.toString().trim();
        try
        {
            long l = Long.parseLong(d);
            Date date = new Date(l);
            setValue(date);

            objectTable.add(date); //Dates can be sent by reference

            if (isDebug)
                trace.write(date);
        }
        catch (NumberFormatException ex)
        {
            throw new MessageException("Invalid date: " + d);
        }
    }

    /**
     * Start process of the Action Script type Double.
     *
     * @param attributes current Attributes
     */
    public void start_double(Attributes attributes)
    {
        text.delete(0, text.length());
    }

    /**
     * End process of the Action Script type Double.
     *
     */
    public void end_double()
    {
        ClassUtil.validateCreation(Double.class);

        String ds = text.toString().trim();
        try
        {
            Double d = Double.valueOf(ds);
            setValue(d);

            if (isDebug)
                trace.write(d.doubleValue());
        }
        catch (NumberFormatException ex)
        {
            throw new MessageException("Invalid double: " + ds);
        }
    }

    /**
     * Start process of the Action Script type False.
     *
     * @param attributes current Attributes
     */
    public void start_false(Attributes attributes)
    {
        ClassUtil.validateCreation(Boolean.class);
        setValue(Boolean.FALSE);
        if (isDebug)
            trace.write(false);
    }

    /**
     * Start process of the Action Script type False.
     *
     */
    public void end_false()
    {
    }

    /**
     * Start process of Item.
     *
     * @param attributes current Attributes
     */
    public void start_item(Attributes attributes)
    {
        String name = attributes.getValue("name");
        if (name != null)
        {
            name = name.trim();
            if (name.length() <= 0)
                throw new MessageException("Array item names cannot be the empty string.");

            char c = name.charAt(0);
            if (!(Character.isLetterOrDigit(c) || c == '_'))
                throw new MessageException("Invalid item name: " + name +
                        ". Array item names must start with a letter, a digit or the underscore '_' character.");
        }
        else
        {
            throw new MessageException("Array item must have a name attribute.");
        }

        //Check that we're expecting an ECMA array
        Object o = objectStackPeek();
        if (!(o instanceof Map))
        {
            throw new MessageException("Unexpected array item name: " + name +
                    ". Please set the ecma attribute to 'true'.");
        }

        arrayPropertyStack.push(name);
    }

    /**
     * End process of Item.
     *
     */
    public void end_item()
    {
        arrayPropertyStack.pop();
    }

    /**
     * Start process of the Action Script type Int.
     *
     * @param attributes current Attributes
     */
    public void start_int(Attributes attributes)
    {
        text.delete(0, text.length());
    }

    /**
     * End process of the Action Script type Int.
     *
     */
    public void end_int()
    {
        ClassUtil.validateCreation(Integer.class);

        String is = text.toString().trim();
        try
        {
            Integer i = Integer.valueOf(is);
            setValue(i);

            if (isDebug)
                trace.write(i.intValue());
        }
        catch (NumberFormatException ex)
        {
            throw new MessageException("Invalid int: " + is);
        }
    }

    /**
     * Start process of the Action Script type NULL.
     *
     * @param attributes current Attributes
     */
    public void start_null(Attributes attributes)
    {
        setValue(null);

        if (isDebug)
            trace.writeNull();
    }

    /**
     * Start process of the Action Script type NULL.
     *
     */
    public void end_null()
    {
    }

    // <object type="com.my.Class">

    /**
     * Start process of type Object.
     *
     * @param attributes current Attributes
     */
    public void start_object(Attributes attributes)
    {
        PropertyProxy proxy = null;

        String type = attributes.getValue("type");
        if (type != null)
        {
            type = type.trim();
        }

        Object object;

        if (type != null && type.length() > 0)
        {
            // Check for any registered class aliases
            String aliasedClass = ClassAliasRegistry.getRegistry().getClassName(type);
            if (aliasedClass != null)
                type = aliasedClass;

            if (type == null || type.length() == 0)
            {
                object = ClassUtil.createDefaultInstance(ASObject.class, null, true /*validate*/);
            }
            else if (type.startsWith(">")) // Handle [RemoteClass] (no server alias)
            {
                object = ClassUtil.createDefaultInstance(ASObject.class, null, true /*validate*/);
                ((ASObject)object).setType(type);
            }
            else if (context.instantiateTypes || type.startsWith("flex."))
            {
                object = getInstantiatedObject(type, proxy);
            }
            else
            {
                // Just return type info with an ASObject...
                object = ClassUtil.createDefaultInstance(ASObject.class, null, true /*validate*/);
                ((ASObject)object).setType(type);
            }
        }
        else
        {
            // TODO: QUESTION: Pete, Investigate why setValue for ASObject is delayed to endObject
            ClassUtil.validateCreation(ASObject.class);
            object = new ASObject(type);
        }

        if (proxy == null)
            proxy = PropertyProxyRegistry.getProxyAndRegister(object);

        objectStack.push(object);
        proxyStack.push(proxy);
        objectTable.add(object);

        if (isDebug)
            trace.startAMFObject(type, objectTable.size() - 1);
    }


    // </object>
    /**
     * End process of type Object.
     *
     */
    public void end_object()
    {
        if (!traitsStack.empty())
            traitsStack.pop();

        if (!objectStack.empty())
        {
            Object obj = objectStack.pop();
            PropertyProxy proxy = (PropertyProxy) proxyStack.pop();

            Object newObj = proxy == null ? obj : proxy.instanceComplete(obj);
            if (newObj != obj)
            {
                int i;
                // Find the index in the list of the old objct and replace it with
                // the new one.
                for (i = 0; i < objectTable.size(); i++)
                    if (objectTable.get(i) == obj)
                        break;

                if (i != objectTable.size())
                    objectTable.set(i, newObj);

                obj = newObj;
            }
            setValue(obj);
        }
        else
        {
            throw new MessageException("Unexpected end of object.");
        }

        if (isDebug)
            trace.endAMFObject();
    }

    /**
     * Start process of reference.
     *
     * @param attributes current Attributes
     */
    public void start_ref(Attributes attributes)
    {
        String id = attributes.getValue("id");
        if (id != null)
        {
            try
            {
                int i = Integer.parseInt(id);
                Object o = objectTable.get(i);
                setValue(o);

                if (isDebug)
                    trace.writeRef(i);
            }
            catch (NumberFormatException ex)
            {
                throw new MessageException("Invalid object reference: " + id);
            }
            catch (IndexOutOfBoundsException ex)
            {
                throw new MessageException("Unknown object reference: " + id);
            }
        }
        else
        {
            throw new MessageException("Unknown object reference: " + id);
        }

    }

    /**
     * End process of reference.
     *
     */
    public void end_ref()
    {
    }

    /**
     * Start process of the Action Script type String.
     *
     * @param attributes current Attributes
     */
    public void start_string(Attributes attributes)
    {
        String id = attributes.getValue("id");
        if (id != null)
        {
            isStringReference = true;

            try
            {
                int i = Integer.parseInt(id);
                String s = (String)stringTable.get(i);
                if (isTraitProperty)
                {
                    TraitsContext traitsContext = (TraitsContext)traitsStack.peek();
                    traitsContext.add(s);
                }
                else
                {
                    ClassUtil.validateCreation(String.class);
                    setValue(s);
                }
            }
            catch (NumberFormatException ex)
            {
                throw new MessageException("Invalid string reference: " + id);
            }
            catch (IndexOutOfBoundsException ex)
            {
                throw new MessageException("Unknown string reference: " + id);
            }
        }
        else
        {
            text.delete(0, text.length());
            isStringReference = false;
        }
    }

    /**
     * End process of the Action Script type String.
     *
     */
    public void end_string()
    {
        if (!isStringReference)
        {
            String s = text.toString();

            // Special case the empty string as it isn't counted as in
            // the string reference table
            if (s.length() > 0)
            {
                // Traits won't contain CDATA
                if (!isTraitProperty)
                    s = unescapeCloseCDATA(s);

                stringTable.add(s);
            }

            if (isTraitProperty)
            {
                TraitsContext traitsContext = (TraitsContext)traitsStack.peek();
                traitsContext.add(s);
            }
            else
            {
                ClassUtil.validateCreation(String.class);
                setValue(s);

                if (isDebug)
                    trace.writeString(s);
            }
        }
    }

    /**
     * Start process of Traits.
     *
     * @param attributes current Attributes
     */
    public void start_traits(Attributes attributes)
    {
        if (!objectStack.empty())
        {
            List traitsList = new ArrayList();
            TraitsContext traitsContext = new TraitsContext(traitsList);
            traitsStack.push(traitsContext);

            String id = attributes.getValue("id");
            if (id != null)
            {
                try
                {
                    int i = Integer.parseInt(id);
                    List l = (List)traitsTable.get(i);

                    Iterator it = l.iterator();
                    while (it.hasNext())
                    {
                        String prop = (String)it.next();
                        traitsList.add(prop);
                    }
                }
                catch (NumberFormatException ex)
                {
                    throw new MessageException("Invalid traits reference: " + id);
                }
                catch (IndexOutOfBoundsException ex)
                {
                    throw new MessageException("Unknown traits reference: " + id);
                }
            }
            else
            {
                boolean externalizable = false;

                String ext = attributes.getValue("externalizable");
                if (ext != null)
                {
                    externalizable = "true".equals(ext.trim());
                }

                Object obj = objectStackPeek();
                if (externalizable && !(obj instanceof Externalizable))
                {
                    //Class '{className}' must implement java.io.Externalizable to receive client IExternalizable instances.
                    SerializationException ex = new SerializationException();
                    ex.setMessage(10305, new Object[] {obj.getClass().getName()});
                    throw ex;
                }

                traitsTable.add(traitsList);
            }

            isTraitProperty = true;
        }
        else
        {
            throw new MessageException("Unexpected traits");
        }
    }

    /**
     * End process of Traits.
     *
     */
    public void end_traits()
    {
        isTraitProperty = false;
    }

    /**
     * Start process of the Action Script type True.
     *
     * @param attributes current Attributes
     */
    public void start_true(Attributes attributes)
    {
        ClassUtil.validateCreation(Boolean.class);

        setValue(Boolean.TRUE);

        if (isDebug)
            trace.write(true);
    }

    /**
     * Start process of the Action Script type True.
     *
     */
    public void end_true()
    {
    }

    /**
     * Start process of the Action Script type undefined.
     *
     * @param attributes current Attributes
     */
    public void start_undefined(Attributes attributes)
    {
        setValue(null);

        if (isDebug)
            trace.writeUndefined();
    }

    /**
     * End process of the Action Script type undefined.
     *
     */
    public void end_undefined()
    {
    }

    /**
     * Start process of XML.
     *
     * @param attributes current Attributes
     */
    public void start_xml(Attributes attributes)
    {
        text.delete(0, text.length());
    }

    /**
     * End process of XML.
     *
     */
    public void end_xml()
    {
        String xml = text.toString();
        xml = unescapeCloseCDATA(xml);

        // Validation performed in XMLUtil#stringToDocument.
        Object value = XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces),
                context.allowXmlDoctypeDeclaration, context.allowXmlExternalEntityExpansion);
        setValue(value);
    }

    private String unescapeCloseCDATA(String s)
    {
        //Only check if string could possibly have an encoded closing for a CDATA "]]>"
        if (s.length() > 5 && s.indexOf("]]&gt;") != -1)
        {
            s = s.replaceAll("]]&gt;", "]]>");
        }

        return s;
    }

    private Object setValue(Object value)
    {
        if (objectStack.empty())
        {
            if (currentHeader != null)
                currentHeader.setData(value);
            else if (currentBody  != null)
                currentBody.setData(value);
            else
                throw new MessageException("Unexpected value: " + value);

            return value;
        }


        // ActionScript Data
        Object obj = objectStackPeek();

        // <object type="..."> <traits externalizable="true">
        if (obj instanceof Externalizable)
        {
            if (value != null && value.getClass().isArray() && Byte.TYPE.equals(value.getClass().getComponentType()))
            {
                Externalizable extern = (Externalizable)obj;
                Amf3Input objIn = new Amf3Input(context);
                byte[] ba = (byte[])value;
                ByteArrayInputStream baIn = new ByteArrayInputStream(ba);
                try
                {
                    //objIn.setDebugTrace(trace);
                    objIn.setInputStream(baIn);
                    extern.readExternal(objIn);
                }
                catch (ClassNotFoundException ex)
                {
                    throw new MessageException("Error while reading Externalizable class " + extern.getClass().getName(), ex);
                }
                catch (IOException ex)
                {
                    throw new MessageException("Error while reading Externalizable class " + extern.getClass().getName(), ex);
                }
                finally
                {
                    try
                    {
                        objIn.close();
                    }
                    catch (IOException ex)
                    {
                    }
                }
            }
            else
            {
                throw new MessageException("Error while reading Externalizable class. Value must be a byte array.");
            }
        }

        // <object>
        else if (obj instanceof ASObject)
        {
            String prop;

            TraitsContext traitsContext = (TraitsContext)traitsStack.peek();
            try
            {
                prop = traitsContext.next();
            }
            catch (IndexOutOfBoundsException ex)
            {
                throw new MessageException("Object has no trait info for value: " + value);
            }

            ASObject aso = (ASObject)obj;
            ClassUtil.validateAssignment(aso, prop, value);
            aso.put(prop, value);

            if (isDebug)
                trace.namedElement(prop);
        }

        // <array ecma="false"> in ArrayList form
        else if (obj instanceof ArrayList && !(obj instanceof ArrayCollection))
        {
            ArrayList list = (ArrayList)obj;
            ClassUtil.validateAssignment(list, list.size(), value);
            list.add(value);

            if (isDebug)
                trace.arrayElement(list.size() - 1);
        }

        // <array ecma="false"> in Object[] form
        else if (obj.getClass().isArray())
        {
            if (!strictArrayIndexStack.empty())
            {
                int[] indexObj = (int[])strictArrayIndexStack.peek();
                int index = indexObj[0];

                if (Array.getLength(obj) > index)
                {
                    ClassUtil.validateAssignment(obj, index, value);
                    Array.set(obj, index, value);
                }
                else
                {
                    throw new MessageException("Index out of bounds at: " + index + " cannot set array value: " + value + "");
                }
                indexObj[0]++;
            }
        }

        else if (obj instanceof Map)
        {
            if (obj instanceof Dictionary) // <dictionary>
            {
                Dictionary dict = (Dictionary)obj;

                if (!dictionaryStack.empty())
                {
                    Object key = dictionaryStack.pop();
                    if (isDebug) trace.addDictionaryEquals();
                    ClassUtil.validateAssignment(dict, key.toString(), value);
                    dict.put(key, value);
                }
                else
                {
                    if (isDebug) trace.startDictionaryElement();
                    dictionaryStack.push(value);
                }

                return value;
            }

            Map map = (Map)obj; // <array ecma="true">

            // <item name="prop">
            if (!arrayPropertyStack.empty())
            {
                String prop = (String)arrayPropertyStack.peek();
                ClassUtil.validateAssignment(map, prop, value);
                map.put(prop, value);

                if (isDebug)
                    trace.namedElement(prop);

                return value;
            }

            // Mixed content, auto-generate string for ECMA Array index
            if (!ecmaArrayIndexStack.empty())
            {
                int[] index = (int[])ecmaArrayIndexStack.peek();

                String prop = String.valueOf(index[0]);
                index[0]++;

                ClassUtil.validateAssignment(map, prop, value);
                map.put(prop, value);

                if (isDebug)
                    trace.namedElement(prop);
            }
        }

        // <object type="...">
        else
        {
            value = setObjectValue(obj, value);
        }

        return value;
    }

    private Object setObjectValue(Object obj, Object value)
    {
        String prop;

        TraitsContext traitsContext = (TraitsContext)traitsStack.peek();
        try
        {
            prop = traitsContext.next();
        }
        catch (IndexOutOfBoundsException ex)
        {
            throw new MessageException("Object has no trait info for value: " + value, ex);
        }

        try
        {
            // Then check if there's a more suitable proxy now that we have an instance
            PropertyProxy proxy = (PropertyProxy) proxyStack.peek();
            if (proxy == null)
                proxy = beanproxy;
            proxy.setValue(obj, prop, value);

            // Reset value in case it was changed by the proxy except empty lists.
            // Proxy converts empty lists to empty arrays in remoting messages.
            // Emply arrays are useless as containers and cause errors.
            if (!(value instanceof ArrayList && ((ArrayList)value).size() == 0))
            {
                Object newValue = proxy.getValue(obj, prop);
                if (value != newValue)
                    value = newValue;
            }

            if (value instanceof ArrayList && !(value instanceof ArrayCollection)
                    && !context.legacyCollection)
            {
                // Means List is being used temporarily, see start_array method for explanation.
                objectStack.push(new ObjectPropertyValueTuple(proxy, obj, prop, value));
            }
        }
        catch (Exception ex)
        {
            throw new MessageException("Failed to set property '" + prop + "' with value: " + value, ex);
        }

        if (isDebug)
            trace.namedElement(prop);

        return value;
    }

    /**
     * Utility method to peek the object in the object stack which can be an Object
     * or an <tt>ObjectPropertyValueTuple</tt>.
     *
     * @return The Object at the top of the object stack.
     */
    private Object objectStackPeek()
    {
        Object obj = objectStack.peek();
        return (obj instanceof ObjectPropertyValueTuple)? ((ObjectPropertyValueTuple)obj).value : obj;
    }

    private Object getInstantiatedObject(String className, PropertyProxy proxy)
    {
        Class<?> desiredClass = null;
        try
        {
            desiredClass = AbstractProxy.getClassFromClassName(className);
        }
        catch (MessageException me)
        {
            // Type not found but don't mind using ASObject for the missing type.
            if (me.getCode().startsWith(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE)
                    && context.createASObjectForMissingType)
            {
                ASObject object = (ASObject)ClassUtil.createDefaultInstance(ASObject.class, null, true /*validate*/);
                object.setType(className);
                return object;
            }
            throw me; // Rethrow.
        }

        // Type exists.
        proxy = PropertyProxyRegistry.getRegistry().getProxyAndRegister(desiredClass);
        return proxy == null? ClassUtil.createDefaultInstance(desiredClass, null, true /*validate*/) :
                    proxy.createInstance(className); // Validation is performed in the proxy.
    }

    /**
     * Helper class used in the case where the supplied array length is more than the
     * INITIAL_ARRAY_CAPACITY. In that case, the List/Object[] on the server is not
     * initialized with that length in case the supplied length has been tampered.
     * Instead, a temporary List of length INITIAL_ARRAY_CAPACITY is constructed and List
     * grows as array members are supplied from the client. This way the user is required to
     * pass in the actual array members for the List to grow. This helper class is needed to
     * convert the temporary List into Object[] if needed.
     */
    private static class ObjectPropertyValueTuple
    {
        private PropertyProxy proxy;
        private Object obj;
        private String property;
        private Object value;

        private ObjectPropertyValueTuple(PropertyProxy proxy, Object obj, String property, Object value)
        {
            this.proxy = proxy;
            this.obj = obj;
            this.property = property;
            this.value = value;
        }
    }

    private class TraitsContext
    {
        private List traits;
        private int counter;

        private TraitsContext(List traits)
        {
            this.traits = traits;
        }

        private void add(String trait)
        {
            trait = trait.trim();

            if (trait.length() <= 0)
                throw new MessageException("Traits cannot be the empty string.");

            char c = trait.charAt(0);
            if (!(Character.isLetterOrDigit(c) || c == '_'))
                throw new MessageException("Invalid trait name: " + trait +
                        ". Object property names must start with a letter, a digit or the underscore '_' character.");


            traits.add(trait);
        }

        private String next()
        {
            String trait = (String)traits.get(counter);
            counter++;
            return trait;
        }
    }
}
