/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.SDOXMLHelper;

import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.XMLDocument;
import commonj.sdo.impl.ExternalizableDelegator;

/**
 * INTERNAL:
 * <p><b>Purpose:</b></p>
 * This class performs serialization/deserialization of an SDODataObject.
 * <p><b>Responsibilities:</b></p>
 * <ul>
 * <li>Provide/override default Java serializable access to a DataObject</li>
 * </ul>
 * Serialization Process
 *
 * <p>Serialization and de-serialization of objects occurs during DAS transactions,
 *   Web Service transactions in the SOAP envelope, EJB container passivation,
 *   web container session saving or directly in an application using the function
 *   ObjectOutputStream.writeObject(Object).
 *   The Serializable and Externalizable framework handles automatic or user defined
 *   reading/writing of streams depending on which interface functions are realized in the implementing classes.</p>
 *
 * <p>The Serializable interface has no operations - therefore a class that implements
 * it needs to add no additional functionality.
 *     Why do this? - For security.  The security manager in the JVM will only serialize objects at
 * runtime if they are flagged as Serializable (or Externalizable) so that by default
 * java classes do not expose themselves to serialization.  (See p49 of Java Security 2nd edition).</p>
 *
 * <p>There are 3 levels of serialization control.</p>
 * <ul><li><i>1) Default Serialization</i><br>
 *     Here we make the class implement Serializable, mark non-serializable fields as
 * transient and implement no new functions.</li>
 * <li><i>2) Partial custom Serialization</i><br>
 *     Here we make the class implement Serializable and implement the optional functions
 * writeObject and readObject to handle custom serialization of the current class while
 * using the default serialization for super and subtypes.</li>
 *
 * <li><b>3) Fully customized Serialization - current implementation</b>.<br>
 *     Here we make the class implement Externalizable and implement the functions
 * readResolve, writeReplace, readExternal, writeExternal.
 * Supertypes and subtypes must also implement these functions.</li>
 * </ul>
 * <p>The SDO 2.01 specification details the high level structure of the
 * serialization format on page 64, section 6 - Java Serialization of DataObjects.
 *     The process will involve gzip serialization of the xml data with UTF representation of the
 * Xpath address of the current DataObject inside the entire tree along with its identification as root/no-root in
 * binary 1/0 format as follows.</p>
 *
 * <ul><li><b>Security:</b><br>
 *     The following public functions expose a data replacement vulnerability where an
 *     outside client can gain access and modify their constants.
 *     We may need to wrap the GZIP streams in some sort of encryption when we are not
 *     using HTTPS or SSL/TLS on the wire.
 *
 * public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
 * public void writeExternal(ObjectOutput out) throws IOException</li>
 * <li><b>Concurrency:</b><br>
 *     Avoid synchronized classes that will queue threaded clients such as Enumeration, Vector etc.
 * We need to discuss how this API will be used by containers like an EJB container that can
 * invoke multithreaded clients.</li>
 *
 *     <li><b>Scalability:</b><br></li>
 *     <li>XML Serialization Size is 4GB:<p>
 *     There is a limitation set by the SDO Specification on the size of the DataObject serialization.
 *     According to the spec we must use an integer to define the size of the GZIP buffer that is serialized.
 *     This size is limited to +/- 2GB.  This limitation is actually set by the JVM itself because a
 *     call to buffer.length returns a signed 32 bit integer.
 * </p></li>
 * <li><b>Performance:</b><br>
 *    Using custom serialization via the Externalizable interface is 30% faster than the
 *    default java serialization because the JVM does not need to discover the class definition.</li>
 * </ul>
 * @since Oracle TopLink 11.1.1.0.0
 */
public class SDOResolvable implements ExternalizableDelegator.Resolvable {

    /** Unique hash ID of this Externalizable class. Use [serialver org.eclipse.persistence.sdo.SDOResolvable] */
    private static final long serialVersionUID = 2807334877368539299L;

    /** Root element name for all DataObjects undergoing serialization = sdo:dataObject */
    public static final String DEFAULT_ROOT_ELEMENT_NAME = "dataObject";

    /** root object with helper context id identifier */
    public static final int SDO_HELPER_CONTEXT_ID_IDENTIFIER = 2;

    /** root object serialization type identifier = 1 */
    public static final int SDO_ROOT_OBJECT_IDENTIFIER = 1;

    /** internal object serialization type identifier = 0 */
    public static final int SDO_INTERNAL_OBJECT_IDENTIFIER = 0;

