/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed 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 org.activemq.util;

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.OutputStream;
import java.lang.reflect.Proxy;

/**
 * @version $Revision: 1.1.1.1 $
 */
public class SerializationHelper {
    
    static final private ClassLoader ACTIVEMQ_CLASSLOADER = SerializationHelper.class.getClassLoader();

    /**
     * Serialize an Object to a ByteArray
     * @param object
     * @return a byte[] array
     * @throws IOException
     */
    public static byte[] writeObject(Object object) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(buffer);
        out.writeObject(object);
        out.close();
        return buffer.toByteArray();
    }

    /**
     * Read an Object from a byte array
     * @param data
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Object readObject(byte[] data) throws IOException, ClassNotFoundException {
        ByteArrayInputStream buffer = new ByteArrayInputStream(data);
        ObjectInputStreamExt in = new ObjectInputStreamExt(buffer);
        Object answer = in.readObject();
        in.close();
        return answer;
    }
    
    /**
     * read an object from an InputStream
     * @param in
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Object readObject(InputStream in) throws IOException, ClassNotFoundException{
        ObjectInputStreamExt objIn = new ObjectInputStreamExt(in);
        Object result = objIn.readObject();
        return result;
        
    }
    
    /**
     * Write an Object to an OutputStream
     * @param out
     * @param obj
     * @throws IOException
     */
    public static void writeObject(OutputStream out, Object obj) throws IOException{
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(obj);
        objOut.flush();
    }
    
    static public class ObjectInputStreamExt extends ObjectInputStream {

        public ObjectInputStreamExt(InputStream in) throws IOException {
            super(in);
        }

        protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            return load(classDesc.getName(), cl);
        }

        protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Class[] cinterfaces = new Class[interfaces.length];
            for (int i = 0; i < interfaces.length; i++)
                cinterfaces[i] = load(interfaces[i], cl);

            try {
                return Proxy.getProxyClass(cinterfaces[0].getClassLoader(), cinterfaces);
            } catch (IllegalArgumentException e) {
                throw new ClassNotFoundException(null, e);
            }
        }

        private Class load(String className, ClassLoader cl) throws ClassNotFoundException {
            try {
                return ClassLoading.loadClass(className, cl);
            } catch ( ClassNotFoundException e ) {
                return ClassLoading.loadClass(className, ACTIVEMQ_CLASSLOADER);
            }
        }

     }

}
