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