Home | History | Annotate | Download | only in proxy
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2010 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist.util.proxy;
     17 
     18 import java.io.IOException;
     19 import java.io.InputStream;
     20 import java.io.ObjectInputStream;
     21 import java.io.ObjectStreamClass;
     22 
     23 /**
     24  * An input stream class which knows how to deserialize proxies created via {@link ProxyFactory} and
     25  * serializedo via a {@link ProxyObjectOutputStream}. It must be used when deserialising proxies created
     26  * from a proxy factory configured with {@link ProxyFactory#useWriteReplace} set to false.
     27  *
     28  * @author Andrew Dinn
     29  */
     30 public class ProxyObjectInputStream extends ObjectInputStream
     31 {
     32     /**
     33      * create an input stream which can be used to deserialize an object graph which includes proxies created
     34      * using class ProxyFactory. the classloader used to resolve proxy superclass and interface names
     35      * read from the input stream will default to the current thread's context class loader or the system
     36      * classloader if the context class loader is null.
     37      * @param in
     38      * @throws java.io.StreamCorruptedException whenever ObjectInputStream would also do so
     39      * @throws	IOException whenever ObjectInputStream would also do so
     40      * @throws	SecurityException whenever ObjectInputStream would also do so
     41      * @throws NullPointerException if in is null
     42      */
     43     public ProxyObjectInputStream(InputStream in) throws IOException
     44     {
     45         super(in);
     46         loader = Thread.currentThread().getContextClassLoader();
     47         if (loader == null) {
     48             loader = ClassLoader.getSystemClassLoader();
     49         }
     50     }
     51 
     52     /**
     53      * Reset the loader to be
     54      * @param loader
     55      */
     56     public void setClassLoader(ClassLoader loader)
     57     {
     58         if (loader != null) {
     59             this.loader = loader;
     60         } else {
     61             loader = ClassLoader.getSystemClassLoader();
     62         }
     63     }
     64 
     65     protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
     66         boolean isProxy = readBoolean();
     67         if (isProxy) {
     68             String name = (String)readObject();
     69             Class superClass = loader.loadClass(name);
     70             int length = readInt();
     71             Class[] interfaces = new Class[length];
     72             for (int i = 0; i < length; i++) {
     73                 name = (String)readObject();
     74                 interfaces[i] = loader.loadClass(name);
     75             }
     76             length = readInt();
     77             byte[] signature = new byte[length];
     78             read(signature);
     79             ProxyFactory factory = new ProxyFactory();
     80             // we must always use the cache and never use writeReplace when using
     81             // ProxyObjectOutputStream and ProxyObjectInputStream
     82             factory.setUseCache(true);
     83             factory.setUseWriteReplace(false);
     84             factory.setSuperclass(superClass);
     85             factory.setInterfaces(interfaces);
     86             Class proxyClass = factory.createClass(signature);
     87             return ObjectStreamClass.lookup(proxyClass);
     88         } else {
     89             return super.readClassDescriptor();
     90         }
     91     }
     92 
     93     /**
     94      * the loader to use to resolve classes for proxy superclass and interface names read
     95      * from the stream. defaults to the context class loader of the thread which creates
     96      * the input stream or the system class loader if the context class loader is null.
     97      */
     98     private ClassLoader loader;
     99 }