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

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import flex.messaging.MessageException;
import flex.messaging.io.AbstractProxy;
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.util.ClassUtil;
import flex.messaging.util.XMLUtil;

/**
 * A deserializer of AMF protocol data.
 *
 * @see ActionMessageOutput
 *
 */
public abstract class AbstractAmfInput extends AmfIO implements ActionMessageInput
{
    /**
     * This is the initial capacity that will be used for AMF arrays, vectors, etc.
     * that have length greater than 1024.
     */
    public static final int INITIAL_COLLECTION_CAPACITY = 1024;

    /**
     * This is the default max String length (25MB).
     */
    public static final int DEFAULT_MAX_STRING_BYTES = 26214400;
    public static final String STRING_MAX_STRING_BYTES = "max-string-bytes";

    protected BeanProxy beanProxy = new BeanProxy();
    protected DataInputStream in = null;
    protected int maxStringBytes = DEFAULT_MAX_STRING_BYTES;

    /**
     * Construct a deserializer without connecting it to an input stream.
     * @param context serialization parameters.
     */
    public AbstractAmfInput(SerializationContext context)
    {
        super(context);

        readMaxStringBytes();
    }

    /**
     * Internal use
     *
     */
    public void setInputStream(InputStream in)
    {
        this.in = new DataInputStream(in);
    }

    protected Object stringToDocument(String xml)
    {
        // FIXME: Temporary workaround for bug 194815
        if (xml != null && xml.indexOf('<') == -1)
            return xml;

        // Validation performed in XMLUtil#stringToDocument.
        return XMLUtil.stringToDocument(xml, !(context.legacyXMLNamespaces),
                context.allowXmlDoctypeDeclaration, context.allowXmlExternalEntityExpansion);
    }

    /**
     * A utility method that is used by subclasses to perform max-string-bytes
     * checks. By default, max-string-bytes is limited to 25MB for security
     * but this can be changed via JVM option called max-string-bytes.
     *
     * @param utflen The UTF string length to check.
     * @throws <tt>SerializationException</tt> if max-string-bytes has been exceeded.
     */
    protected void checkUTFLength(int utflen)
    {
        if (utflen > maxStringBytes)
        {
            // Error deserializing the string with length ''{0}'', it exceeds the max-string-bytes limit of ''{1}''.
            SerializationException ex = new SerializationException();
            ex.setMessage(10314, new Object[] {utflen, maxStringBytes});
            throw ex;
        }
    }

    /**
     * Internal use. Common logic for creating an object for AMF0 and AMF3. Used from
     * Amf0Input.readObjectValue() and Amf3Input.readScriptObject().
     * This method is responsible for resolving class aliases, creating and
     * registering a property proxy and instantiating an instance of the desired class.
     * The params array is used as a holder for parameter values that are updated or
     * created in this method, but are needed by its callers.
     * @param params array of values that may be updated by this method.
     *               [0] - String className - the name or alias of the class to create
     *               [1] - PropertyProxy proxy
     * @return an instance of the appropriate object for deserialization
     *
     */
    protected Object createObjectInstance(Object[] params)
    {
        String className = (String)params[0];

        // Check for any registered class aliases
        String aliasedClass = ClassAliasRegistry.getRegistry().getClassName(className);
        if (aliasedClass != null)
        {
            className = aliasedClass;
            params[0] = className; //update the params array so that callers get this change
        }

        Object object = null;
        PropertyProxy proxy = null;

        if (className != null && className.startsWith(">")) // Handle [RemoteClass] (no server alias)
        {
            object = createDefaultASObject(className);
        }
        else if (className != null && className.length() > 0 && (context.instantiateTypes || className.startsWith("flex.")))
        {
            // otherwise attempt to create an instance if we have a className
            Class<?> desiredClass = null;
            try
            {
                desiredClass = AbstractProxy.getClassFromClassName(className);
            }
            catch (MessageException me)
            {
                // Type not found and don't want to use ASObject for the missing type.
                if (!(me.getCode().startsWith(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE)
                        && context.createASObjectForMissingType))
                {
                    throw me; // Rethrow.
                }
                // if we didn't rethrow the exception, the default ASObject will be created further down.
            }

            // Type exists. Create either default instance of desiredClass or an instance from a registered proxy.
            if (desiredClass != null)
            {
                proxy = PropertyProxyRegistry.getRegistry().getProxyAndRegister(desiredClass);
                if (proxy == null)
                {
                    object = ClassUtil.createDefaultInstance(desiredClass, null, true /*validate*/);
                }
                else
                {
                    object = proxy.createInstance(className); // Validation is performed in the proxy.
                }
            }
        }

        // if we still don't have an object, create an ASObject with what we have for className (can be null)
        if (object == null)
            object = createDefaultASObject(className);

        // if proxy wasn't created, create one based on the new instance.
        if (proxy == null)
            proxy = PropertyProxyRegistry.getProxyAndRegister(object);

        params[1] = proxy; //update the params array so that callers get the proxy

        return object;
    }

