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