169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2010 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.util.proxy;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.InputStream;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ObjectInputStream;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ObjectStreamClass;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * An input stream class which knows how to deserialize proxies created via {@link ProxyFactory} and
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * serializedo via a {@link ProxyObjectOutputStream}. It must be used when deserialising proxies created
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * from a proxy factory configured with {@link ProxyFactory#useWriteReplace} set to false.
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author Andrew Dinn
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ProxyObjectInputStream extends ObjectInputStream
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal{
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * create an input stream which can be used to deserialize an object graph which includes proxies created
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * using class ProxyFactory. the classloader used to resolve proxy superclass and interface names
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * read from the input stream will default to the current thread's context class loader or the system
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * classloader if the context class loader is null.
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param in
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws java.io.StreamCorruptedException whenever ObjectInputStream would also do so
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws	IOException whenever ObjectInputStream would also do so
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws	SecurityException whenever ObjectInputStream would also do so
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws NullPointerException if in is null
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ProxyObjectInputStream(InputStream in) throws IOException
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(in);
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        loader = Thread.currentThread().getContextClassLoader();
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (loader == null) {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            loader = ClassLoader.getSystemClassLoader();
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Reset the loader to be
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param loader
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setClassLoader(ClassLoader loader)
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (loader != null) {
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.loader = loader;
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } else {
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            loader = ClassLoader.getSystemClassLoader();
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean isProxy = readBoolean();
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (isProxy) {
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = (String)readObject();
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Class superClass = loader.loadClass(name);
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int length = readInt();
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Class[] interfaces = new Class[length];
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < length; i++) {
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                name = (String)readObject();
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                interfaces[i] = loader.loadClass(name);
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            length = readInt();
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] signature = new byte[length];
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            read(signature);
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ProxyFactory factory = new ProxyFactory();
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // we must always use the cache and never use writeReplace when using
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // ProxyObjectOutputStream and ProxyObjectInputStream
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            factory.setUseCache(true);
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            factory.setUseWriteReplace(false);
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            factory.setSuperclass(superClass);
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            factory.setInterfaces(interfaces);
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Class proxyClass = factory.createClass(signature);
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return ObjectStreamClass.lookup(proxyClass);
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } else {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return super.readClassDescriptor();
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the loader to use to resolve classes for proxy superclass and interface names read
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * from the stream. defaults to the context class loader of the thread which creates
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the input stream or the system class loader if the context class loader is null.
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ClassLoader loader;
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}