    /**
     * Internal use. Convenience method for creating an ASObject and assigning it a type
     * @param type named type for the ASObject or null
     * @return a new instance of ASObject
     *
     */
    protected ASObject createDefaultASObject(String type)
    {
        ASObject object = (ASObject) ClassUtil.createDefaultInstance(ASObject.class, null, true /*validate*/);
        if (type != null && type.length() > 0)
            object.setType(type);
        return object;
    }

    /**
     *
     */
    protected void readMaxStringBytes()
    {
        // See if a JVM option is specified for max-string-bytes.
        String maxStringBytes = null;
        try
        {
            maxStringBytes = System.getProperty(STRING_MAX_STRING_BYTES);
        }
        catch (SecurityException se)
        {
            // Ignore and use the default.
        }

        if (maxStringBytes == null)
            return;

        try
        {
            this.maxStringBytes = Integer.parseInt(maxStringBytes);
        }
        catch (NumberFormatException ignore)
        {
            // Ignore and use the default.
        }
    }

    //
    // java.io.ObjectInput IMPLEMENTATIONS
    //

    /** {@inheritDoc} */
    public int available() throws IOException
    {
        return in.available();
    }

    /** {@inheritDoc} */
    public void close() throws IOException
    {
        in.close();
    }

    /** {@inheritDoc} */
    public int read() throws IOException
    {
        return in.read();
    }

    /** {@inheritDoc} */
    public int read(byte[] bytes) throws IOException
    {
        return in.read(bytes);
    }

    /** {@inheritDoc} */
    public int read(byte[] bytes, int offset, int length) throws IOException
    {
        return in.read(bytes, offset, length);
    }

    /** {@inheritDoc} */
    public long skip(long n) throws IOException
    {
        return in.skip(n);
    }

    /** {@inheritDoc} */
    public int skipBytes(int n) throws IOException
    {
        return in.skipBytes(n);
    }

    //
    // java.io.DataInput IMPLEMENTATIONS
    //

    /** {@inheritDoc} */
    public boolean readBoolean() throws IOException
    {
        return in.readBoolean();
    }

    /** {@inheritDoc} */
    public byte readByte() throws IOException
    {
        return in.readByte();
    }

    /** {@inheritDoc} */
    public char readChar() throws IOException
    {
        return in.readChar();
    }

    /** {@inheritDoc} */
    public double readDouble() throws IOException
    {
        return in.readDouble();
    }

    /** {@inheritDoc} */
    public float readFloat() throws IOException
    {
        return in.readFloat();
    }

    /** {@inheritDoc} */
    public void readFully(byte[] bytes) throws IOException
    {
        in.readFully(bytes);
    }

    /** {@inheritDoc} */
    public void readFully(byte[] bytes, int offset, int length) throws IOException
    {
        in.readFully(bytes, offset, length);
    }

    /** {@inheritDoc} */
    public int readInt() throws IOException
    {
        return in.readInt();
    }

    /**
     *  Reads the next line of text from the input stream.
     * @deprecated
     */
    public String readLine() throws IOException
    {
        return in.readLine();
    }

    /** {@inheritDoc} */
    public long readLong() throws IOException
    {
        return in.readLong();
    }

    /** {@inheritDoc} */
    public short readShort() throws IOException
    {
        return in.readShort();
    }

    /** {@inheritDoc} */
    public int readUnsignedByte() throws IOException
    {
        return in.readUnsignedByte();
    }

    /** {@inheritDoc} */
    public int readUnsignedShort() throws IOException
    {
        return in.readUnsignedShort();
    }

    /** {@inheritDoc} */
    public String readUTF() throws IOException
    {
        return in.readUTF();
    }
}