/*
 * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
/*
 * Licensed Materials - Property of IBM
 * RMI-IIOP v1.0
 * Copyright IBM Corp. 1998 1999  All Rights Reserved
 *
 */

package com.sun.corba.se.impl.io;

import java.io.IOException;
import java.io.StreamCorruptedException;
import java.io.NotActiveException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;

import org.omg.CORBA.portable.ValueInputStream;

import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.orb.ORBVersion;
import com.sun.corba.se.spi.orb.ORBVersionFactory;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.logging.UtilSystemException;
import com.sun.corba.se.impl.logging.OMGSystemException;

public abstract class InputStreamHook extends ObjectInputStream
{
    // These should be visible in all the nested classes
    static final OMGSystemException omgWrapper =
        OMGSystemException.get( CORBALogDomains.RPC_ENCODING ) ;

    static final UtilSystemException utilWrapper =
        UtilSystemException.get( CORBALogDomains.RPC_ENCODING ) ;

    private class HookGetFields extends ObjectInputStream.GetField {
        private Map fields = null;

        HookGetFields(Map fields){
            this.fields = fields;
        }

        /**
         * Get the ObjectStreamClass that describes the fields in the stream.
         *
         * REVISIT!  This doesn't work since we have our own ObjectStreamClass.
         */
        public java.io.ObjectStreamClass getObjectStreamClass() {
            return null;
        }

        /**
         * Return true if the named field is defaulted and has no value
         * in this stream.
         */
        public boolean defaulted(String name)
            throws IOException, IllegalArgumentException  {
            return (!fields.containsKey(name));
        }

