/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: MarshallTool.java 15428 2008-10-07 11:20:29Z sauthieg $
 * --------------------------------------------------------------------------
 */


package org.ow2.jonas.lib.ejb21;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;

/**
 * Contains static methods to marshall/unmarshall objects to/from a byte[]
 *
 * @author Vincent Trussart (vincent@linuxfreak.com) : Initial developer
 * @author Helene Joanin
 */

public class MarshallTool {

    /**
     * Converts an instance of java.io.Serializable to a serialized byte array
     * @param o Object to serialize
     * @return byte array containing the serialization of the Serializable object
     * @throws IOException in error case
     */
    public static synchronized byte[] toBytes(Serializable o)
            throws IOException {

        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bas);

        oos.writeObject(o);
        oos.close();

        return bas.toByteArray();
    }

    /**
     * Converts byte array to an instance of java.io.Serializable
     * @param bytes A byte array containing the a serialized object
     * @return the unmarshalled object
     * @throws IOException in error case
     * @throws ClassNotFoundException in error case
     */
    public static synchronized Serializable fromBytes(byte[] bytes)
            throws IOException, ClassNotFoundException {

        /**
         * Specialization of the java.io.ObjectInputStream to re-implement the
         * resolveClass method
         */
        class SpecializedOIS extends ObjectInputStream {

            /**
             * Default constructor
             * @param is input stream to read from
             * @throws IOException in error case
             */
            SpecializedOIS(InputStream is) throws IOException {
                super(is);
            }

            /**
             * Load the local class equivalent of the specified stream class
             * description using the context class loader.
             * @param osc an instance of class ObjectStreamClass
             * @return a Class object corresponding to the osc
             * @throws IOException in error case
             * @throws ClassNotFoundException in error case
             */
            protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
                try {
                    return super.resolveClass(osc);
                } catch (ClassNotFoundException e) {
                    // Use the thread classloader
                    return Class.forName(osc.getName(), false, Thread.currentThread().getContextClassLoader());
                }
            }
        }

        if (bytes == null) {
            return null;
        }

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        SpecializedOIS sois = new SpecializedOIS(bis);
        return (Serializable) sois.readObject();
    }

}

