class ProxyObjectInputStream extends ObjectInputStream
{
    /**
     * create an input stream which can be used to deserialize an object graph which includes proxies created
     * using class ProxyFactory. the classloader used to resolve proxy superclass and interface names
     * read from the input stream will default to the current thread's context class loader or the system
     * classloader if the context class loader is null.
     * @param in
     * @throws java.io.StreamCorruptedException whenever ObjectInputStream would also do so
     * @throws	IOException whenever ObjectInputStream would also do so
     * @throws	SecurityException whenever ObjectInputStream would also do so
     * @throws NullPointerException if in is null
     */
    public ProxyObjectInputStream(InputStream in) throws IOException
    {
        super(in);
        loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            loader = ClassLoader.getSystemClassLoader();
        }
    }

    /**
     * Reset the loader to be
     * @param loader
     */
    public void setClassLoader(ClassLoader loader)
    {
        if (loader != null) {
            this.loader = loader;
        } else {
            loader = ClassLoader.getSystemClassLoader();
        }
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {<FILL_FUNCTION_BODY>}

    /**
     * the loader to use to resolve classes for proxy superclass and interface names read
     * from the stream. defaults to the context class loader of the thread which creates
     * the input stream or the system class loader if the context class loader is null.
     */
    private ClassLoader loader;
}

        boolean isProxy = readBoolean();
        if (isProxy) {
            String name = (String)readObject();
            Class<?> superClass = loader.loadClass(name);
            int length = readInt();
            Class<?>[] interfaces = new Class[length];
            for (int i = 0; i < length; i++) {
                name = (String)readObject();
                interfaces[i] = loader.loadClass(name);
            }
            length = readInt();
            byte[] signature = new byte[length];
            read(signature);
            ProxyFactory factory = new ProxyFactory();
            // we must always use the cache and never use writeReplace when using
            // ProxyObjectOutputStream and ProxyObjectInputStream
            factory.setUseCache(true);
            factory.setUseWriteReplace(false);
            factory.setSuperclass(superClass);
            factory.setInterfaces(interfaces);
            Class<?> proxyClass = factory.createClass(signature);
            return ObjectStreamClass.lookup(proxyClass);
        }
        return super.readClassDescriptor();
    
<methods>public void <init>(java.io.InputStream) throws java.io.IOException,public int available() throws java.io.IOException,public void close() throws java.io.IOException,public void defaultReadObject() throws java.io.IOException, java.lang.ClassNotFoundException,public final java.io.ObjectInputFilter getObjectInputFilter() ,public int read() throws java.io.IOException,public int read(byte[], int, int) throws java.io.IOException,public boolean readBoolean() throws java.io.IOException,public byte readByte() throws java.io.IOException,public char readChar() throws java.io.IOException,public double readDouble() throws java.io.IOException,public java.io.ObjectInputStream.GetField readFields() throws java.io.IOException, java.lang.ClassNotFoundException,public float readFloat() throws java.io.IOException,public void readFully(byte[]) throws java.io.IOException,public void readFully(byte[], int, int) throws java.io.IOException,public int readInt() throws java.io.IOException,public java.lang.String readLine() throws java.io.IOException,public long readLong() throws java.io.IOException,public final java.lang.Object readObject() throws java.io.IOException, java.lang.ClassNotFoundException,public short readShort() throws java.io.IOException,public java.lang.String readUTF() throws java.io.IOException,public java.lang.Object readUnshared() throws java.io.IOException, java.lang.ClassNotFoundException,public int readUnsignedByte() throws java.io.IOException,public int readUnsignedShort() throws java.io.IOException,public void registerValidation(java.io.ObjectInputValidation, int) throws java.io.NotActiveException, java.io.InvalidObjectException,public final void setObjectInputFilter(java.io.ObjectInputFilter) ,public int skipBytes(int) throws java.io.IOException<variables>static final boolean $assertionsDisabled,private static final int NULL_HANDLE,private static final jdk.internal.misc.Unsafe UNSAFE,private final java.io.ObjectInputStream.BlockDataInputStream bin,private boolean closed,private java.io.SerialCallbackContext curContext,private boolean defaultDataEnd,private long depth,private final boolean enableOverride,private boolean enableResolve,private final java.io.ObjectInputStream.HandleTable handles,private int passHandle,private static final Map<java.lang.String,Class<?>> primClasses,private java.io.ObjectInputFilter serialFilter,private boolean streamFilterSet,private long totalObjectRefs,private static final java.lang.Object unsharedMarker,private final java.io.ObjectInputStream.ValidationList vlist