    /** Visibility reduced from [public] in 2.1.0. May 15 2007 */
    /** member field holding DataObject being serialized/deserialized */
    private transient SDODataObject theSDODataObject;

    /** Visibility reduced from [public] in 2.1.0. May 15 2007 */
    /** hold the context containing all helpers so that we can preserve inter-helper relationships */
    private transient HelperContext aHelperContext;

    public SDOResolvable() {
        aHelperContext = SDOHelperContext.getHelperContext();
    }

    /**
     * Default constructor for deserialization
     */
    public SDOResolvable(HelperContext aContext) {
        aHelperContext = aContext;
    }

    /**
     * Constructor for serialization
     */
    public SDOResolvable(Object target, HelperContext aContext) {
        // set the serialized/deserialized object holder
        theSDODataObject = (SDODataObject)target;
        aHelperContext = aContext;
    }

    /**
     * Purpose: This function is called after readExternal to return the
     * recently deserialized object retrieved from the ObjectInputStream.
     * Here there is an opportunity to replace the object with a Singleton version
     */
    @Override
    public Object readResolve() throws ObjectStreamException {
        // return object previously constructed in readExternal()
        return theSDODataObject;
    }

    /**
     * Purpose: Serialize an SDODataObject to an ObjectOutputStream This
     * function is mandated by the Externalizable interface. It writes binary
     * data in the same order as was will be read back in readExternal().
     *
     * Prerequisites: An object has already been constructed and associated with
     * the theSDODataObject member
     */
    @Override
    public void writeExternal(ObjectOutput objectOutput) throws IOException {
        GZIPOutputStream aGZIPOutputStream = null;
        ByteArrayOutputStream aByteOutputStream = null;

        // check whether we are a root DataObject, write gzip of the root
        if ((theSDODataObject.getContainer() == null)) {
            try {
                // is a root object
                String identifier = null;
                if(this.aHelperContext.getClass() == SDOHelperContext.class) {
                    identifier = ((SDOHelperContext)this.aHelperContext).getIdentifier();
                }
                if(identifier != null && !(identifier.equals(""))) {
                    objectOutput.writeByte(SDO_HELPER_CONTEXT_ID_IDENTIFIER);
                    objectOutput.writeUTF(identifier);
                } else {
                    objectOutput.writeByte(SDO_ROOT_OBJECT_IDENTIFIER);
                }


                // write root xml
                aByteOutputStream = new ByteArrayOutputStream();

                // chain a GZIP stream to the byte stream
                aGZIPOutputStream = new GZIPOutputStream(aByteOutputStream);

                // write XML Serialization of the root DataObject to the GZIP output stream
                XMLDocument aDocument = aHelperContext.getXMLHelper().createDocument(//
                        theSDODataObject, //
                        SDOConstants.SDO_URL, // root element URI
                        SDOConstants.SDO_PREFIX + SDOConstants.SDO_XPATH_NS_SEPARATOR_FRAGMENT + DEFAULT_ROOT_ELEMENT_NAME);
                ((SDOXMLHelper) aHelperContext.getXMLHelper()).serialize(aDocument, aGZIPOutputStream, null);
                // finished the stream to move compressed data from the Deflater
                aGZIPOutputStream.finish();
                // flush the streams
                aGZIPOutputStream.flush();
                aByteOutputStream.flush();

                // get bytes from ByteOutputStream
                byte[] buf = aByteOutputStream.toByteArray();

                // write gzip buffer length
                objectOutput.writeInt(buf.length);// compressed xml file length
                // write gzip buffer to ostream
                objectOutput.write(buf);
            } finally {
                // close streams on all Exceptions
                if (aGZIPOutputStream != null) {// Clover: false case testing requires IO/comm failure
                    aGZIPOutputStream.close();
                }
                if (aByteOutputStream != null) {// Clover: false case testing requires IO/comm failure
                    aByteOutputStream.close();
                }
            }
        } else {
            // Internal non-root object, write the path to the from this object to the root
            // call this function recursively again for the root object serialization
            objectOutput.writeByte(SDO_INTERNAL_OBJECT_IDENTIFIER);

            // write path to the root
            String aPath = theSDODataObject._getPath();
            objectOutput.writeUTF(aPath);

            // write root (via indirect recursion to SDOResolvable)
            objectOutput.writeObject(theSDODataObject.getRootObject());
        }
    }