        /**
         * Get the value of the named boolean field from the persistent field.
         */
        public boolean get(String name, boolean defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Boolean)fields.get(name)).booleanValue();
        }

        /**
         * Get the value of the named char field from the persistent fields.
         */
        public char get(String name, char defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Character)fields.get(name)).charValue();

        }

        /**
         * Get the value of the named byte field from the persistent fields.
         */
        public byte get(String name, byte defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Byte)fields.get(name)).byteValue();

        }

        /**
         * Get the value of the named short field from the persistent fields.
         */
        public short get(String name, short defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Short)fields.get(name)).shortValue();

        }

        /**
         * Get the value of the named int field from the persistent fields.
         */
        public int get(String name, int defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Integer)fields.get(name)).intValue();

        }

        /**
         * Get the value of the named long field from the persistent fields.
         */
        public long get(String name, long defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Long)fields.get(name)).longValue();

        }

        /**
         * Get the value of the named float field from the persistent fields.
         */
        public float get(String name, float defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return ((Float)fields.get(name)).floatValue();

        }

        /**
         * Get the value of the named double field from the persistent field.
         */
        public double get(String name, double defvalue)
            throws IOException, IllegalArgumentException  {
            if (defaulted(name))
                return defvalue;
            else return ((Double)fields.get(name)).doubleValue();

        }

        /**
         * Get the value of the named Object field from the persistent field.
         */
        public Object get(String name, Object defvalue)
            throws IOException, IllegalArgumentException {
            if (defaulted(name))
                return defvalue;
            else return fields.get(name);

        }

        public String toString(){
            return fields.toString();
        }
    }

    public InputStreamHook()
        throws IOException {
        super();
    }

    public void defaultReadObject()
        throws IOException, ClassNotFoundException, NotActiveException
    {
        readObjectState.beginDefaultReadObject(this);

        defaultReadObjectDelegate();

        readObjectState.endDefaultReadObject(this);
    }

    public abstract void defaultReadObjectDelegate();

    abstract void readFields(java.util.Map fieldToValueMap)
        throws java.io.InvalidClassException, java.io.StreamCorruptedException,
               ClassNotFoundException, java.io.IOException;


    // See java.io.ObjectInputStream.GetField
    // Remember that this is equivalent to defaultReadObject
    // in RMI-IIOP
    public ObjectInputStream.GetField readFields()
        throws IOException, ClassNotFoundException, NotActiveException {

        HashMap fieldValueMap = new HashMap();

        // We were treating readFields same as defaultReadObject. It is
        // incorrect if the state is readOptionalData. If this line
        // is uncommented, it will throw a stream corrupted exception.
        // _REVISIT_: The ideal fix would be to add a new state. In
        // writeObject user may do one of the following
        // 1. Call defaultWriteObject()
        // 2. Put out optional fields
        // 3. Call writeFields
        // We have the state defined for (1) and (2) but not for (3), so
        // we should ideally introduce a new state for 3 and have the
        // beginDefaultReadObject do nothing.
        //readObjectState.beginDefaultReadObject(this);

        readFields(fieldValueMap);

        readObjectState.endDefaultReadObject(this);

        return new HookGetFields(fieldValueMap);
    }

    // The following is a State pattern implementation of what
    // should be done when the sender's Serializable has a
    // writeObject method.  This was especially necessary for
    // RMI-IIOP stream format version 2.  Please see the
    // state diagrams in the docs directory of the workspace.
    //
    // On the reader's side, the main factors are whether or not
    // we have a readObject method and whether or not the
    // sender wrote default data

    protected void setState(ReadObjectState newState) {
        readObjectState = newState;
    }

    protected abstract byte getStreamFormatVersion();
    abstract org.omg.CORBA_2_3.portable.InputStream getOrbStream();

    // Description of possible actions
    protected static class ReadObjectState {
        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject) throws IOException {}

        public void endUnmarshalCustomValue(InputStreamHook stream) throws IOException {}
        public void beginDefaultReadObject(InputStreamHook stream) throws IOException {}
        public void endDefaultReadObject(InputStreamHook stream) throws IOException {}
        public void readData(InputStreamHook stream) throws IOException {}
    }

    protected ReadObjectState readObjectState = DEFAULT_STATE;

    protected static final ReadObjectState DEFAULT_STATE = new DefaultState();
    protected static final ReadObjectState IN_READ_OBJECT_OPT_DATA
        = new InReadObjectOptionalDataState();
    protected static final ReadObjectState IN_READ_OBJECT_NO_MORE_OPT_DATA
        = new InReadObjectNoMoreOptionalDataState();
    protected static final ReadObjectState IN_READ_OBJECT_DEFAULTS_SENT
        = new InReadObjectDefaultsSentState();
    protected static final ReadObjectState NO_READ_OBJECT_DEFAULTS_SENT
        = new NoReadObjectDefaultsSentState();

    protected static final ReadObjectState IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED
        = new InReadObjectRemoteDidNotUseWriteObjectState();
    protected static final ReadObjectState IN_READ_OBJECT_PAST_DEFAULTS_REMOTE_NOT_CUSTOM
        = new InReadObjectPastDefaultsRemoteDidNotUseWOState();

    protected static class DefaultState extends ReadObjectState {

        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject)
            throws IOException {

            if (hasReadObject) {
                if (calledDefaultWriteObject)
                    stream.setState(IN_READ_OBJECT_DEFAULTS_SENT);
                else {
                    try {
                        if (stream.getStreamFormatVersion() == 2)
                            ((ValueInputStream)stream.getOrbStream()).start_value();
                    } catch( Exception e ) {
                        // This will happen for Big Integer which uses
                        // writeFields in it's writeObject. We should be past
                        // start_value by now.
                        // NOTE: If we don't log any exception here we should
                        // be fine. If there is an error, it will be caught
                        // while reading the optional data.

                    }
                    stream.setState(IN_READ_OBJECT_OPT_DATA);
                }
            } else {
                if (calledDefaultWriteObject)
                    stream.setState(NO_READ_OBJECT_DEFAULTS_SENT);
                else
                    // XXX I18N and logging needed.
                    throw new StreamCorruptedException("No default data sent");
            }
        }
    }

    // REVISIT.  If a readObject exits here without reading
    // default data, we won't skip it.  This could be done automatically
    // as in line 1492 in IIOPInputStream.
    protected static class InReadObjectRemoteDidNotUseWriteObjectState extends ReadObjectState {

        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject)
        {
            throw utilWrapper.badBeginUnmarshalCustomValue() ;
        }

        public void endDefaultReadObject(InputStreamHook stream) {
            stream.setState(IN_READ_OBJECT_PAST_DEFAULTS_REMOTE_NOT_CUSTOM);
        }

        public void readData(InputStreamHook stream) {
            stream.throwOptionalDataIncompatibleException();
        }
    }

    protected static class InReadObjectPastDefaultsRemoteDidNotUseWOState extends ReadObjectState {

        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject)
        {
            throw utilWrapper.badBeginUnmarshalCustomValue() ;
        }

        public void beginDefaultReadObject(InputStreamHook stream) throws IOException
        {
            // XXX I18N and logging needed.
            throw new StreamCorruptedException("Default data already read");
        }


        public void readData(InputStreamHook stream) {
            stream.throwOptionalDataIncompatibleException();
        }
    }

    protected void throwOptionalDataIncompatibleException()
    {
        throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
    }


    protected static class InReadObjectDefaultsSentState extends ReadObjectState {

        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject) {
            // This should never happen.
            throw utilWrapper.badBeginUnmarshalCustomValue() ;
        }

        public void endUnmarshalCustomValue(InputStreamHook stream) {

            // In stream format version 2, we can skip over
            // the optional data this way.  In stream format version 1,
            // we will probably wind up with an error if we're
            // unmarshaling a superclass.
            if (stream.getStreamFormatVersion() == 2) {
                ((ValueInputStream)stream.getOrbStream()).start_value();
                ((ValueInputStream)stream.getOrbStream()).end_value();
            }

            stream.setState(DEFAULT_STATE);
        }

        public void endDefaultReadObject(InputStreamHook stream) throws IOException {

            // Read the fake valuetype header in stream format version 2
            if (stream.getStreamFormatVersion() == 2)
                ((ValueInputStream)stream.getOrbStream()).start_value();

            stream.setState(IN_READ_OBJECT_OPT_DATA);
        }

        public void readData(InputStreamHook stream) throws IOException {
            org.omg.CORBA.ORB orb = stream.getOrbStream().orb();
            if ((orb == null) ||
                    !(orb instanceof com.sun.corba.se.spi.orb.ORB)) {
                throw new StreamCorruptedException(
                                     "Default data must be read first");
            }
            ORBVersion clientOrbVersion =
                ((com.sun.corba.se.spi.orb.ORB)orb).getORBVersion();

            // Fix Date interop bug. For older versions of the ORB don't do
            // anything for readData(). Before this used to throw
            // StreamCorruptedException for older versions of the ORB where
            // calledDefaultWriteObject always returns true.
            if ((ORBVersionFactory.getPEORB().compareTo(clientOrbVersion) <= 0) ||
                    (clientOrbVersion.equals(ORBVersionFactory.getFOREIGN()))) {
                // XXX I18N and logging needed.
                throw new StreamCorruptedException("Default data must be read first");
            }
        }
    }

    protected static class InReadObjectOptionalDataState extends ReadObjectState {

        public void beginUnmarshalCustomValue(InputStreamHook stream,
                                              boolean calledDefaultWriteObject,
                                              boolean hasReadObject)
        {
            // This should never happen.
            throw utilWrapper.badBeginUnmarshalCustomValue() ;
        }

        public void endUnmarshalCustomValue(InputStreamHook stream) throws IOException
        {
            if (stream.getStreamFormatVersion() == 2) {
                ((ValueInputStream)stream.getOrbStream()).end_value();
            }
            stream.setState(DEFAULT_STATE);
        }

        public void beginDefaultReadObject(InputStreamHook stream) throws IOException
        {
            // XXX I18N and logging needed.
            throw new StreamCorruptedException("Default data not sent or already read/passed");
        }


    }

    protected static class InReadObjectNoMoreOptionalDataState
        extends InReadObjectOptionalDataState {

        public void readData(InputStreamHook stream) throws IOException {
            stream.throwOptionalDataIncompatibleException();
        }
    }

    protected static class NoReadObjectDefaultsSentState extends ReadObjectState {
        public void endUnmarshalCustomValue(InputStreamHook stream) throws IOException {
            // Code should read default fields before calling this

            if (stream.getStreamFormatVersion() == 2) {
                ((ValueInputStream)stream.getOrbStream()).start_value();
                ((ValueInputStream)stream.getOrbStream()).end_value();
            }

            stream.setState(DEFAULT_STATE);
        }
    }
}
