/*
 * 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();
    }
}