    /**
     * Purpose: Deserialize from an ObjectInputStream into an SDODataObject This
     * function is mandated by the Externalizable interface. It reads back
     * binary data in the same order as was written in writeExternal(). An
     * object has already been constructed with the no-arg constructor before
     * this function fills in the member fields.
     *
     * The deserialized object will be returned later in a call from the
     * ObjectInputStream to readResolve()
     */
    @Override
    public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
        ByteArrayInputStream aByteInputStream = null;
        GZIPInputStream aGZIPInputStream = null;

        // read first byte to get DataObject type [0 = internal, 1 = root]
        int dataObjectIdentifier = objectInput.read();

        /**
         * based on the first byte of the object stream we will deserialize into
         * either of the following.
         *
         * Internal: byte(0) = 0 [path] = XPath string in UTF format with the
         * location of the object in relation to the root [root] = theserialized
         * root DataObject (2 calls to this function)
         *
         * Root: byte(0) = 1 [rootXML] = the GZIP binary stream of the XML
         * serialization of the root DataObject (1 call to this function)
         */

        // check whether we are a root DataObject, write gzip of the root
        switch (dataObjectIdentifier) {
        case SDO_INTERNAL_OBJECT_IDENTIFIER:
            // not a root object, read the [path] and [root]
            // read path to the root
            String xPathString = objectInput.readUTF();

            // read root (an ExternalizableDelegator) via an indirect recursive call back to
            // the root case below will resolve the root
            SDODataObject deserializedDataObject = (SDODataObject)objectInput.readObject();

            // point SDODataObject member to the internal node based on XPath retrieved
            theSDODataObject = (SDODataObject)deserializedDataObject.get(xPathString);
            // return internal DataObject in next readResolve callback
            break;
        case SDO_ROOT_OBJECT_IDENTIFIER:
            try {
                // get length of gzip stream
                int aStreamLength = objectInput.readInt();

                // read in gzip bytes [rootXML]
                byte[] aGZIPByteArray = new byte[aStreamLength];

                // read in the length of bytes - EOF, buffering and stream
                // length is handled internally by this function
                objectInput.readFully(aGZIPByteArray);

                // setup input stream chaining
                aByteInputStream = new ByteArrayInputStream(aGZIPByteArray);

                // chain a GZIP stream to the byte stream
                aGZIPInputStream = new GZIPInputStream(aByteInputStream);

                // read XML Serialization of the root DataObject from the GZIP input stream
                XMLDocument aDocument = aHelperContext.getXMLHelper().load(aGZIPInputStream);

                theSDODataObject = (SDODataObject)aDocument.getRootObject();
            } finally {
                // close streams on all Exceptions
                if (aGZIPInputStream != null) {// Clover: false case testing requires IO/comm failure
                    aGZIPInputStream.close();
                }
                if (aByteInputStream != null) {// Clover: false case testing requires IO/comm failure
                    aByteInputStream.close();
                }
            }
            break;
        case SDO_HELPER_CONTEXT_ID_IDENTIFIER:
            try {
                String helperContextIdentifier = objectInput.readUTF();
                // get length of gzip stream
                int aStreamLength = objectInput.readInt();

                // read in gzip bytes [rootXML]
                byte[] aGZIPByteArray = new byte[aStreamLength];

                // read in the length of bytes - EOF, buffering and stream
                // length is handled internally by this function
                objectInput.readFully(aGZIPByteArray);

                // setup input stream chaining
                aByteInputStream = new ByteArrayInputStream(aGZIPByteArray);

                // chain a GZIP stream to the byte stream
                aGZIPInputStream = new GZIPInputStream(aByteInputStream);

                // read XML Serialization of the root DataObject from the GZIP input stream
                HelperContext contextToUse = SDOHelperContext.getHelperContext(helperContextIdentifier);

                XMLDocument aDocument = contextToUse.getXMLHelper().load(aGZIPInputStream);

                theSDODataObject = (SDODataObject)aDocument.getRootObject();
            } finally {
                // close streams on all Exceptions
                if (aGZIPInputStream != null) {// Clover: false case testing requires IO/comm failure
                    aGZIPInputStream.close();
                }
                if (aByteInputStream != null) {// Clover: false case testing requires IO/comm failure
                    aByteInputStream.close();
                }
            }
            break;
        }
    }

    /**
     *
     * @return
     */
    public HelperContext getHelperContext() {
        return aHelperContext;
    }

    /**
     *
     * @param helperContext
     */
    public void setHelperContext(HelperContext helperContext) {
        aHelperContext = helperContext;
    }
}
