151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ObjectStreamClass.WeakClassKey;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.ReferenceQueue;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.Array;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.Modifier;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.Proxy;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessControlContext;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedAction;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedActionException;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedExceptionAction;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.HashMap;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentHashMap;
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentMap;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.atomic.AtomicBoolean;
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport static java.io.ObjectStreamClass.processQueue;
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.reflect.misc.ReflectUtil;
468d05e88f57c1ea5543d4012687c70cd64efcada0Piotr Jastrzebskiimport dalvik.system.VMStack;
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * An ObjectInputStream deserializes primitive data and objects previously
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * written using an ObjectOutputStream.
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>ObjectOutputStream and ObjectInputStream can provide an application with
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * persistent storage for graphs of objects when used with a FileOutputStream
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and FileInputStream respectively.  ObjectInputStream is used to recover
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * those objects previously serialized. Other uses include passing objects
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * between hosts using a socket stream or for marshaling and unmarshaling
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * arguments and parameters in a remote communication system.
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>ObjectInputStream ensures that the types of all objects in the graph
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * created from the stream match the classes present in the Java Virtual
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Machine.  Classes are loaded as required using the standard mechanisms.
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Only objects that support the java.io.Serializable or
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * java.io.Externalizable interface can be read from streams.
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The method <code>readObject</code> is used to read an object from the
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream.  Java's safe casting should be used to get the desired type.  In
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Java, strings and arrays are objects and are treated as objects during
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization. When read they need to be cast to the expected type.
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Primitive data types can be read from the stream using the appropriate
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method on DataInput.
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The default deserialization mechanism for objects restores the contents
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of each field to the value and type it had when it was written.  Fields
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * declared as transient or static are ignored by the deserialization process.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * References to other objects cause those objects to be read from the stream
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as necessary.  Graphs of objects are restored correctly using a reference
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sharing mechanism.  New objects are always allocated when deserializing,
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which prevents existing objects from being overwritten.
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Reading an object is analogous to running the constructors of a new
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object.  Memory is allocated for the object and initialized to zero (NULL).
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * No-arg constructors are invoked for the non-serializable classes and then
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the fields of the serializable classes are restored from the stream starting
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with the serializable class closest to java.lang.object and finishing with
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the object's most specific class.
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>For example to read from a stream as written by the example in
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ObjectOutputStream:
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <br>
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      FileInputStream fis = new FileInputStream("t.tmp");
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      ObjectInputStream ois = new ObjectInputStream(fis);
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      int i = ois.readInt();
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      String today = (String) ois.readObject();
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      Date date = (Date) ois.readObject();
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      ois.close();
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre>
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Classes control how they are serialized by implementing either the
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * java.io.Serializable or java.io.Externalizable interfaces.
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Implementing the Serializable interface allows object serialization to
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * save and restore the entire state of the object and it allows classes to
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * evolve between the time the stream is written and the time it is read.  It
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * automatically traverses references between objects, saving and restoring
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * entire graphs.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Serializable classes that require special handling during the
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serialization and deserialization process should implement the following
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods:<p>
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void writeObject(java.io.ObjectOutputStream stream)
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     throws IOException;
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void readObject(java.io.ObjectInputStream stream)
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     throws IOException, ClassNotFoundException;
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private void readObjectNoData()
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     throws ObjectStreamException;
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre>
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The readObject method is responsible for reading and restoring the state
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the object for its particular class using data written to the stream by
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the corresponding writeObject method.  The method does not need to concern
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * itself with the state belonging to its superclasses or subclasses.  State is
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * restored by reading data from the ObjectInputStream for the individual
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * fields and making assignments to the appropriate fields of the object.
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reading primitive data types is supported by DataInput.
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Any attempt to read object data which exceeds the boundaries of the
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * custom data written by the corresponding writeObject method will cause an
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OptionalDataException to be thrown with an eof field value of true.
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Non-object reads which exceed the end of the allotted data will reflect the
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * end of data in the same way that they would indicate the end of the stream:
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bytewise reads will return -1 as the byte read or number of bytes read, and
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * primitive reads will throw EOFExceptions.  If there is no corresponding
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * writeObject method, then the end of default serialized data marks the end of
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the allotted data.
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Primitive and object read calls issued from within a readExternal method
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * behave in the same manner--if the stream is already positioned at the end of
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data written by the corresponding writeExternal method, object reads will
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * throw OptionalDataExceptions with eof set to true, bytewise reads will
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * return -1, and primitive reads will throw EOFExceptions.  Note that this
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * behavior does not hold for streams written with the old
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * end of data written by writeExternal methods is not demarcated, and hence
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cannot be detected.
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>The readObjectNoData method is responsible for initializing the state of
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the object for its particular class in the event that the serialization
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream does not list the given class as a superclass of the object being
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * deserialized.  This may occur in cases where the receiving party uses a
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * different version of the deserialized instance's class than the sending
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * party, and the receiver's version extends classes that are not extended by
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the sender's version.  This may also occur if the serialization stream has
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * been tampered; hence, readObjectNoData is useful for initializing
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * deserialized objects properly despite a "hostile" or incomplete source
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream.
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Serialization does not read or assign values to the fields of any object
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that does not implement the java.io.Serializable interface.  Subclasses of
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Objects that are not serializable can be serializable. In this case the
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * non-serializable class must have a no-arg constructor to allow its fields to
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be initialized.  In this case it is the responsibility of the subclass to
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * save and restore the state of the non-serializable class. It is frequently
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the case that the fields of that class are accessible (public, package, or
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * protected) or that there are get and set methods that can be used to restore
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the state.
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Any exception that occurs while deserializing an object will be caught by
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the ObjectInputStream and abort the reading process.
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Implementing the Externalizable interface allows the object to assume
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * complete control over the contents and format of the object's serialized
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * form.  The methods of the Externalizable interface, writeExternal and
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * readExternal, are called to save and restore the objects state.  When
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * implemented by a class they can write and read their own state using all of
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the objects to handle any versioning that occurs.
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Enum constants are deserialized differently than ordinary serializable or
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * externalizable objects.  The serialized form of an enum constant consists
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * solely of its name; field values of the constant are not transmitted.  To
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * deserialize an enum constant, ObjectInputStream reads the constant name from
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream; the deserialized constant is then obtained by calling the static
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * base type and the received constant name as arguments.  Like other
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * serializable or externalizable objects, enum constants can function as the
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * targets of back references appearing subsequently in the serialization
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream.  The process by which enum constants are deserialized cannot be
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * customized: any class-specific readObject, readObjectNoData, and readResolve
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods defined by enum types are ignored during deserialization.
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Similarly, any serialPersistentFields or serialVersionUID field declarations
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are also ignored--all enum types have a fixed serialVersionUID of 0L.
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author      Mike Warres
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author      Roger Riggs
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.DataInput
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.ObjectOutputStream
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see java.io.Serializable
205d2449bb576ad1e3a3877364e5e1ae28625f69e35Yi Kong * @see <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since   JDK1.1
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class ObjectInputStream
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    extends InputStream implements ObjectInput, ObjectStreamConstants
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
2118d05e88f57c1ea5543d4012687c70cd64efcada0Piotr Jastrzebski
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** handle value representing null */
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int NULL_HANDLE = -1;
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** marker for unshared objects in internal handle table */
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final Object unsharedMarker = new Object();
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** table mapping primitive type names to corresponding class objects */
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final HashMap<String, Class<?>> primClasses
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        = new HashMap<>(8, 1.0F);
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static {
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("boolean", boolean.class);
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("byte", byte.class);
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("char", char.class);
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("short", short.class);
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("int", int.class);
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("long", long.class);
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("float", float.class);
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("double", double.class);
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        primClasses.put("void", void.class);
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class Caches {
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** cache of subclass security audit results */
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            new ConcurrentHashMap<>();
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** queue for WeakReferences to audited subclasses */
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        static final ReferenceQueue<Class<?>> subclassAuditsQueue =
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            new ReferenceQueue<>();
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** filter stream for handling block data conversion */
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final BlockDataInputStream bin;
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** validation callback list */
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final ValidationList vlist;
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** recursion depth */
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int depth;
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** whether stream is closed */
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean closed;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** wire handle -> obj/exception map */
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final HandleTable handles;
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** scratch field for passing handle values up/down call stack */
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int passHandle = NULL_HANDLE;
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean defaultDataEnd = false;
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** buffer for reading primitive field values */
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private byte[] primVals;
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** if true, invoke readObjectOverride() instead of readObject() */
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final boolean enableOverride;
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** if true, invoke resolveObject() */
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean enableResolve;
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Context during upcalls to class-defined readObject methods; holds
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object currently being deserialized and descriptor for current class.
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Null when not during readObject upcall.
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private SerialCallbackContext curContext;
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an ObjectInputStream that reads from the specified InputStream.
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * A serialization stream header is read from the stream and verified.
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This constructor will block until the corresponding ObjectOutputStream
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * has written and flushed the header.
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>If a security manager is installed, this constructor will check for
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the "enableSubclassImplementation" SerializablePermission when invoked
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * directly or indirectly by the constructor of a subclass which overrides
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * methods.
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   in input stream to read from
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  StreamCorruptedException if the stream header is incorrect
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if an I/O error occurs while reading stream header
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  SecurityException if untrusted subclass illegally overrides
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          security-sensitive methods
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  NullPointerException if <code>in</code> is <code>null</code>
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     ObjectInputStream#ObjectInputStream()
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     ObjectInputStream#readFields()
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public ObjectInputStream(InputStream in) throws IOException {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verifySubclass();
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin = new BlockDataInputStream(in);
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles = new HandleTable(10);
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vlist = new ValidationList();
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        enableOverride = false;
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        readStreamHeader();
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(true);
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Provide a way for subclasses that are completely reimplementing
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ObjectInputStream to not have to allocate private data just used by this
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * implementation of ObjectInputStream.
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>If there is a security manager installed, this method first calls the
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * security manager's <code>checkPermission</code> method with the
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>SerializablePermission("enableSubclassImplementation")</code>
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * permission to ensure it's ok to enable subclassing.
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  SecurityException if a security manager exists and its
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <code>checkPermission</code> method denies enabling
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          subclassing.
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see SecurityManager#checkPermission
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.io.SerializablePermission
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected ObjectInputStream() throws IOException, SecurityException {
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SecurityManager sm = System.getSecurityManager();
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sm != null) {
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin = null;
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles = null;
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vlist = null;
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        enableOverride = true;
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Read an object from the ObjectInputStream.  The class of the object, the
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * signature of the class, and the values of the non-transient and
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * non-static fields of the class and all of its supertypes are read.
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Default deserializing for a class can be overriden using the writeObject
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and readObject methods.  Objects referenced by this object are read
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * transitively so that a complete equivalent graph of objects is
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reconstructed by readObject.
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>The root object is completely restored when all of its fields and the
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * objects it references are completely restored.  At this point the object
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * validation callbacks are executed in order based on their registered
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * priorities. The callbacks are registered by objects (in the readObject
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * special methods) as they are individually restored.
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>Exceptions are thrown for problems with the InputStream and for
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * classes that should not be deserialized.  All exceptions are fatal to
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the InputStream and leave it in an indeterminate state; it is up to the
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * caller to ignore or recover the stream state.
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException Class of a serialized object cannot be
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          found.
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  InvalidClassException Something is wrong with a class used by
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          serialization.
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  StreamCorruptedException Control information in the
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          stream is inconsistent.
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  OptionalDataException Primitive data was found in the
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          stream instead of objects.
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException Any of the usual Input/Output related exceptions.
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final Object readObject()
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (enableOverride) {
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return readObjectOverride();
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if nested read, passHandle contains handle of enclosing object
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int outerHandle = passHandle;
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object obj = readObject0(false);
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markDependency(outerHandle, passHandle);
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ClassNotFoundException ex = handles.lookupException(passHandle);
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ex != null) {
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw ex;
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (depth == 0) {
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vlist.doCallbacks();
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return obj;
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            passHandle = outerHandle;
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (closed && depth == 0) {
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                clear();
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method is called by trusted subclasses of ObjectOutputStream that
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constructed ObjectOutputStream using the protected no-arg constructor.
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The subclass is expected to provide an override method with the modifier
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * "final".
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the Object read from the stream.
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException Class definition of a serialized object
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          cannot be found.
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  OptionalDataException Primitive data was found in the stream
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          instead of objects.
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if I/O errors occurred while reading from the
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          underlying stream
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #ObjectInputStream()
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #readObject()
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.2
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Object readObjectOverride()
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads an "unshared" object from the ObjectInputStream.  This method is
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * identical to readObject, except that it prevents subsequent calls to
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * readObject and readUnshared from returning additional references to the
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * deserialized instance obtained via this call.  Specifically:
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <ul>
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *   <li>If readUnshared is called to deserialize a back-reference (the
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *       stream representation of an object which has been written
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *       previously to the stream), an ObjectStreamException will be
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *       thrown.
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *   <li>If readUnshared returns successfully, then any subsequent attempts
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *       to deserialize back-references to the stream handle deserialized
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *       by readUnshared will cause an ObjectStreamException to be thrown.
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </ul>
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Deserializing an object via readUnshared invalidates the stream handle
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with the returned object.  Note that this in itself does not
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * always guarantee that the reference returned by readUnshared is unique;
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the deserialized object may define a readResolve method which returns an
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object visible to other parties, or readUnshared may return a Class
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object or enum constant obtainable elsewhere in the stream or through
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * external means. If the deserialized object defines a readResolve method
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and the invocation of that method returns an array, then readUnshared
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returns a shallow clone of that array; this guarantees that the returned
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * array object is unique and cannot be obtained a second time from an
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * invocation of readObject or readUnshared on the ObjectInputStream,
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * even if the underlying data stream has been manipulated.
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>ObjectInputStream subclasses which override this method can only be
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constructed in security contexts possessing the
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * "enableSubclassImplementation" SerializablePermission; any attempt to
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * instantiate such a subclass without this permission will cause a
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * SecurityException to be thrown.
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  reference to deserialized object
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException if class of an object to deserialize
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          cannot be found
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  StreamCorruptedException if control information in the stream
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          is inconsistent
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ObjectStreamException if object to deserialize has already
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          appeared in stream
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  OptionalDataException if primitive data is next in stream
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if an I/O error occurs during deserialization
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since   1.4
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Object readUnshared() throws IOException, ClassNotFoundException {
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if nested read, passHandle contains handle of enclosing object
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int outerHandle = passHandle;
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object obj = readObject0(true);
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markDependency(outerHandle, passHandle);
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ClassNotFoundException ex = handles.lookupException(passHandle);
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ex != null) {
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw ex;
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (depth == 0) {
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vlist.doCallbacks();
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return obj;
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            passHandle = outerHandle;
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (closed && depth == 0) {
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                clear();
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Read the non-static and non-transient fields of the current class from
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this stream.  This may only be called from the readObject method of the
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class being deserialized. It will throw the NotActiveException if it is
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called otherwise.
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException if the class of a serialized object
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          could not be found.
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if an I/O error occurs.
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  NotActiveException if the stream is not currently reading
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          objects.
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void defaultReadObject()
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (curContext == null) {
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NotActiveException("not in call to readObject");
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object curObj = curContext.getObj();
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass curDesc = curContext.getDesc();
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(false);
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        defaultReadFields(curObj, curDesc);
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(true);
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!curDesc.hasWriteObjectData()) {
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Fix for 4360508: since stream does not contain terminating
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * knows to simulate end-of-custom-data behavior.
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            defaultDataEnd = true;
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException ex = handles.lookupException(passHandle);
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ex != null) {
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw ex;
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads the persistent fields from the stream and makes them available by
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * name.
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the <code>GetField</code> object representing the persistent
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          fields of the object being deserialized
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException if the class of a serialized object
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          could not be found.
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if an I/O error occurs.
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  NotActiveException if the stream is not currently reading
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          objects.
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.2
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public ObjectInputStream.GetField readFields()
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (curContext == null) {
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NotActiveException("not in call to readObject");
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object curObj = curContext.getObj();
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass curDesc = curContext.getDesc();
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(false);
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        GetFieldImpl getField = new GetFieldImpl(curDesc);
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        getField.readFields();
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(true);
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!curDesc.hasWriteObjectData()) {
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Fix for 4360508: since stream does not contain terminating
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * knows to simulate end-of-custom-data behavior.
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            defaultDataEnd = true;
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getField;
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Register an object to be validated before the graph is returned.  While
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * similar to resolveObject these validations are called after the entire
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * graph has been reconstituted.  Typically, a readObject method will
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * register the object with the stream so that when all of the objects are
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * restored a final set of validations can be performed.
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   obj the object to receive the validation callback.
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   prio controls the order of callbacks;zero is a good default.
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          Use higher numbers to be called back earlier, lower numbers for
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          later callbacks. Within a priority, callbacks are processed in
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          no particular order.
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  NotActiveException The stream is not currently reading objects
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          so it is invalid to register a callback.
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  InvalidObjectException The validation object is null.
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void registerValidation(ObjectInputValidation obj, int prio)
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws NotActiveException, InvalidObjectException
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (depth == 0) {
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NotActiveException("stream inactive");
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vlist.register(obj, prio);
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Load the local class equivalent of the specified stream class
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * description.  Subclasses may implement this method to allow classes to
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be fetched from an alternate source.
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>The corresponding method in <code>ObjectOutputStream</code> is
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>annotateClass</code>.  This method will be invoked only once for
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * each unique class in the stream.  This method can be implemented by
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * subclasses to use an alternate loading mechanism but must return a
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>Class</code> object. Once returned, if the class is not an array
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class, its serialVersionUID is compared to the serialVersionUID of the
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * serialized class, and if there is a mismatch, the deserialization fails
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and an {@link InvalidClassException} is thrown.
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>The default implementation of this method in
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ObjectInputStream</code> returns the result of calling
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <pre>
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     Class.forName(desc.getName(), false, loader)
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre>
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * where <code>loader</code> is determined as follows: if there is a
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method on the current thread's stack whose declaring class was
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * defined by a user-defined class loader (and was not a generated to
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * implement reflective invocations), then <code>loader</code> is class
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * loader corresponding to the closest such method to the currently
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * executing frame; otherwise, <code>loader</code> is
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>null</code>. If this call results in a
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ClassNotFoundException</code> and the name of the passed
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ObjectStreamClass</code> instance is the Java language keyword
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for a primitive type or void, then the <code>Class</code> object
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * representing that primitive type or void will be returned
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (e.g., an <code>ObjectStreamClass</code> with the name
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the caller of this method.
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   desc an instance of class <code>ObjectStreamClass</code>
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a <code>Class</code> object corresponding to <code>desc</code>
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException any of the usual Input/Output exceptions.
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException if class of a serialized object cannot
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          be found.
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Class<?> resolveClass(ObjectStreamClass desc)
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String name = desc.getName();
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Class.forName(name, false, latestUserDefinedLoader());
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (ClassNotFoundException ex) {
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Class<?> cl = primClasses.get(name);
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (cl != null) {
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return cl;
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw ex;
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a proxy class that implements the interfaces named in a proxy
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class descriptor; subclasses may implement this method to read custom
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * data from the stream along with the descriptors for dynamic proxy
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * classes, allowing them to use an alternate loading mechanism for the
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * interfaces and the proxy class.
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>This method is called exactly once for each unique proxy class
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * descriptor in the stream.
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>The corresponding method in <code>ObjectOutputStream</code> is
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>annotateProxyClass</code>.  For a given subclass of
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ObjectInputStream</code> that overrides this method, the
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>annotateProxyClass</code> method in the corresponding subclass of
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ObjectOutputStream</code> must write any data or objects read by
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this method.
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>The default implementation of this method in
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>ObjectInputStream</code> returns the result of calling
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * objects for the interfaces that are named in the <code>interfaces</code>
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parameter.  The <code>Class</code> object for each interface name
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>i</code> is the value returned by calling
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <pre>
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     Class.forName(i, false, loader)
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre>
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * where <code>loader</code> is that of the first non-<code>null</code>
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class loader up the execution stack, or <code>null</code> if no
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * non-<code>null</code> class loaders are on the stack (the same class
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * loader choice used by the <code>resolveClass</code> method).  Unless any
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of the resolved interfaces are non-public, this same value of
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>loader</code> is also the class loader passed to
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * their class loader is passed instead (if more than one non-public
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * interface class loader is encountered, an
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>IllegalAccessError</code> is thrown).
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If <code>Proxy.getProxyClass</code> throws an
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will throw a <code>ClassNotFoundException</code> containing the
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>IllegalArgumentException</code>.
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param interfaces the list of interface names that were
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                deserialized in the proxy class descriptor
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a proxy class for the specified interfaces
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws        IOException any exception thrown by the underlying
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                <code>InputStream</code>
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws        ClassNotFoundException if the proxy class or any of the
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                named interfaces could not be found
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see ObjectOutputStream#annotateProxyClass(Class)
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Class<?> resolveProxyClass(String[] interfaces)
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader latestLoader = latestUserDefinedLoader();
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader nonPublicLoader = null;
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean hasNonPublicInterface = false;
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // define proxy in class loader of non-public interface(s), if any
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class[] classObjs = new Class[interfaces.length];
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < interfaces.length; i++) {
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Class cl = Class.forName(interfaces[i], false, latestLoader);
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (hasNonPublicInterface) {
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (nonPublicLoader != cl.getClassLoader()) {
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IllegalAccessError(
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            "conflicting non-public interface class loaders");
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    nonPublicLoader = cl.getClassLoader();
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    hasNonPublicInterface = true;
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            classObjs[i] = cl;
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Proxy.getProxyClass(
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                hasNonPublicInterface ? nonPublicLoader : latestLoader,
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                classObjs);
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IllegalArgumentException e) {
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new ClassNotFoundException(null, e);
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method will allow trusted subclasses of ObjectInputStream to
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * substitute one object for another during deserialization. Replacing
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * objects is disabled until enableResolveObject is called. The
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * enableResolveObject method checks that the stream requesting to resolve
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object can be trusted. Every reference to serializable objects is passed
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to resolveObject.  To insure that the private state of objects is not
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unintentionally exposed only trusted streams may use resolveObject.
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>This method is called after an object has been read but before it is
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returned from readObject.  The default resolveObject method just returns
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the same object.
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>When a subclass is replacing objects it must insure that the
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * substituted object is compatible with every field where the reference
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will be stored.  Objects whose type is not a subclass of the type of the
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * field or array element abort the serialization by raising an exception
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and the object is not be stored.
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>This method is called only once when each object is first
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * encountered.  All subsequent references to the object will be redirected
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to the new object.
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   obj object to be substituted
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the substituted object
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException Any of the usual Input/Output exceptions.
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected Object resolveObject(Object obj) throws IOException {
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return obj;
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Enable the stream to allow objects read from the stream to be replaced.
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * When enabled, the resolveObject method is called for every object being
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * deserialized.
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>If <i>enable</i> is true, and there is a security manager installed,
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this method first calls the security manager's
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>checkPermission</code> method with the
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>SerializablePermission("enableSubstitution")</code> permission to
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ensure it's ok to enable the stream to allow objects read from the
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stream to be replaced.
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   enable true for enabling use of <code>resolveObject</code> for
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          every object being deserialized
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the previous setting before this method was invoked
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  SecurityException if a security manager exists and its
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <code>checkPermission</code> method denies enabling the stream
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          to allow objects read from the stream to be replaced.
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see SecurityManager#checkPermission
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.io.SerializablePermission
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean enableResolveObject(boolean enable)
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws SecurityException
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (enable == enableResolve) {
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return enable;
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (enable) {
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SecurityManager sm = System.getSecurityManager();
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (sm != null) {
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sm.checkPermission(SUBSTITUTION_PERMISSION);
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        enableResolve = enable;
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return !enableResolve;
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The readStreamHeader method is provided to allow subclasses to read and
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * verify their own stream headers. It reads and verifies the magic number
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and version number.
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if there are I/O errors while reading from the
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          underlying <code>InputStream</code>
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  StreamCorruptedException if control information in the stream
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          is inconsistent
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void readStreamHeader()
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, StreamCorruptedException
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        short s0 = bin.readShort();
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        short s1 = bin.readShort();
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new StreamCorruptedException(
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String.format("invalid stream header: %04X%04X", s0, s1));
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Read a class descriptor from the serialization stream.  This method is
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called when the ObjectInputStream expects a class descriptor as the next
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * item in the serialization stream.  Subclasses of ObjectInputStream may
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * override this method to read in class descriptors that have been written
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in non-standard formats (by subclasses of ObjectOutputStream which have
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * overridden the <code>writeClassDescriptor</code> method).  By default,
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this method reads class descriptors according to the format defined in
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the Object Serialization specification.
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the class descriptor read
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If an I/O error has occurred.
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  ClassNotFoundException If the Class of a serialized object used
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          in the class descriptor representation cannot be found
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected ObjectStreamClass readClassDescriptor()
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ClassNotFoundException
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = new ObjectStreamClass();
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        desc.readNonProxy(this);
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return desc;
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a byte of data. This method will block if no input is available.
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the byte read, or -1 if the end of the stream is reached.
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If an I/O error has occurred.
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int read() throws IOException {
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.read();
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads into an array of bytes.  This method will block until some input
84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is available. Consider using java.io.DataInputStream.readFully to read
84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * exactly 'length' bytes.
84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   buf the buffer into which the data is read
85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   off the start offset of the data
85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   len the maximum number of bytes read
85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the actual number of bytes read, -1 is returned when the end of
85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          the stream is reached.
85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If an I/O error has occurred.
85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.io.DataInputStream#readFully(byte[],int,int)
85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int read(byte[] buf, int off, int len) throws IOException {
85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (buf == null) {
86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int endoff = off + len;
86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.read(buf, off, len, false);
86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the number of bytes that can be read without blocking.
87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the number of available bytes.
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if there are I/O errors while reading from the
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          underlying <code>InputStream</code>
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int available() throws IOException {
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.available();
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Closes the input stream. Must be called to release any resources
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with the stream.
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If an I/O error has occurred.
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void close() throws IOException {
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Even if stream already closed, propagate redundant close to
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * underlying stream to stay consistent with previous implementations.
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        closed = true;
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (depth == 0) {
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            clear();
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.close();
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in a boolean.
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the boolean read.
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean readBoolean() throws IOException {
90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readBoolean();
90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads an 8 bit byte.
91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 8 bit byte read.
91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte readByte() throws IOException  {
91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readByte();
91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads an unsigned 8 bit byte.
92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 8 bit byte read.
92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int readUnsignedByte()  throws IOException {
92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readUnsignedByte();
92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 16 bit char.
93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 16 bit char read.
93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public char readChar()  throws IOException {
93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readChar();
94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 16 bit short.
94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 16 bit short read.
94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public short readShort()  throws IOException {
95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readShort();
95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads an unsigned 16 bit short.
95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 16 bit short read.
95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int readUnsignedShort() throws IOException {
96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readUnsignedShort();
96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 32 bit int.
96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 32 bit integer read.
96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int readInt()  throws IOException {
97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readInt();
97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 64 bit long.
97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the read 64 bit long.
97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long readLong()  throws IOException {
98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readLong();
98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 32 bit float.
98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 32 bit float read.
99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public float readFloat() throws IOException {
99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readFloat();
99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a 64 bit double.
99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the 64 bit double read.
100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public double readDouble() throws IOException {
100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readDouble();
100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads bytes, blocking until all bytes are read.
101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   buf the buffer into which the data is read
101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void readFully(byte[] buf) throws IOException {
101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.readFully(buf, 0, buf.length, false);
101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads bytes, blocking until all bytes are read.
102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   buf the buffer into which the data is read
102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   off the start offset of the data
102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   len the maximum number of bytes to read
102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  EOFException If end of file is reached.
102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If other I/O error has occurred.
102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void readFully(byte[] buf, int off, int len) throws IOException {
102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int endoff = off + len;
103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.readFully(buf, off, len, false);
103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Skips bytes.
103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   len the number of bytes to be skipped
104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the actual number of bytes skipped.
104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException If an I/O error has occurred.
104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int skipBytes(int len) throws IOException {
104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.skipBytes(len);
104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a String copy of the line.
105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if there are I/O errors while reading from the
105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          underlying <code>InputStream</code>
105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @deprecated This method does not properly convert bytes to characters.
105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          see DataInputStream for the details and alternatives.
105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Deprecated
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String readLine() throws IOException {
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readLine();
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a String in
106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * format.
106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the String.
106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  IOException if there are I/O errors while reading from the
106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          underlying <code>InputStream</code>
106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws  UTFDataFormatException if read bytes do not represent a valid
107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          modified UTF-8 encoding of a string
107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String readUTF() throws IOException {
107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return bin.readUTF();
107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Provide access to the persistent fields read from the input stream.
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static abstract class GetField {
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the ObjectStreamClass that describes the fields in the stream.
108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return  the descriptor class that describes the serializable fields
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract ObjectStreamClass getObjectStreamClass();
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Return true if the named field is defaulted and has no value in this
109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * stream.
109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return true, if and only if the named field is defaulted
109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from
109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         the underlying <code>InputStream</code>
109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if <code>name</code> does not
109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         correspond to a serializable field
109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract boolean defaulted(String name) throws IOException;
110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named boolean field from the persistent field.
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>boolean</code> field
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract boolean get(String name, boolean val)
111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws IOException;
111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named byte field from the persistent field.
111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>byte</code> field
112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract byte get(String name, byte val) throws IOException;
112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named char field from the persistent field.
113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>char</code> field
113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract char get(String name, char val) throws IOException;
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named short field from the persistent field.
114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>short</code> field
115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract short get(String name, short val) throws IOException;
115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named int field from the persistent field.
116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>int</code> field
116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract int get(String name, int val) throws IOException;
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named long field from the persistent field.
117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>long</code> field
117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract long get(String name, long val) throws IOException;
118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named float field from the persistent field.
118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>float</code> field
119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract float get(String name, float val) throws IOException;
119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named double field from the persistent field.
120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>double</code> field
120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract double get(String name, double val) throws IOException;
121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Get the value of the named Object field from the persistent field.
121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *
121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  name the name of the field
121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @param  val the default value to use if <code>name</code> does not
121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         have a value
122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @return the value of the named <code>Object</code> field
122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IOException if there are I/O errors while reading from the
122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         underlying <code>InputStream</code>
122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * @throws IllegalArgumentException if type of <code>name</code> is
122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *         not serializable or if the field type is incorrect
122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract Object get(String name, Object val) throws IOException;
122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Verifies that this (possibly subclass) instance can be constructed
123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * without violating security constraints: the subclass must not override
123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * security-sensitive non-final methods, or else the
123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * "enableSubclassImplementation" SerializablePermission is checked.
123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void verifySubclass() {
123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = getClass();
123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cl == ObjectInputStream.class) {
123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SecurityManager sm = System.getSecurityManager();
124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sm == null) {
124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Boolean result = Caches.subclassAudits.get(key);
124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (result == null) {
124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result = Boolean.valueOf(auditSubclass(cl));
124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Caches.subclassAudits.putIfAbsent(key, result);
125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (result.booleanValue()) {
125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Performs reflective checks on given subclass to verify that it doesn't
125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * override security-sensitive non-final methods.  Returns true if subclass
126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is "safe", false otherwise.
126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static boolean auditSubclass(final Class<?> subcl) {
126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Boolean result = AccessController.doPrivileged(
126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            new PrivilegedAction<Boolean>() {
126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                public Boolean run() {
126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for (Class<?> cl = subcl;
126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         cl != ObjectInputStream.class;
126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         cl = cl.getSuperclass())
126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    {
127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        try {
127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            cl.getDeclaredMethod(
127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                "readUnshared", (Class[]) null);
127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return Boolean.FALSE;
127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } catch (NoSuchMethodException ex) {
127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        try {
127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            cl.getDeclaredMethod("readFields", (Class[]) null);
127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return Boolean.FALSE;
127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } catch (NoSuchMethodException ex) {
128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return Boolean.TRUE;
128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        );
128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return result.booleanValue();
128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Clears internal data structures.
129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void clear() {
129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.clear();
129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vlist.clear();
129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Underlying readObject implementation.
129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readObject0(boolean unshared) throws IOException {
130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean oldMode = bin.getBlockDataMode();
130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (oldMode) {
130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int remain = bin.currentBlockRemaining();
130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (remain > 0) {
130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new OptionalDataException(remain);
130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (defaultDataEnd) {
130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /*
130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * Fix for 4360508: stream is currently at the end of a field
130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * value block written via default serialization; since there
131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * is no terminating TC_ENDBLOCKDATA tag, simulate
131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * end-of-custom-data behavior explicitly.
131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new OptionalDataException(true);
131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bin.setBlockDataMode(false);
131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte tc;
131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while ((tc = bin.peekByte()) == TC_RESET) {
132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bin.readByte();
132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handleReset();
132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        depth++;
132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (tc) {
132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_NULL:
132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return readNull();
132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_REFERENCE:
133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return readHandle(unshared);
133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_CLASS:
133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return readClass(unshared);
133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_CLASSDESC:
133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_PROXYCLASSDESC:
133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return readClassDesc(unshared);
133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_STRING:
134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_LONGSTRING:
134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return checkResolve(readString(unshared));
134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_ARRAY:
134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return checkResolve(readArray(unshared));
134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_ENUM:
134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return checkResolve(readEnum(unshared));
134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_OBJECT:
135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return checkResolve(readOrdinaryObject(unshared));
135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_EXCEPTION:
135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    IOException ex = readFatalException();
135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new WriteAbortedException("writing aborted", ex);
135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_BLOCKDATA:
135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_BLOCKDATALONG:
135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (oldMode) {
136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        bin.setBlockDataMode(true);
136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        bin.peek();             // force header read
136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new OptionalDataException(
136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            bin.currentBlockRemaining());
136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new StreamCorruptedException(
136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            "unexpected block data");
136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_ENDBLOCKDATA:
137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (oldMode) {
137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new OptionalDataException(true);
137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new StreamCorruptedException(
137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            "unexpected end of block data");
137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new StreamCorruptedException(
137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        String.format("invalid type code: %02X", tc));
138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            depth--;
138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bin.setBlockDataMode(oldMode);
138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If resolveObject has been enabled and given object does not have an
138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * exception associated with it, calls resolveObject to determine
139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * replacement for object, and updates handle table accordingly.  Returns
139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * replacement object, or echoes provided object if no replacement
139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * occurred.  Expects that passHandle is set to given object's handle prior
139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to calling this method.
139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object checkResolve(Object obj) throws IOException {
139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!enableResolve || handles.lookupException(passHandle) != null) {
139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return obj;
139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object rep = resolveObject(obj);
140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (rep != obj) {
140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.setObject(passHandle, rep);
140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return rep;
140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads string without allowing it to be replaced in stream.  Called from
140851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * within ObjectStreamClass.read().
140951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
141051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    String readTypeString() throws IOException {
141151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int oldHandle = passHandle;
141251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
141351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte tc = bin.peekByte();
141451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (tc) {
141551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_NULL:
141651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return (String) readNull();
141751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
141851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_REFERENCE:
141951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return (String) readHandle(false);
142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_STRING:
142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_LONGSTRING:
142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return readString(false);
142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new StreamCorruptedException(
142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        String.format("invalid type code: %02X", tc));
142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            passHandle = oldHandle;
143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readNull() throws IOException {
143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_NULL) {
143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = NULL_HANDLE;
144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in object handle, sets passHandle to the read handle, and returns
144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object associated with the handle.
144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readHandle(boolean unshared) throws IOException {
145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_REFERENCE) {
145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = bin.readInt() - baseWireHandle;
145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (passHandle < 0 || passHandle >= handles.size()) {
145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new StreamCorruptedException(
145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String.format("invalid handle value: %08X", passHandle +
145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                baseWireHandle));
145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (unshared) {
146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // REMIND: what type of exception to throw here?
146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InvalidObjectException(
146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "cannot read back reference as unshared");
146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object obj = handles.lookupObject(passHandle);
146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (obj == unsharedMarker) {
146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // REMIND: what type of exception to throw here?
146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InvalidObjectException(
146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "cannot read back reference to unshared object");
147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return obj;
147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns class object.  Sets passHandle to class object's
147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * assigned handle.  Returns null if class is unresolvable (in which case a
147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ClassNotFoundException will be associated with the class' handle in the
147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * handle table).
147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Class readClass(boolean unshared) throws IOException {
148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_CLASS) {
148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = readClassDesc(false);
148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = desc.forClass();
148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = handles.assign(unshared ? unsharedMarker : cl);
148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = desc.getResolveException();
148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (resolveEx != null) {
149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markException(passHandle, resolveEx);
149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(passHandle);
149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cl;
149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns (possibly null) class descriptor.  Sets passHandle
149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to class descriptor's assigned handle.  If class descriptor cannot be
150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * resolved to a class in the local VM, a ClassNotFoundException is
150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with the class descriptor's handle.
150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ObjectStreamClass readClassDesc(boolean unshared)
150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte tc = bin.peekByte();
150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (tc) {
150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_NULL:
150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (ObjectStreamClass) readNull();
151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_REFERENCE:
151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (ObjectStreamClass) readHandle(unshared);
151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_PROXYCLASSDESC:
151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return readProxyDesc(unshared);
151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_CLASSDESC:
151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return readNonProxyDesc(unshared);
151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new StreamCorruptedException(
152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String.format("invalid type code: %02X", tc));
152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isCustomSubclass() {
152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Return true if this class is a custom subclass of ObjectInputStream
152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getClass().getClassLoader()
152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    != ObjectInputStream.class.getClassLoader();
153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns class descriptor for a dynamic proxy class.  Sets
153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * passHandle to proxy class descriptor's assigned handle.  If proxy class
153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * descriptor cannot be resolved to a class in the local VM, a
153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ClassNotFoundException is associated with the descriptor's handle.
153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ObjectStreamClass readProxyDesc(boolean unshared)
153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_PROXYCLASSDESC) {
154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
154351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
154451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
154551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = new ObjectStreamClass();
154651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
154751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = NULL_HANDLE;
154851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
154951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int numIfaces = bin.readInt();
155051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String[] ifaces = new String[numIfaces];
155151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < numIfaces; i++) {
155251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ifaces[i] = bin.readUTF();
155351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
155451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
155551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = null;
155651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = null;
155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(true);
155851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((cl = resolveProxyClass(ifaces)) == null) {
156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                resolveEx = new ClassNotFoundException("null class");
156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (!Proxy.isProxyClass(cl)) {
156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new InvalidClassException("Not a proxy");
156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // ReflectUtil.checkProxyPackageAccess makes a test
156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // equivalent to isCustomSubclass so there's no need
156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // to condition this call to isCustomSubclass == true here.
156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ReflectUtil.checkProxyPackageAccess(
156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        getClass().getClassLoader(),
156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        cl.getInterfaces());
157051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
157151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (ClassNotFoundException ex) {
157251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            resolveEx = ex;
157351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
157451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        skipCustomData();
157551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
157651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        desc.initProxy(cl, resolveEx, readClassDesc(false));
157751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
157851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(descHandle);
157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = descHandle;
158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return desc;
158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns class descriptor for a class that is not a dynamic
158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class descriptor cannot be resolved to a class in the local VM, a
158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ClassNotFoundException is associated with the descriptor's handle.
158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ObjectStreamClass readNonProxyDesc(boolean unshared)
159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_CLASSDESC) {
159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = new ObjectStreamClass();
159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = NULL_HANDLE;
159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass readDesc = null;
160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readDesc = readClassDescriptor();
160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (ClassNotFoundException ex) {
160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw (IOException) new InvalidClassException(
160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "failed to read class descriptor").initCause(ex);
160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = null;
160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = null;
161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.setBlockDataMode(true);
161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final boolean checksRequired = isCustomSubclass();
161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((cl = resolveClass(readDesc)) == null) {
161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                resolveEx = new ClassNotFoundException("null class");
161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (checksRequired) {
161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ReflectUtil.checkPackageAccess(cl);
161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (ClassNotFoundException ex) {
161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            resolveEx = ex;
162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        skipCustomData();
162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(descHandle);
162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = descHandle;
162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return desc;
162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns new string.  Sets passHandle to new string's
163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * assigned handle.
163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String readString(boolean unshared) throws IOException {
163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String str;
163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte tc = bin.readByte();
163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (tc) {
163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_STRING:
163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                str = bin.readUTF();
164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TC_LONGSTRING:
164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                str = bin.readLongUTF();
164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new StreamCorruptedException(
164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String.format("invalid type code: %02X", tc));
164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = handles.assign(unshared ? unsharedMarker : str);
165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(passHandle);
165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return str;
165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns array object, or null if array class is
165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unresolvable.  Sets passHandle to array's assigned handle.
165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readArray(boolean unshared) throws IOException {
166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_ARRAY) {
166151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = readClassDesc(false);
166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = bin.readInt();
166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object array = null;
166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl, ccl = null;
166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((cl = desc.forClass()) != null) {
167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ccl = cl.getComponentType();
167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            array = Array.newInstance(ccl, len);
167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = desc.getResolveException();
167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (resolveEx != null) {
167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markException(arrayHandle, resolveEx);
167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ccl == null) {
168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < len; i++) {
168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                readObject0(false);
168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (ccl.isPrimitive()) {
168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ccl == Integer.TYPE) {
168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readInts((int[]) array, 0, len);
168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Byte.TYPE) {
168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readFully((byte[]) array, 0, len, true);
168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Long.TYPE) {
169051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readLongs((long[]) array, 0, len);
169151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Float.TYPE) {
169251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readFloats((float[]) array, 0, len);
169351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Double.TYPE) {
169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readDoubles((double[]) array, 0, len);
169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Short.TYPE) {
169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readShorts((short[]) array, 0, len);
169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Character.TYPE) {
169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readChars((char[]) array, 0, len);
169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (ccl == Boolean.TYPE) {
170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.readBooleans((boolean[]) array, 0, len);
170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new InternalError();
170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object[] oa = (Object[]) array;
170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < len; i++) {
170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                oa[i] = readObject0(false);
170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handles.markDependency(arrayHandle, passHandle);
170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
171051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
171151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
171251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(arrayHandle);
171351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = arrayHandle;
171451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return array;
171551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
171651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
171751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
171851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns enum constant, or null if enum type is
171951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unresolvable.  Sets passHandle to enum constant's assigned handle.
172051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Enum readEnum(boolean unshared) throws IOException {
172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_ENUM) {
172351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
172451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = readClassDesc(false);
172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!desc.isEnum()) {
172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InvalidClassException("non-enum class: " + desc);
172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int enumHandle = handles.assign(unshared ? unsharedMarker : null);
173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = desc.getResolveException();
173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (resolveEx != null) {
173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markException(enumHandle, resolveEx);
173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String name = readString(false);
173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Enum en = null;
173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = desc.forClass();
174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cl != null) {
174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                en = Enum.valueOf(cl, name);
174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IllegalArgumentException ex) {
174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw (IOException) new InvalidObjectException(
174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "enum constant " + name + " does not exist in " +
174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    cl).initCause(ex);
174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
174851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!unshared) {
174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handles.setObject(enumHandle, en);
175051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
175151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(enumHandle);
175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = enumHandle;
175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return en;
175651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads and returns "ordinary" (i.e., not a String, Class,
176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ObjectStreamClass, array, or enum constant) object, or null if object's
176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class is unresolvable (in which case a ClassNotFoundException will be
176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with object's handle).  Sets passHandle to object's assigned
176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * handle.
176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Object readOrdinaryObject(boolean unshared)
176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_OBJECT) {
176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
177051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
177151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass desc = readClassDesc(false);
177351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        desc.checkDeserialize();
177451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class<?> cl = desc.forClass();
177651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cl == String.class || cl == Class.class
177751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                || cl == ObjectStreamClass.class) {
177851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InvalidClassException("invalid class descriptor");
177951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
178051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
178151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object obj;
178251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
178351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            obj = desc.isInstantiable() ? desc.newInstance() : null;
178451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception ex) {
178551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw (IOException) new InvalidClassException(
178651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                desc.forClass().getName(),
178751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "unable to create instance").initCause(ex);
178851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
178951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
179051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = handles.assign(unshared ? unsharedMarker : obj);
179151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException resolveEx = desc.getResolveException();
179251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (resolveEx != null) {
179351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.markException(passHandle, resolveEx);
179451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
179551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
179651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (desc.isExternalizable()) {
179751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readExternalData((Externalizable) obj, desc);
179851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
179951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readSerialData(obj, desc);
180051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
180151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
180251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        handles.finish(passHandle);
180351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
180451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (obj != null &&
180551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handles.lookupException(passHandle) == null &&
180651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            desc.hasReadResolveMethod())
180751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
180851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object rep = desc.invokeReadResolve(obj);
180951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (unshared && rep.getClass().isArray()) {
181051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                rep = cloneArray(rep);
181151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
181251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (rep != obj) {
181351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handles.setObject(passHandle, obj = rep);
181451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
181551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
181651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
181751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return obj;
181851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
181951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
182051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
182151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If obj is non-null, reads externalizable data by invoking readExternal()
182251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method of obj; otherwise, attempts to skip over externalizable data.
182351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Expects that passHandle is set to obj's handle before this method is
182451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called.
182551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
182651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void readExternalData(Externalizable obj, ObjectStreamClass desc)
182751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
182851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
182951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SerialCallbackContext oldContext = curContext;
183051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        curContext = null;
183151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
183251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean blocked = desc.hasBlockExternalData();
183351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blocked) {
183451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.setBlockDataMode(true);
183551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
183651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (obj != null) {
183751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
183851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    obj.readExternal(this);
183951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (ClassNotFoundException ex) {
184051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    /*
184151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * In most cases, the handle table has already propagated
184251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * a CNFException to passHandle at this point; this mark
184351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * call is included to address cases where the readExternal
184451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * method has cons'ed and thrown a new CNFException of its
184551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * own.
184651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     */
184751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     handles.markException(passHandle, ex);
184851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
184951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
185051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blocked) {
185151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                skipCustomData();
185251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
185351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
185451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            curContext = oldContext;
185551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
185651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
185751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * At this point, if the externalizable data was not written in
185851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * block-data form and either the externalizable class doesn't exist
185951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * locally (i.e., obj == null) or readExternal() just threw a
186051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * CNFException, then the stream is probably in an inconsistent state,
186151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * since some (or all) of the externalizable data may not have been
186251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * consumed.  Since there's no "correct" action to take in this case,
186351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * we mimic the behavior of past serialization implementations and
186451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * blindly hope that the stream is in sync; if it isn't and additional
186551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * externalizable data remains in the stream, a subsequent read will
186651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * most likely throw a StreamCorruptedException.
186751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
186851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
186951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
187051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
187151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads (or attempts to skip, if obj is null or is tagged with a
187251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ClassNotFoundException) instance data for each serializable class of
187351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * object in stream, from superclass to subclass.  Expects that passHandle
187451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is set to obj's handle before this method is called.
187551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
187651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void readSerialData(Object obj, ObjectStreamClass desc)
187751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
187851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
187951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
188051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < slots.length; i++) {
188151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ObjectStreamClass slotDesc = slots[i].desc;
188251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
188351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (slots[i].hasData) {
188451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (obj != null &&
188551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    slotDesc.hasReadObjectMethod() &&
188651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handles.lookupException(passHandle) == null)
188751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                {
188851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SerialCallbackContext oldContext = curContext;
188951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
189051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    try {
189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        curContext = new SerialCallbackContext(obj, slotDesc);
189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        bin.setBlockDataMode(true);
189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        slotDesc.invokeReadObject(obj, this);
189551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } catch (ClassNotFoundException ex) {
189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        /*
189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * In most cases, the handle table has already
189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * propagated a CNFException to passHandle at this
189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * point; this mark call is included to address cases
190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * where the custom readObject method has cons'ed and
190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * thrown a new CNFException of its own.
190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         */
190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        handles.markException(passHandle, ex);
190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } finally {
190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        curContext.setUsed();
190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        curContext = oldContext;
190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    /*
191051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * defaultDataEnd may have been set indirectly by custom
191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * readObject() method when calling defaultReadObject() or
191251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * readFields(); clear it to restore normal read behavior.
191351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     */
191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    defaultDataEnd = false;
191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    defaultReadFields(obj, slotDesc);
191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (slotDesc.hasWriteObjectData()) {
191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    skipCustomData();
192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
192151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bin.setBlockDataMode(false);
192251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
192351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
192451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (obj != null &&
192551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    slotDesc.hasReadObjectNoDataMethod() &&
192651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handles.lookupException(passHandle) == null)
192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                {
192851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    slotDesc.invokeReadObjectNoData(obj);
192951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
193151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
193251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
193351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
193451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
193551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Skips over all block data and objects until TC_ENDBLOCKDATA is
193651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * encountered.
193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
193851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void skipCustomData() throws IOException {
193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int oldHandle = passHandle;
194051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (;;) {
194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (bin.getBlockDataMode()) {
194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.skipBlockData();
194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bin.setBlockDataMode(false);
194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (bin.peekByte()) {
194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_BLOCKDATA:
194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_BLOCKDATALONG:
194851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bin.setBlockDataMode(true);
194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case TC_ENDBLOCKDATA:
195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bin.readByte();
195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    passHandle = oldHandle;
195451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
195551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
195651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
195751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    readObject0(false);
195851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
195951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
196051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
196151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
196251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
196351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
196451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in values of serializable fields declared by given class
196551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
196651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * passHandle is set to obj's handle before this method is called.
196751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
196851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void defaultReadFields(Object obj, ObjectStreamClass desc)
196951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
197051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
197151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // REMIND: is isInstance check necessary?
197251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class cl = desc.forClass();
197351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cl != null && obj != null && !cl.isInstance(obj)) {
197451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new ClassCastException();
197551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
197651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
197751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int primDataSize = desc.getPrimDataSize();
197851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (primVals == null || primVals.length < primDataSize) {
197951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            primVals = new byte[primDataSize];
198051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
198151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bin.readFully(primVals, 0, primDataSize, false);
198251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (obj != null) {
198351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            desc.setPrimFieldValues(obj, primVals);
198451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
198551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
198651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int objHandle = passHandle;
198751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectStreamField[] fields = desc.getFields(false);
198851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object[] objVals = new Object[desc.getNumObjFields()];
198951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int numPrimFields = fields.length - objVals.length;
199051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < objVals.length; i++) {
199151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ObjectStreamField f = fields[numPrimFields + i];
199251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            objVals[i] = readObject0(f.isUnshared());
199351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (f.getField() != null) {
199451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handles.markDependency(objHandle, passHandle);
199551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
199651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
199751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (obj != null) {
199851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            desc.setObjFieldValues(obj, objVals);
199951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
200051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        passHandle = objHandle;
200151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
200251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
200351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
200451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads in and returns IOException that caused serialization to abort.
200551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * All stream state is discarded prior to reading in fatal exception.  Sets
200651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * passHandle to fatal exception's handle.
200751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
200851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private IOException readFatalException() throws IOException {
200951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bin.readByte() != TC_EXCEPTION) {
201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InternalError();
201151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
201251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        clear();
2013c17398294ce7bc00e83cd236109edf95340d33e5Przemyslaw Szczepaniak        IOException e = (IOException) readObject0(false);
2014c17398294ce7bc00e83cd236109edf95340d33e5Przemyslaw Szczepaniak        // ----- BEGIN android -----
2015c17398294ce7bc00e83cd236109edf95340d33e5Przemyslaw Szczepaniak        clear();
2016c17398294ce7bc00e83cd236109edf95340d33e5Przemyslaw Szczepaniak        // ----- END android -----
2017c17398294ce7bc00e83cd236109edf95340d33e5Przemyslaw Szczepaniak        return e;
201851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
201951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
202051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
202151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If recursion depth is 0, clears internal data structures; otherwise,
202251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * throws a StreamCorruptedException.  This method is called when a
202351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TC_RESET typecode is encountered.
202451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
202551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void handleReset() throws StreamCorruptedException {
202651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (depth > 0) {
202751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new StreamCorruptedException(
202851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "unexpected reset; recursion depth: " + depth);
202951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
203051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        clear();
203151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
203251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
203351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
203451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Converts specified span of bytes into float values.
203551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
203651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // REMIND: remove once hotspot inlines Float.intBitsToFloat
203751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static native void bytesToFloats(byte[] src, int srcpos,
203851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             float[] dst, int dstpos,
203951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             int nfloats);
204051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
204151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
204251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Converts specified span of bytes into double values.
204351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
204451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // REMIND: remove once hotspot inlines Double.longBitsToDouble
204551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static native void bytesToDoubles(byte[] src, int srcpos,
204651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                              double[] dst, int dstpos,
204751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                              int ndoubles);
204851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
204951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
205051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the first non-null class loader (not counting class loaders of
205151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * generated reflection implementation classes) up the execution stack, or
205251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * null if only code from the null class loader is on the stack.  This
205351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is also called via reflection by the following RMI-IIOP class:
205451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
205551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     com.sun.corba.se.internal.util.JDKClassLoader
205651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
205751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method should not be removed or its signature changed without
205851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * corresponding modifications to the above class.
205951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
206051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static ClassLoader latestUserDefinedLoader() {
2061419d15f19dcb247d6188bb6954cb55e8c5ddf20aPrzemyslaw Szczepaniak        return VMStack.getClosestUserClassLoader();
206251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
206351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
206451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
206551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Default GetField implementation.
206651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
206751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class GetFieldImpl extends GetField {
206851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
206951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** class descriptor describing serializable fields */
207051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final ObjectStreamClass desc;
207151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** primitive field values */
207251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final byte[] primVals;
207351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** object field values */
207451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final Object[] objVals;
207551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** object field value handles */
207651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final int[] objHandles;
207751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
207851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
207951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Creates GetFieldImpl object for reading fields defined in given
208051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * class descriptor.
208151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
208251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        GetFieldImpl(ObjectStreamClass desc) {
208351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.desc = desc;
208451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            primVals = new byte[desc.getPrimDataSize()];
208551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            objVals = new Object[desc.getNumObjFields()];
208651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            objHandles = new int[objVals.length];
208751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
208851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
208951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public ObjectStreamClass getObjectStreamClass() {
209051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return desc;
209151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
209251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
209351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean defaulted(String name) throws IOException {
209451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (getFieldOffset(name, null) < 0);
209551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
209651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
209751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean get(String name, boolean val) throws IOException {
209851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Boolean.TYPE);
209951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
210051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
210151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
210251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public byte get(String name, byte val) throws IOException {
210351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Byte.TYPE);
210451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? primVals[off] : val;
210551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
210651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
210751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public char get(String name, char val) throws IOException {
210851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Character.TYPE);
210951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getChar(primVals, off) : val;
211051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
211151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
211251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public short get(String name, short val) throws IOException {
211351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Short.TYPE);
211451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getShort(primVals, off) : val;
211551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
211651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
211751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int get(String name, int val) throws IOException {
211851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Integer.TYPE);
211951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getInt(primVals, off) : val;
212051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
212151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
212251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public float get(String name, float val) throws IOException {
212351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Float.TYPE);
212451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getFloat(primVals, off) : val;
212551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
212651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
212751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public long get(String name, long val) throws IOException {
212851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Long.TYPE);
212951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getLong(primVals, off) : val;
213051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
213151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
213251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public double get(String name, double val) throws IOException {
213351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Double.TYPE);
213451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (off >= 0) ? Bits.getDouble(primVals, off) : val;
213551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
213651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
213751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Object get(String name, Object val) throws IOException {
213851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int off = getFieldOffset(name, Object.class);
213951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (off >= 0) {
214051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int objHandle = objHandles[off];
214151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handles.markDependency(passHandle, objHandle);
214251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (handles.lookupException(objHandle) == null) ?
214351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    objVals[off] : null;
214451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
214551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return val;
214651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
214751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
214851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
214951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
215051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Reads primitive and object field values from stream.
215151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
215251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readFields() throws IOException {
215351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bin.readFully(primVals, 0, primVals.length, false);
215451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
215551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int oldHandle = passHandle;
215651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ObjectStreamField[] fields = desc.getFields(false);
215751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int numPrimFields = fields.length - objVals.length;
215851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < objVals.length; i++) {
215951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                objVals[i] =
216051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    readObject0(fields[numPrimFields + i].isUnshared());
216151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                objHandles[i] = passHandle;
216251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
216351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            passHandle = oldHandle;
216451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
216551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
216651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
216751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Returns offset of field with given name and type.  A specified type
216851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * of null matches all types, Object.class matches all non-primitive
216951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * types, and any other non-null type matches assignable types only.
217051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * If no matching field is found in the (incoming) class
217151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * descriptor but a matching field is present in the associated local
217251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * class descriptor, returns -1.  Throws IllegalArgumentException if
217351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * neither incoming nor local class descriptor contains a match.
217451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
217551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int getFieldOffset(String name, Class type) {
217651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ObjectStreamField field = desc.getField(name, type);
217751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (field != null) {
217851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return field.getOffset();
217951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (desc.getLocalDesc().getField(name, type) != null) {
218051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
218151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
218251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalArgumentException("no such field " + name +
218351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   " with type " + type);
218451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
218551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
218651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
218751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
218851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
218951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Prioritized list of callbacks to be performed once object graph has been
219051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * completely deserialized.
219151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
219251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class ValidationList {
219351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
219451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static class Callback {
219551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            final ObjectInputValidation obj;
219651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            final int priority;
219751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Callback next;
219851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            final AccessControlContext acc;
219951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
220051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Callback(ObjectInputValidation obj, int priority, Callback next,
220151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                AccessControlContext acc)
220251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
220351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.obj = obj;
220451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.priority = priority;
220551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.next = next;
220651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                this.acc = acc;
220751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
220851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
220951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
221051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** linked list of callbacks */
221151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private Callback list;
221251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
221351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
221451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Creates new (empty) ValidationList.
221551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
221651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ValidationList() {
221751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
221851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
221951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
222051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Registers callback.  Throws InvalidObjectException if callback
222151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * object is null.
222251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
222351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void register(ObjectInputValidation obj, int priority)
222451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws InvalidObjectException
222551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
222651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (obj == null) {
222751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new InvalidObjectException("null callback");
222851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
222951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
223051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Callback prev = null, cur = list;
223151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (cur != null && priority < cur.priority) {
223251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                prev = cur;
223351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cur = cur.next;
223451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
223551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            AccessControlContext acc = AccessController.getContext();
223651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (prev != null) {
223751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                prev.next = new Callback(obj, priority, cur, acc);
223851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
223951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                list = new Callback(obj, priority, list, acc);
224051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
224151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
224251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
224351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
224451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Invokes all registered callbacks and clears the callback list.
224551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Callbacks with higher priorities are called first; those with equal
224651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * priorities may be called in any order.  If any of the callbacks
224751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * throws an InvalidObjectException, the callback process is terminated
224851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * and the exception propagated upwards.
224951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
225051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void doCallbacks() throws InvalidObjectException {
225151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
225251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (list != null) {
225351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    AccessController.doPrivileged(
225451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        new PrivilegedExceptionAction<Void>()
225551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    {
225651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        public Void run() throws InvalidObjectException {
225751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            list.obj.validateObject();
225851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return null;
225951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
226051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }, list.acc);
226151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    list = list.next;
226251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
226351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (PrivilegedActionException ex) {
226451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                list = null;
226551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw (InvalidObjectException) ex.getException();
226651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
226751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
226851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
226951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
227051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Resets the callback list to its initial (empty) state.
227151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
227251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void clear() {
227351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list = null;
227451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
227551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
227651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
227751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
227851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Input stream supporting single-byte peek operations.
227951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
228051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class PeekInputStream extends InputStream {
228151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
228251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** underlying stream */
228351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final InputStream in;
228451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** peeked byte */
228551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int peekb = -1;
228651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
228751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
228851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Creates new PeekInputStream on top of given underlying stream.
228951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
229051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        PeekInputStream(InputStream in) {
229151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.in = in;
229251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
229351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
229451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
229551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Peeks at next byte value in stream.  Similar to read(), except
229651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * that it does not consume the read value.
229751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
229851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int peek() throws IOException {
229951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (peekb >= 0) ? peekb : (peekb = in.read());
230051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
230151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
230251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read() throws IOException {
230351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (peekb >= 0) {
230451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int v = peekb;
230551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                peekb = -1;
230651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return v;
230751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
230851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.read();
230951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
231051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
231151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
231251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read(byte[] b, int off, int len) throws IOException {
231351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (len == 0) {
231451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0;
231551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (peekb < 0) {
231651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.read(b, off, len);
231751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
231851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                b[off++] = (byte) peekb;
231951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                len--;
232051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                peekb = -1;
232151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int n = in.read(b, off, len);
232251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (n >= 0) ? (n + 1) : 1;
232351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
232451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
232551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
232651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readFully(byte[] b, int off, int len) throws IOException {
232751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = 0;
232851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (n < len) {
232951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int count = read(b, off + n, len - n);
233051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (count < 0) {
233151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new EOFException();
233251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
233351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                n += count;
233451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
233551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
233651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
233751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public long skip(long n) throws IOException {
233851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (n <= 0) {
233951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0;
234051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
234151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int skipped = 0;
234251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (peekb >= 0) {
234351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                peekb = -1;
234451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                skipped++;
234551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                n--;
234651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
234751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return skipped + skip(n);
234851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
234951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
235051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int available() throws IOException {
235151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return in.available() + ((peekb >= 0) ? 1 : 0);
235251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
235351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
235451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void close() throws IOException {
235551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in.close();
235651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
235751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
235851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
235951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
236051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Input stream with two modes: in default mode, inputs data written in the
236151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * same format as DataOutputStream; in "block data" mode, inputs data
236251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * bracketed by block data markers (see object serialization specification
236351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for details).  Buffering depends on block data mode: when in default
236451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * mode, no data is buffered in advance; when in block data mode, all data
236551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for the current data block is read in at once (and buffered).
236651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
236751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class BlockDataInputStream
236851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        extends InputStream implements DataInput
236951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
237051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** maximum data block length */
237151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final int MAX_BLOCK_SIZE = 1024;
237251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** maximum data block header length */
237351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final int MAX_HEADER_SIZE = 5;
237451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** (tunable) length of char buffer (for reading strings) */
237551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final int CHAR_BUF_SIZE = 256;
237651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** readBlockHeader() return value indicating header read may block */
237751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final int HEADER_BLOCKED = -2;
237851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
237951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** buffer for reading general/block data */
238051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
238151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** buffer for reading block data headers */
238251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
238351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** char buffer for fast string reads */
238451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final char[] cbuf = new char[CHAR_BUF_SIZE];
238551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
238651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** block data mode */
238751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private boolean blkmode = false;
238851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
238951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // block data state fields; values meaningful only when blkmode true
239051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** current offset into buf */
239151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int pos = 0;
239251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** end offset of valid data in buf, or -1 if no more block data */
239351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int end = -1;
239451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** number of bytes in current block yet to be read from stream */
239551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int unread = 0;
239651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
239751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** underlying stream (wrapped in peekable filter stream) */
239851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final PeekInputStream in;
239951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** loopback stream (for data reads that span data blocks) */
240051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private final DataInputStream din;
240151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
240251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
240351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Creates new BlockDataInputStream on top of given underlying stream.
240451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Block data mode is turned off by default.
240551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
240651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BlockDataInputStream(InputStream in) {
240751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.in = new PeekInputStream(in);
240851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            din = new DataInputStream(this);
240951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
241051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
241151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
241251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Sets block data mode to the given mode (true == on, false == off)
241351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * and returns the previous mode value.  If the new mode is the same as
241451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the old mode, no action is taken.  Throws IllegalStateException if
241551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * block data mode is being switched from on to off while unconsumed
241651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * block data is still present in the stream.
241751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
241851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean setBlockDataMode(boolean newmode) throws IOException {
241951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode == newmode) {
242051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return blkmode;
242151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
242251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (newmode) {
242351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
242451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = 0;
242551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                unread = 0;
242651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (pos < end) {
242751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalStateException("unread block data");
242851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
242951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            blkmode = newmode;
243051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return !blkmode;
243151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
243251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
243351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
243451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Returns true if the stream is currently in block data mode, false
243551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * otherwise.
243651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
243751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean getBlockDataMode() {
243851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return blkmode;
243951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
244051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
244151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
244251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * If in block data mode, skips to the end of the current group of data
244351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * blocks (but does not unset block data mode).  If not in block data
244451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * mode, throws an IllegalStateException.
244551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
244651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void skipBlockData() throws IOException {
244751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
244851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalStateException("not in block data mode");
244951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
245051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (end >= 0) {
245151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                refill();
245251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
245351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
245451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
245551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
245651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Attempts to read in the next block data header (if any).  If
245751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * canBlock is false and a full header cannot be read without possibly
245851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * blocking, returns HEADER_BLOCKED, else if the next element in the
245951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * stream is a block data header, returns the block data length
246051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * specified by the header, else returns -1.
246151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
246251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int readBlockHeader(boolean canBlock) throws IOException {
246351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (defaultDataEnd) {
246451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /*
246551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * Fix for 4360508: stream is currently at the end of a field
246651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * value block written via default serialization; since there
246751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * is no terminating TC_ENDBLOCKDATA tag, simulate
246851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * end-of-custom-data behavior explicitly.
246951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
247051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
247151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
247251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
247351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (;;) {
247451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int avail = canBlock ? Integer.MAX_VALUE : in.available();
247551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (avail == 0) {
247651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return HEADER_BLOCKED;
247751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
247851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
247951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int tc = in.peek();
248051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    switch (tc) {
248151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case TC_BLOCKDATA:
248251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (avail < 2) {
248351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                return HEADER_BLOCKED;
248451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
248551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            in.readFully(hbuf, 0, 2);
248651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return hbuf[1] & 0xFF;
248751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
248851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case TC_BLOCKDATALONG:
248951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (avail < 5) {
249051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                return HEADER_BLOCKED;
249151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
249251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            in.readFully(hbuf, 0, 5);
249351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            int len = Bits.getInt(hbuf, 1);
249451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (len < 0) {
249551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new StreamCorruptedException(
249651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    "illegal block data header length: " +
249751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    len);
249851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
249951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return len;
250051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
250151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        /*
250251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * TC_RESETs may occur in between data blocks.
250351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * Unfortunately, this case must be parsed at a lower
250451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * level than other typecodes, since primitive data
250551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         * reads may span data blocks separated by a TC_RESET.
250651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         */
250751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case TC_RESET:
250851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            in.read();
250951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            handleReset();
251051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
251151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
251251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        default:
251351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
251451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new StreamCorruptedException(
251551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    String.format("invalid type code: %02X",
251651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    tc));
251751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
251851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return -1;
251951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
252051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
252151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (EOFException ex) {
252251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new StreamCorruptedException(
252351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "unexpected EOF while reading block data header");
252451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
252551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
252651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
252751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
252851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Refills internal buffer buf with block data.  Any data in buf at the
252951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * time of the call is considered consumed.  Sets the pos, end, and
253051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * unread fields to reflect the new amount of available block data; if
253151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the next element in the stream is not a data block, sets pos and
253251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * unread to 0 and end to -1.
253351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
253451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private void refill() throws IOException {
253551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
253651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                do {
253751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
253851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (unread > 0) {
253951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        int n =
254051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
254151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (n >= 0) {
254251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            end = n;
254351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            unread -= n;
254451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
254551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            throw new StreamCorruptedException(
254651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                "unexpected EOF in middle of data block");
254751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
254851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
254951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        int n = readBlockHeader(true);
255051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (n >= 0) {
255151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            end = 0;
255251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            unread = n;
255351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
255451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            end = -1;
255551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            unread = 0;
255651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
255751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
255851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } while (pos == end);
255951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException ex) {
256051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
256151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = -1;
256251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                unread = 0;
256351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw ex;
256451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
256551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
256651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
256751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
256851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * If in block data mode, returns the number of unconsumed bytes
256951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * remaining in the current data block.  If not in block data mode,
257051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * throws an IllegalStateException.
257151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
257251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int currentBlockRemaining() {
257351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode) {
257451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (end >= 0) ? (end - pos) + unread : 0;
257551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
257651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalStateException();
257751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
257851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
257951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
258051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
258151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Peeks at (but does not consume) and returns the next byte value in
258251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the stream, or -1 if the end of the stream/block data (if in block
258351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * data mode) has been reached.
258451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
258551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int peek() throws IOException {
258651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode) {
258751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (pos == end) {
258851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    refill();
258951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
259051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (end >= 0) ? (buf[pos] & 0xFF) : -1;
259151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
259251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.peek();
259351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
259451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
259551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
259651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
259751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Peeks at (but does not consume) and returns the next byte value in
259851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the stream, or throws EOFException if end of stream/block data has
259951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * been reached.
260051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
260151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte peekByte() throws IOException {
260251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int val = peek();
260351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (val < 0) {
260451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new EOFException();
260551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
260651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (byte) val;
260751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
260851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
260951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
261051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* ----------------- generic input stream methods ------------------ */
261151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
261251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * The following methods are equivalent to their counterparts in
261351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * InputStream, except that they interpret data block boundaries and
261451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * read the requested data from within data blocks when in block data
261551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * mode.
261651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
261751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
261851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read() throws IOException {
261951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode) {
262051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (pos == end) {
262151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    refill();
262251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
262351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
262451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
262551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.read();
262651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
262751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
262851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
262951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int read(byte[] b, int off, int len) throws IOException {
263051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return read(b, off, len, false);
263151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
263251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
263351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public long skip(long len) throws IOException {
263451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long remain = len;
263551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (remain > 0) {
263651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (blkmode) {
263751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (pos == end) {
263851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        refill();
263951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
264051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (end < 0) {
264151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
264251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
264351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int nread = (int) Math.min(remain, end - pos);
264451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    remain -= nread;
264551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos += nread;
264651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
264751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
264851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((nread = in.read(buf, 0, nread)) < 0) {
264951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
265051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
265151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    remain -= nread;
265251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
265351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
265451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return len - remain;
265551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
265651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
265751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int available() throws IOException {
265851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode) {
265951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((pos == end) && (unread == 0)) {
266051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int n;
266151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    while ((n = readBlockHeader(false)) == 0) ;
266251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    switch (n) {
266351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case HEADER_BLOCKED:
266451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
266551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
266651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case -1:
266751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            pos = 0;
266851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            end = -1;
266951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
267051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
267151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        default:
267251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            pos = 0;
267351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            end = 0;
267451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            unread = n;
267551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
267651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
267751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
267851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // avoid unnecessary call to in.available() if possible
267951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int unreadAvail = (unread > 0) ?
268051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Math.min(in.available(), unread) : 0;
268151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (end >= 0) ? (end - pos) + unreadAvail : 0;
268251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
268351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.available();
268451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
268551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
268651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
268751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void close() throws IOException {
268851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (blkmode) {
268951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
269051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = -1;
269151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                unread = 0;
269251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
269351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in.close();
269451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
269551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
269651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
269751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Attempts to read len bytes into byte array b at offset off.  Returns
269851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the number of bytes read, or -1 if the end of stream/block data has
269951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * been reached.  If copy is true, reads values into an intermediate
270051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * buffer before copying them to b (to avoid exposing a reference to
270151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * b).
270251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
270351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int read(byte[] b, int off, int len, boolean copy) throws IOException {
270451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (len == 0) {
270551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0;
270651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (blkmode) {
270751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (pos == end) {
270851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    refill();
270951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
271051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (end < 0) {
271151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return -1;
271251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
271351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int nread = Math.min(len, end - pos);
271451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                System.arraycopy(buf, pos, b, off, nread);
271551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos += nread;
271651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return nread;
271751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (copy) {
271851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
271951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (nread > 0) {
272051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    System.arraycopy(buf, 0, b, off, nread);
272151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
272251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return nread;
272351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
272451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return in.read(b, off, len);
272551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
272651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
272751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
272851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* ----------------- primitive data input methods ------------------ */
272951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
273051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * The following methods are equivalent to their counterparts in
273151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * DataInputStream, except that they interpret data block boundaries
273251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * and read the requested data from within data blocks when in block
273351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * data mode.
273451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
273551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
273651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void readFully(byte[] b) throws IOException {
273751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readFully(b, 0, b.length, false);
273851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
273951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
274051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void readFully(byte[] b, int off, int len) throws IOException {
274151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readFully(b, off, len, false);
274251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
274351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
274451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void readFully(byte[] b, int off, int len, boolean copy)
274551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws IOException
274651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
274751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (len > 0) {
274851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int n = read(b, off, len, copy);
274951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (n < 0) {
275051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new EOFException();
275151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
275251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                off += n;
275351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                len -= n;
275451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
275551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
275651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
275751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int skipBytes(int n) throws IOException {
275851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return din.skipBytes(n);
275951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
276051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
276151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean readBoolean() throws IOException {
276251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int v = read();
276351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (v < 0) {
276451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new EOFException();
276551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
276651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (v != 0);
276751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
276851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
276951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public byte readByte() throws IOException {
277051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int v = read();
277151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (v < 0) {
277251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new EOFException();
277351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
277451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (byte) v;
277551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
277651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
277751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int readUnsignedByte() throws IOException {
277851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int v = read();
277951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (v < 0) {
278051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new EOFException();
278151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
278251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
278351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
278451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
278551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public char readChar() throws IOException {
278651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
278751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
278851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 2);
278951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 2) {
279051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readChar();
279151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
279251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            char v = Bits.getChar(buf, pos);
279351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 2;
279451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
279551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
279651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
279751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public short readShort() throws IOException {
279851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
279951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
280051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 2);
280151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 2) {
280251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readShort();
280351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
280451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            short v = Bits.getShort(buf, pos);
280551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 2;
280651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
280751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
280851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
280951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int readUnsignedShort() throws IOException {
281051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
281151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
281251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 2);
281351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 2) {
281451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readUnsignedShort();
281551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
281651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int v = Bits.getShort(buf, pos) & 0xFFFF;
281751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 2;
281851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
281951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
282051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
282151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public int readInt() throws IOException {
282251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
282351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
282451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 4);
282551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 4) {
282651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readInt();
282751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
282851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int v = Bits.getInt(buf, pos);
282951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 4;
283051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
283151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
283251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
283351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public float readFloat() throws IOException {
283451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
283551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
283651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 4);
283751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 4) {
283851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readFloat();
283951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
284051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            float v = Bits.getFloat(buf, pos);
284151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 4;
284251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
284351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
284451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
284551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public long readLong() throws IOException {
284651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
284751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
284851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 8);
284951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 8) {
285051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readLong();
285151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
285251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long v = Bits.getLong(buf, pos);
285351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 8;
285451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
285551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
285651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
285751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public double readDouble() throws IOException {
285851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
285951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos = 0;
286051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.readFully(buf, 0, 8);
286151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (end - pos < 8) {
286251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return din.readDouble();
286351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
286451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            double v = Bits.getDouble(buf, pos);
286551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos += 8;
286651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return v;
286751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
286851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
286951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public String readUTF() throws IOException {
287051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return readUTFBody(readUnsignedShort());
287151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
287251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
287351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public String readLine() throws IOException {
287451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return din.readLine();      // deprecated, not worth optimizing
287551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
287651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
287751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* -------------- primitive data array input methods --------------- */
287851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
287951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * The following methods read in spans of primitive data values.
288051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Though equivalent to calling the corresponding primitive read
288151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * methods repeatedly, these methods are optimized for reading groups
288251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * of primitive data values more efficiently.
288351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
288451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
288551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readBooleans(boolean[] v, int off, int len) throws IOException {
288651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop, endoff = off + len;
288751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
288851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
288951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
289051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span);
289151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = off + span;
289251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
289351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 1) {
289451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readBoolean();
289551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
289651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
289751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = Math.min(endoff, off + end - pos);
289851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
289951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
290051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (off < stop) {
290151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = Bits.getBoolean(buf, pos++);
290251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
290351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
290451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
290551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
290651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readChars(char[] v, int off, int len) throws IOException {
290751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop, endoff = off + len;
290851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
290951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
291051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
291151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 1);
291251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = off + span;
291351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
291451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 2) {
291551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readChar();
291651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
291751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
291851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = Math.min(endoff, off + ((end - pos) >> 1));
291951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
292051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
292151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (off < stop) {
292251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = Bits.getChar(buf, pos);
292351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos += 2;
292451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
292551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
292651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
292751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
292851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readShorts(short[] v, int off, int len) throws IOException {
292951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop, endoff = off + len;
293051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
293151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
293251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
293351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 1);
293451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = off + span;
293551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
293651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 2) {
293751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readShort();
293851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
293951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
294051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = Math.min(endoff, off + ((end - pos) >> 1));
294151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
294251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
294351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (off < stop) {
294451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = Bits.getShort(buf, pos);
294551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos += 2;
294651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
294751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
294851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
294951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
295051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readInts(int[] v, int off, int len) throws IOException {
295151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop, endoff = off + len;
295251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
295351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
295451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
295551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 2);
295651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = off + span;
295751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
295851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 4) {
295951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readInt();
296051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
296151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
296251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = Math.min(endoff, off + ((end - pos) >> 2));
296351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
296451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
296551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (off < stop) {
296651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = Bits.getInt(buf, pos);
296751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos += 4;
296851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
296951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
297051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
297151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
297251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readFloats(float[] v, int off, int len) throws IOException {
297351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int span, endoff = off + len;
297451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
297551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
297651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
297751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 2);
297851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
297951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 4) {
298051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readFloat();
298151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
298251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
298351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    span = Math.min(endoff - off, ((end - pos) >> 2));
298451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
298551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
298651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bytesToFloats(buf, pos, v, off, span);
298751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                off += span;
298851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos += span << 2;
298951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
299051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
299151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
299251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readLongs(long[] v, int off, int len) throws IOException {
299351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop, endoff = off + len;
299451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
299551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
299651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
299751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 3);
299851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = off + span;
299951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
300051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 8) {
300151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readLong();
300251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
300351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
300451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    stop = Math.min(endoff, off + ((end - pos) >> 3));
300551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
300651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
300751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (off < stop) {
300851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = Bits.getLong(buf, pos);
300951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos += 8;
301051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
301151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
301251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
301351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
301451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void readDoubles(double[] v, int off, int len) throws IOException {
301551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int span, endoff = off + len;
301651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (off < endoff) {
301751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!blkmode) {
301851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
301951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    in.readFully(buf, 0, span << 3);
302051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = 0;
302151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (end - pos < 8) {
302251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    v[off++] = din.readDouble();
302351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
302451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
302551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    span = Math.min(endoff - off, ((end - pos) >> 3));
302651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
302751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
302851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bytesToDoubles(buf, pos, v, off, span);
302951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                off += span;
303051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pos += span << 3;
303151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
303251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
303351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
303451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
303551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Reads in string written in "long" UTF format.  "Long" UTF format is
303651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * identical to standard UTF, except that it uses an 8 byte header
303751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * (instead of the standard 2 bytes) to convey the UTF encoding length.
303851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
303951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String readLongUTF() throws IOException {
304051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return readUTFBody(readLong());
304151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
304251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
304351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
304451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Reads in the "body" (i.e., the UTF representation minus the 2-byte
304551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * or 8-byte length header) of a UTF encoding, which occupies the next
304651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * utflen bytes.
304751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
304851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private String readUTFBody(long utflen) throws IOException {
304951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            StringBuilder sbuf = new StringBuilder();
305051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!blkmode) {
305151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = pos = 0;
305251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
305351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
305451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (utflen > 0) {
305551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int avail = end - pos;
305651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (avail >= 3 || (long) avail == utflen) {
305751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    utflen -= readUTFSpan(sbuf, utflen);
305851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
305951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (blkmode) {
306051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // near block boundary, read one byte at a time
306151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        utflen -= readUTFChar(sbuf, utflen);
306251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
306351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // shift and refill buffer manually
306451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (avail > 0) {
306551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            System.arraycopy(buf, pos, buf, 0, avail);
306651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
306751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos = 0;
306851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
306951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        in.readFully(buf, avail, end - avail);
307051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
307151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
307251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
307351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
307451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return sbuf.toString();
307551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
307651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
307751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
307851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Reads span of UTF-encoded characters out of internal buffer
307951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * (starting at offset pos and ending at or before offset end),
308051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * consuming no more than utflen bytes.  Appends read characters to
308151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * sbuf.  Returns the number of bytes consumed.
308251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
308351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private long readUTFSpan(StringBuilder sbuf, long utflen)
308451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws IOException
308551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
308651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int cpos = 0;
308751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int start = pos;
308851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int avail = Math.min(end - pos, CHAR_BUF_SIZE);
308951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // stop short of last char unless all of utf bytes in buffer
309051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
309151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean outOfBounds = false;
309251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
309351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
309451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (pos < stop) {
309551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int b1, b2, b3;
309651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    b1 = buf[pos++] & 0xFF;
309751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    switch (b1 >> 4) {
309851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 0:
309951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 1:
310051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 2:
310151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 3:
310251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 4:
310351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 5:
310451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 6:
310551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 7:   // 1 byte format: 0xxxxxxx
310651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            cbuf[cpos++] = (char) b1;
310751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
310851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
310951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 12:
311051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
311151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            b2 = buf[pos++];
311251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if ((b2 & 0xC0) != 0x80) {
311351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new UTFDataFormatException();
311451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
311551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
311651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   ((b2 & 0x3F) << 0));
311751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
311851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
311951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
312051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            b3 = buf[pos + 1];
312151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            b2 = buf[pos + 0];
312251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            pos += 2;
312351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
312451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new UTFDataFormatException();
312551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
312651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
312751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   ((b2 & 0x3F) << 6) |
312851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   ((b3 & 0x3F) << 0));
312951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
313051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
313151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        default:  // 10xx xxxx, 1111 xxxx
313251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            throw new UTFDataFormatException();
313351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
313451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
313551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (ArrayIndexOutOfBoundsException ex) {
313651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                outOfBounds = true;
313751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
313851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (outOfBounds || (pos - start) > utflen) {
313951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    /*
314051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * Fix for 4450867: if a malformed utf char causes the
314151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * conversion loop to scan past the expected end of the utf
314251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * string, only consume the expected number of utf bytes.
314351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     */
314451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos = start + (int) utflen;
314551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new UTFDataFormatException();
314651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
314751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
314851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
314951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sbuf.append(cbuf, 0, cpos);
315051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return pos - start;
315151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
315251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
315351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
315451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Reads in single UTF-encoded character one byte at a time, appends
315551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * the character to sbuf, and returns the number of bytes consumed.
315651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * This method is used when reading in UTF strings written in block
315751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * data mode to handle UTF-encoded characters which (potentially)
315851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * straddle block-data boundaries.
315951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
316051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private int readUTFChar(StringBuilder sbuf, long utflen)
316151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws IOException
316251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
316351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int b1, b2, b3;
316451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            b1 = readByte() & 0xFF;
316551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (b1 >> 4) {
316651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 0:
316751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 1:
316851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 2:
316951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 3:
317051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 4:
317151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 5:
317251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 6:
317351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 7:     // 1 byte format: 0xxxxxxx
317451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sbuf.append((char) b1);
317551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 1;
317651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
317751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 12:
317851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
317951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (utflen < 2) {
318051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new UTFDataFormatException();
318151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
318251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    b2 = readByte();
318351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((b2 & 0xC0) != 0x80) {
318451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new UTFDataFormatException();
318551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
318651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sbuf.append((char) (((b1 & 0x1F) << 6) |
318751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        ((b2 & 0x3F) << 0)));
318851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 2;
318951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
319051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
319151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (utflen < 3) {
319251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (utflen == 2) {
319351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            readByte();         // consume remaining byte
319451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
319551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new UTFDataFormatException();
319651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
319751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    b2 = readByte();
319851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    b3 = readByte();
319951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
320051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new UTFDataFormatException();
320151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
320251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sbuf.append((char) (((b1 & 0x0F) << 12) |
320351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        ((b2 & 0x3F) << 6) |
320451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        ((b3 & 0x3F) << 0)));
320551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return 3;
320651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
320751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:   // 10xx xxxx, 1111 xxxx
320851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new UTFDataFormatException();
320951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
321051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
321151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
321251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
321351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
321451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Unsynchronized table which tracks wire handle to object mappings, as
321551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * well as ClassNotFoundExceptions associated with deserialized objects.
321651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This class implements an exception-propagation algorithm for
321751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * determining which objects should have ClassNotFoundExceptions associated
321851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * with them, taking into account cycles and discontinuities (e.g., skipped
321951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * fields) in the object graph.
322051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
322151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>General use of the table is as follows: during deserialization, a
322251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * given object is first assigned a handle by calling the assign method.
322351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method leaves the assigned handle in an "open" state, wherein
322451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * dependencies on the exception status of other handles can be registered
322551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * by calling the markDependency method, or an exception can be directly
322651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with the handle by calling markException.  When a handle is
322751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * tagged with an exception, the HandleTable assumes responsibility for
322851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * propagating the exception to any other objects which depend
322951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (transitively) on the exception-tagged object.
323051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
323151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>Once all exception information/dependencies for the handle have been
323251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * registered, the handle should be "closed" by calling the finish method
323351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * on it.  The act of finishing a handle allows the exception propagation
323451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algorithm to aggressively prune dependency links, lessening the
323551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * performance/memory impact of exception tracking.
323651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
323751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>Note that the exception propagation algorithm used depends on handles
323851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * being assigned/finished in LIFO order; however, for simplicity as well
323951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * as memory conservation, it does not enforce this constraint.
324051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
324151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // REMIND: add full description of exception propagation algorithm?
324251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static class HandleTable {
324351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
324451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* status codes indicating whether object has associated exception */
324551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final byte STATUS_OK = 1;
324651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final byte STATUS_UNKNOWN = 2;
324751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static final byte STATUS_EXCEPTION = 3;
324851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
324951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** array mapping handle -> object status */
325051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] status;
325151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** array mapping handle -> object/exception (depending on status) */
325251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object[] entries;
325351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** array mapping handle -> list of dependent handles (if any) */
325451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        HandleList[] deps;
325551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** lowest unresolved dependency */
325651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lowDep = -1;
325751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /** number of handles in table */
325851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int size = 0;
325951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
326051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
326151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Creates handle table with the given initial capacity.
326251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
326351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        HandleTable(int initialCapacity) {
326451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            status = new byte[initialCapacity];
326551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            entries = new Object[initialCapacity];
326651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            deps = new HandleList[initialCapacity];
326751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
326851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
326951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
327051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Assigns next available handle to given object, and returns assigned
327151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * handle.  Once object has been completely deserialized (and all
327251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * dependencies on other objects identified), the handle should be
327351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * "closed" by passing it to finish().
327451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
327551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int assign(Object obj) {
327651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (size >= entries.length) {
327751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                grow();
327851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
327951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            status[size] = STATUS_UNKNOWN;
328051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            entries[size] = obj;
328151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size++;
328251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
328351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
328451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
328551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Registers a dependency (in exception status) of one handle on
328651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * another.  The dependent handle must be "open" (i.e., assigned, but
328751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * not finished yet).  No action is taken if either dependent or target
328851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * handle is NULL_HANDLE.
328951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
329051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void markDependency(int dependent, int target) {
329151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
329251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
329351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
329451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (status[dependent]) {
329551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
329651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_UNKNOWN:
329751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    switch (status[target]) {
329851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case STATUS_OK:
329951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // ignore dependencies on objs with no exception
330051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
330151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
330251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case STATUS_EXCEPTION:
330351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // eagerly propagate exception
330451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            markException(dependent,
330551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                (ClassNotFoundException) entries[target]);
330651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
330751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
330851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        case STATUS_UNKNOWN:
330951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // add to dependency list of target
331051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (deps[target] == null) {
331151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                deps[target] = new HandleList();
331251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
331351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            deps[target].add(dependent);
331451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
331551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // remember lowest unresolved target seen
331651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (lowDep < 0 || lowDep > target) {
331751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                lowDep = target;
331851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
331951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
332051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
332151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        default:
332251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            throw new InternalError();
332351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
332451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
332551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
332651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_EXCEPTION:
332751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
332851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
332951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
333051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new InternalError();
333151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
333251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
333351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
333451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
333551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Associates a ClassNotFoundException (if one not already associated)
333651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * with the currently active handle and propagates it to other
333751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * referencing objects as appropriate.  The specified handle must be
333851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * "open" (i.e., assigned, but not finished yet).
333951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
334051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void markException(int handle, ClassNotFoundException ex) {
334151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (status[handle]) {
334251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_UNKNOWN:
334351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    status[handle] = STATUS_EXCEPTION;
334451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    entries[handle] = ex;
334551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
334651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // propagate exception to dependents
334751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    HandleList dlist = deps[handle];
334851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (dlist != null) {
334951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        int ndeps = dlist.size();
335051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        for (int i = 0; i < ndeps; i++) {
335151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            markException(dlist.get(i), ex);
335251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
335351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        deps[handle] = null;
335451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
335551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
335651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
335751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_EXCEPTION:
335851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
335951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
336051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
336151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new InternalError();
336251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
336351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
336451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
336551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
336651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Marks given handle as finished, meaning that no new dependencies
336751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * will be marked for handle.  Calls to the assign and finish methods
336851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * must occur in LIFO order.
336951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
337051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void finish(int handle) {
337151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int end;
337251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (lowDep < 0) {
337351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // no pending unknowns, only resolve current handle
337451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = handle + 1;
337551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (lowDep >= handle) {
337651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // pending unknowns now clearable, resolve all upward handles
337751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                end = size;
337851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                lowDep = -1;
337951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
338051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // unresolved backrefs present, can't resolve anything yet
338151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
338251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
338351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
338451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
338551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = handle; i < end; i++) {
338651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                switch (status[i]) {
338751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    case STATUS_UNKNOWN:
338851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        status[i] = STATUS_OK;
338951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        deps[i] = null;
339051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
339151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
339251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    case STATUS_OK:
339351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    case STATUS_EXCEPTION:
339451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
339551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
339651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    default:
339751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new InternalError();
339851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
339951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
340051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
340151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
340251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
340351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Assigns a new object to the given handle.  The object previously
340451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * associated with the handle is forgotten.  This method has no effect
340551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * if the given handle already has an exception associated with it.
340651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * This method may be called at any time after the handle is assigned.
340751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
340851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void setObject(int handle, Object obj) {
340951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (status[handle]) {
341051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_UNKNOWN:
341151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_OK:
341251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    entries[handle] = obj;
341351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
341451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
341551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                case STATUS_EXCEPTION:
341651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
341751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
341851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                default:
341951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new InternalError();
342051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
342151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
342251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
342351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
342451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Looks up and returns object associated with the given handle.
342551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Returns null if the given handle is NULL_HANDLE, or if it has an
342651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * associated ClassNotFoundException.
342751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
342851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object lookupObject(int handle) {
342951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (handle != NULL_HANDLE &&
343051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    status[handle] != STATUS_EXCEPTION) ?
343151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                entries[handle] : null;
343251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
343351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
343451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
343551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Looks up and returns ClassNotFoundException associated with the
343651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * given handle.  Returns null if the given handle is NULL_HANDLE, or
343751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * if there is no ClassNotFoundException associated with the handle.
343851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
343951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassNotFoundException lookupException(int handle) {
344051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (handle != NULL_HANDLE &&
344151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    status[handle] == STATUS_EXCEPTION) ?
344251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (ClassNotFoundException) entries[handle] : null;
344351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
344451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
344551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
344651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Resets table to its initial state.
344751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
344851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        void clear() {
344951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Arrays.fill(status, 0, size, (byte) 0);
345051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Arrays.fill(entries, 0, size, null);
345151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Arrays.fill(deps, 0, size, null);
345251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lowDep = -1;
345351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            size = 0;
345451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
345551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
345651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
345751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Returns number of handles registered in table.
345851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
345951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int size() {
346051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return size;
346151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
346251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
346351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
346451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Expands capacity of internal arrays.
346551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
346651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private void grow() {
346751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int newCapacity = (entries.length << 1) + 1;
346851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
346951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] newStatus = new byte[newCapacity];
347051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Object[] newEntries = new Object[newCapacity];
347151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            HandleList[] newDeps = new HandleList[newCapacity];
347251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
347351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            System.arraycopy(status, 0, newStatus, 0, size);
347451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            System.arraycopy(entries, 0, newEntries, 0, size);
347551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            System.arraycopy(deps, 0, newDeps, 0, size);
347651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
347751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            status = newStatus;
347851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            entries = newEntries;
347951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            deps = newDeps;
348051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
348151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
348251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
348351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Simple growable list of (integer) handles.
348451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
348551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private static class HandleList {
348651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            private int[] list = new int[4];
348751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            private int size = 0;
348851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
348951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public HandleList() {
349051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
349151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
349251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public void add(int handle) {
349351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (size >= list.length) {
349451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int[] newList = new int[list.length << 1];
349551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    System.arraycopy(list, 0, newList, 0, list.length);
349651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    list = newList;
349751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
349851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                list[size++] = handle;
349951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
350051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
350151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public int get(int index) {
350251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (index >= size) {
350351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new ArrayIndexOutOfBoundsException();
350451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
350551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return list[index];
350651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
350751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
350851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public int size() {
350951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return size;
351051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
351151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
351251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
351351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
351451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
351551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Method for cloning arrays in case of using unsharing reading
351651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
351751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static Object cloneArray(Object array) {
351851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (array instanceof Object[]) {
351951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((Object[]) array).clone();
352051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof boolean[]) {
352151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((boolean[]) array).clone();
352251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof byte[]) {
352351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((byte[]) array).clone();
352451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof char[]) {
352551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((char[]) array).clone();
352651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof double[]) {
352751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((double[]) array).clone();
352851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof float[]) {
352951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((float[]) array).clone();
353051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof int[]) {
353151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((int[]) array).clone();
353251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof long[]) {
353351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((long[]) array).clone();
353451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (array instanceof short[]) {
353551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((short[]) array).clone();
353651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
353751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new AssertionError();
353851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
353951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
354051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
354151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
3542