ObjectInputStream.java revision b46dab348e2007bc08abaf7ecae34d89a2474e50
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.io;
19
20// BEGIN android-note
21// Harmony uses ObjectAccessors to access fields through JNI. Android has not
22// yet migrated that API. As a consequence, there's a lot of changes here...
23// END android-note
24
25import dalvik.system.VMStack;
26import java.io.EmulatedFields.ObjectSlot;
27import java.lang.reflect.Array;
28import java.lang.reflect.Constructor;
29import java.lang.reflect.Field;
30import java.lang.reflect.InvocationTargetException;
31import java.lang.reflect.Method;
32import java.lang.reflect.Modifier;
33import java.lang.reflect.Proxy;
34import java.security.AccessController;
35import java.security.PrivilegedAction;
36import java.util.ArrayList;
37import java.util.Arrays;
38import java.util.HashMap;
39import java.util.Iterator;
40import libcore.base.EmptyArray;
41import org.apache.harmony.luni.util.PriviAction;
42
43/**
44 * A specialized {@link InputStream} that is able to read (deserialize) Java
45 * objects as well as primitive data types (int, byte, char etc.). The data has
46 * typically been saved using an ObjectOutputStream.
47 *
48 * @see ObjectOutputStream
49 * @see ObjectInput
50 * @see Serializable
51 * @see Externalizable
52 */
53public class ObjectInputStream extends InputStream implements ObjectInput,
54        ObjectStreamConstants {
55
56    // BEGIN android-note
57    // this is non-static to avoid sync contention. Would static be faster?
58    // END android-note
59    private InputStream emptyStream = new ByteArrayInputStream(EmptyArray.BYTE);
60
61    // To put into objectsRead when reading unsharedObject
62    private static final Object UNSHARED_OBJ = new Object(); // $NON-LOCK-1$
63
64    // If the receiver has already read & not consumed a TC code
65    private boolean hasPushbackTC;
66
67    // Push back TC code if the variable above is true
68    private byte pushbackTC;
69
70    // How many nested levels to readObject. When we reach 0 we have to validate
71    // the graph then reset it
72    private int nestedLevels;
73
74    // All objects are assigned an ID (integer handle)
75    private int nextHandle;
76
77    // Where we read from
78    private DataInputStream input;
79
80    // Where we read primitive types from
81    private DataInputStream primitiveTypes;
82
83    // Where we keep primitive type data
84    private InputStream primitiveData = emptyStream;
85
86    // Resolve object is a mechanism for replacement
87    private boolean enableResolve;
88
89    // Table mapping Integer (handle) -> Object
90    private HashMap<Integer, Object> objectsRead;
91
92    // Used by defaultReadObject
93    private Object currentObject;
94
95    // Used by defaultReadObject
96    private ObjectStreamClass currentClass;
97
98    // All validations to be executed when the complete graph is read. See inner
99    // type below.
100    private InputValidationDesc[] validations;
101
102    // Allows the receiver to decide if it needs to call readObjectOverride
103    private boolean subclassOverridingImplementation;
104
105    // Original caller's class loader, used to perform class lookups
106    private ClassLoader callerClassLoader;
107
108    // false when reading missing fields
109    private boolean mustResolve = true;
110
111    // Handle for the current class descriptor
112    private Integer descriptorHandle;
113
114    private static final HashMap<String, Class<?>> PRIMITIVE_CLASSES =
115        new HashMap<String, Class<?>>();
116
117    static {
118        PRIMITIVE_CLASSES.put("byte", byte.class);
119        PRIMITIVE_CLASSES.put("short", short.class);
120        PRIMITIVE_CLASSES.put("int", int.class);
121        PRIMITIVE_CLASSES.put("long", long.class);
122        PRIMITIVE_CLASSES.put("boolean", boolean.class);
123        PRIMITIVE_CLASSES.put("char", char.class);
124        PRIMITIVE_CLASSES.put("float", float.class);
125        PRIMITIVE_CLASSES.put("double", double.class);
126    }
127
128    // BEGIN android-removed
129    // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor();
130    // END android-removed
131
132    // Internal type used to keep track of validators & corresponding priority
133    static class InputValidationDesc {
134        ObjectInputValidation validator;
135
136        int priority;
137    }
138
139    /**
140     * GetField is an inner class that provides access to the persistent fields
141     * read from the source stream.
142     */
143    public abstract static class GetField {
144        /**
145         * Gets the ObjectStreamClass that describes a field.
146         *
147         * @return the descriptor class for a serialized field.
148         */
149        public abstract ObjectStreamClass getObjectStreamClass();
150
151        /**
152         * Indicates if the field identified by {@code name} is defaulted. This
153         * means that it has no value in this stream.
154         *
155         * @param name
156         *            the name of the field to check.
157         * @return {@code true} if the field is defaulted, {@code false}
158         *         otherwise.
159         * @throws IllegalArgumentException
160         *             if {@code name} does not identify a serializable field.
161         * @throws IOException
162         *             if an error occurs while reading from the source input
163         *             stream.
164         */
165        public abstract boolean defaulted(String name) throws IOException,
166                IllegalArgumentException;
167
168        /**
169         * Gets the value of the boolean field identified by {@code name} from
170         * the persistent field.
171         *
172         * @param name
173         *            the name of the field to get.
174         * @param defaultValue
175         *            the default value that is used if the field does not have
176         *            a value when read from the source stream.
177         * @return the value of the field identified by {@code name}.
178         * @throws IOException
179         *             if an error occurs while reading from the source input
180         *             stream.
181         * @throws IllegalArgumentException
182         *             if the type of the field identified by {@code name} is
183         *             not {@code boolean}.
184         */
185        public abstract boolean get(String name, boolean defaultValue)
186                throws IOException, IllegalArgumentException;
187
188        /**
189         * Gets the value of the character field identified by {@code name} from
190         * the persistent field.
191         *
192         * @param name
193         *            the name of the field to get.
194         * @param defaultValue
195         *            the default value that is used if the field does not have
196         *            a value when read from the source stream.
197         * @return the value of the field identified by {@code name}.
198         * @throws IOException
199         *             if an error occurs while reading from the source input
200         *             stream.
201         * @throws IllegalArgumentException
202         *             if the type of the field identified by {@code name} is
203         *             not {@code char}.
204         */
205        public abstract char get(String name, char defaultValue)
206                throws IOException, IllegalArgumentException;
207
208        /**
209         * Gets the value of the byte field identified by {@code name} from the
210         * persistent field.
211         *
212         * @param name
213         *            the name of the field to get.
214         * @param defaultValue
215         *            the default value that is used if the field does not have
216         *            a value when read from the source stream.
217         * @return the value of the field identified by {@code name}.
218         * @throws IOException
219         *             if an error occurs while reading from the source input
220         *             stream.
221         * @throws IllegalArgumentException
222         *             if the type of the field identified by {@code name} is
223         *             not {@code byte}.
224         */
225        public abstract byte get(String name, byte defaultValue)
226                throws IOException, IllegalArgumentException;
227
228        /**
229         * Gets the value of the short field identified by {@code name} from the
230         * persistent field.
231         *
232         * @param name
233         *            the name of the field to get.
234         * @param defaultValue
235         *            the default value that is used if the field does not have
236         *            a value when read from the source stream.
237         * @return the value of the field identified by {@code name}.
238         * @throws IOException
239         *             if an error occurs while reading from the source input
240         *             stream.
241         * @throws IllegalArgumentException
242         *             if the type of the field identified by {@code name} is
243         *             not {@code short}.
244         */
245        public abstract short get(String name, short defaultValue)
246                throws IOException, IllegalArgumentException;
247
248        /**
249         * Gets the value of the integer field identified by {@code name} from
250         * the persistent field.
251         *
252         * @param name
253         *            the name of the field to get.
254         * @param defaultValue
255         *            the default value that is used if the field does not have
256         *            a value when read from the source stream.
257         * @return the value of the field identified by {@code name}.
258         * @throws IOException
259         *             if an error occurs while reading from the source input
260         *             stream.
261         * @throws IllegalArgumentException
262         *             if the type of the field identified by {@code name} is
263         *             not {@code int}.
264         */
265        public abstract int get(String name, int defaultValue)
266                throws IOException, IllegalArgumentException;
267
268        /**
269         * Gets the value of the long field identified by {@code name} from the
270         * persistent field.
271         *
272         * @param name
273         *            the name of the field to get.
274         * @param defaultValue
275         *            the default value that is used if the field does not have
276         *            a value when read from the source stream.
277         * @return the value of the field identified by {@code name}.
278         * @throws IOException
279         *             if an error occurs while reading from the source input
280         *             stream.
281         * @throws IllegalArgumentException
282         *             if the type of the field identified by {@code name} is
283         *             not {@code long}.
284         */
285        public abstract long get(String name, long defaultValue)
286                throws IOException, IllegalArgumentException;
287
288        /**
289         * Gets the value of the float field identified by {@code name} from the
290         * persistent field.
291         *
292         * @param name
293         *            the name of the field to get.
294         * @param defaultValue
295         *            the default value that is used if the field does not have
296         *            a value when read from the source stream.
297         * @return the value of the field identified by {@code name}.
298         * @throws IOException
299         *             if an error occurs while reading from the source input
300         *             stream.
301         * @throws IllegalArgumentException
302         *             if the type of the field identified by {@code float} is
303         *             not {@code char}.
304         */
305        public abstract float get(String name, float defaultValue)
306                throws IOException, IllegalArgumentException;
307
308        /**
309         * Gets the value of the double field identified by {@code name} from
310         * the persistent field.
311         *
312         * @param name
313         *            the name of the field to get.
314         * @param defaultValue
315         *            the default value that is used if the field does not have
316         *            a value when read from the source stream.
317         * @return the value of the field identified by {@code name}.
318         * @throws IOException
319         *             if an error occurs while reading from the source input
320         *             stream.
321         * @throws IllegalArgumentException
322         *             if the type of the field identified by {@code name} is
323         *             not {@code double}.
324         */
325        public abstract double get(String name, double defaultValue)
326                throws IOException, IllegalArgumentException;
327
328        /**
329         * Gets the value of the object field identified by {@code name} from
330         * the persistent field.
331         *
332         * @param name
333         *            the name of the field to get.
334         * @param defaultValue
335         *            the default value that is used if the field does not have
336         *            a value when read from the source stream.
337         * @return the value of the field identified by {@code name}.
338         * @throws IOException
339         *             if an error occurs while reading from the source input
340         *             stream.
341         * @throws IllegalArgumentException
342         *             if the type of the field identified by {@code name} is
343         *             not {@code Object}.
344         */
345        public abstract Object get(String name, Object defaultValue)
346                throws IOException, IllegalArgumentException;
347    }
348
349    /**
350     * Constructs a new ObjectInputStream. This default constructor can be used
351     * by subclasses that do not want to use the public constructor if it
352     * allocates unneeded data.
353     *
354     * @throws IOException
355     *             if an error occurs when creating this stream.
356     * @throws SecurityException
357     *             if a security manager is installed and it denies subclassing
358     *             this class.
359     * @see SecurityManager#checkPermission(java.security.Permission)
360     */
361    protected ObjectInputStream() throws IOException, SecurityException {
362        super();
363        SecurityManager currentManager = System.getSecurityManager();
364        if (currentManager != null) {
365            currentManager.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
366        }
367        // WARNING - we should throw IOException if not called from a subclass
368        // according to the JavaDoc. Add the test.
369        this.subclassOverridingImplementation = true;
370    }
371
372    /**
373     * Constructs a new ObjectInputStream that reads from the InputStream
374     * {@code input}.
375     *
376     * @param input
377     *            the non-null source InputStream to filter reads on.
378     * @throws IOException
379     *             if an error occurs while reading the stream header.
380     * @throws StreamCorruptedException
381     *             if the source stream does not contain serialized objects that
382     *             can be read.
383     * @throws SecurityException
384     *             if a security manager is installed and it denies subclassing
385     *             this class.
386     */
387    public ObjectInputStream(InputStream input)
388            throws StreamCorruptedException, IOException {
389        final Class<?> implementationClass = getClass();
390        final Class<?> thisClass = ObjectInputStream.class;
391        SecurityManager sm = System.getSecurityManager();
392        if (sm != null && implementationClass != thisClass) {
393            boolean mustCheck = AccessController
394                    .doPrivileged(new PrivilegedAction<Boolean>() {
395                        public Boolean run() {
396                            try {
397                                Method method = implementationClass.getMethod("readFields",
398                                        EmptyArray.CLASS);
399                                if (method.getDeclaringClass() != thisClass) {
400                                    return Boolean.TRUE;
401                                }
402                            } catch (NoSuchMethodException ignored) {
403                            }
404                            try {
405                                Method method = implementationClass.getMethod("readUnshared",
406                                        EmptyArray.CLASS);
407                                if (method.getDeclaringClass() != thisClass) {
408                                    return Boolean.TRUE;
409                                }
410                            } catch (NoSuchMethodException ignored) {
411                            }
412                            return Boolean.FALSE;
413                        }
414                    });
415            if (mustCheck) {
416                sm
417                        .checkPermission(ObjectStreamConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
418            }
419        }
420        this.input = (input instanceof DataInputStream) ? (DataInputStream) input
421                : new DataInputStream(input);
422        primitiveTypes = new DataInputStream(this);
423        enableResolve = false;
424        this.subclassOverridingImplementation = false;
425        resetState();
426        nestedLevels = 0;
427        // So read...() methods can be used by
428        // subclasses during readStreamHeader()
429        primitiveData = this.input;
430        // Has to be done here according to the specification
431        readStreamHeader();
432        primitiveData = emptyStream;
433    }
434
435    @Override
436    public int available() throws IOException {
437        // returns 0 if next data is an object, or N if reading primitive types
438        checkReadPrimitiveTypes();
439        return primitiveData.available();
440    }
441
442    /**
443     * Checks to if it is ok to read primitive types from this stream at
444     * this point. One is not supposed to read primitive types when about to
445     * read an object, for example, so an exception has to be thrown.
446     *
447     * @throws IOException
448     *             If any IO problem occurred when trying to read primitive type
449     *             or if it is illegal to read primitive types
450     */
451    private void checkReadPrimitiveTypes() throws IOException {
452        // If we still have primitive data, it is ok to read primitive data
453        if (primitiveData == input || primitiveData.available() > 0) {
454            return;
455        }
456
457        // If we got here either we had no Stream previously created or
458        // we no longer have data in that one, so get more bytes
459        do {
460            int next = 0;
461            if (hasPushbackTC) {
462                hasPushbackTC = false;
463            } else {
464                next = input.read();
465                pushbackTC = (byte) next;
466            }
467            switch (pushbackTC) {
468                case TC_BLOCKDATA:
469                    primitiveData = new ByteArrayInputStream(readBlockData());
470                    return;
471                case TC_BLOCKDATALONG:
472                    primitiveData = new ByteArrayInputStream(readBlockDataLong());
473                    return;
474                case TC_RESET:
475                    resetState();
476                    break;
477                default:
478                    if (next != -1) {
479                        pushbackTC();
480                    }
481                    return;
482            }
483            // Only TC_RESET falls through
484        } while (true);
485    }
486
487    /**
488     * Closes this stream. This implementation closes the source stream.
489     *
490     * @throws IOException
491     *             if an error occurs while closing this stream.
492     */
493    @Override
494    public void close() throws IOException {
495        input.close();
496    }
497
498    /**
499     * Default method to read objects from this stream. Serializable fields
500     * defined in the object's class and superclasses are read from the source
501     * stream.
502     *
503     * @throws ClassNotFoundException
504     *             if the object's class cannot be found.
505     * @throws IOException
506     *             if an I/O error occurs while reading the object data.
507     * @throws NotActiveException
508     *             if this method is not called from {@code readObject()}.
509     * @see ObjectOutputStream#defaultWriteObject
510     */
511    public void defaultReadObject() throws IOException, ClassNotFoundException,
512            NotActiveException {
513        // We can't be called from just anywhere. There are rules.
514        if (currentObject != null || !mustResolve) {
515            readFieldValues(currentObject, currentClass);
516        } else {
517            throw new NotActiveException();
518        }
519    }
520
521    /**
522     * Enables object replacement for this stream. By default this is not
523     * enabled. Only trusted subclasses (loaded with system class loader) are
524     * allowed to change this status.
525     *
526     * @param enable
527     *            {@code true} to enable object replacement; {@code false} to
528     *            disable it.
529     * @return the previous setting.
530     * @throws SecurityException
531     *             if a security manager is installed and it denies enabling
532     *             object replacement for this stream.
533     * @see #resolveObject
534     * @see ObjectOutputStream#enableReplaceObject
535     */
536    protected boolean enableResolveObject(boolean enable)
537            throws SecurityException {
538        if (enable) {
539            // The Stream has to be trusted for this feature to be enabled.
540            // trusted means the stream's class loader has to be null
541            SecurityManager currentManager = System.getSecurityManager();
542            if (currentManager != null) {
543                currentManager.checkPermission(SUBSTITUTION_PERMISSION);
544            }
545        }
546        boolean originalValue = enableResolve;
547        enableResolve = enable;
548        return originalValue;
549    }
550
551    /**
552     * Checks if two classes belong to the same package.
553     *
554     * @param c1
555     *            one of the classes to test.
556     * @param c2
557     *            the other class to test.
558     * @return {@code true} if the two classes belong to the same package,
559     *         {@code false} otherwise.
560     */
561    private boolean inSamePackage(Class<?> c1, Class<?> c2) {
562        String nameC1 = c1.getName();
563        String nameC2 = c2.getName();
564        int indexDotC1 = nameC1.lastIndexOf('.');
565        int indexDotC2 = nameC2.lastIndexOf('.');
566        if (indexDotC1 != indexDotC2) {
567            return false; // cannot be in the same package if indices are not
568        }
569        // the same
570        if (indexDotC1 < 0) {
571            return true; // both of them are in default package
572        }
573        return nameC1.substring(0, indexDotC1).equals(
574                nameC2.substring(0, indexDotC2));
575    }
576
577    // BEGIN android-added
578    /**
579     * Create and return a new instance of class {@code instantiationClass}
580     * but running the constructor defined in class
581     * {@code constructorClass} (same as {@code instantiationClass}
582     * or a superclass).
583     *
584     * Has to be native to avoid visibility rules and to be able to have
585     * {@code instantiationClass} not the same as
586     * {@code constructorClass} (no such API in java.lang.reflect).
587     *
588     * @param instantiationClass
589     *            The new object will be an instance of this class
590     * @param constructorClass
591     *            The empty constructor to run will be in this class
592     * @return the object created from {@code instantiationClass}
593     */
594    private static native Object newInstance(Class<?> instantiationClass,
595            Class<?> constructorClass);
596    // END android-added
597
598    /**
599     * Return the next {@code int} handle to be used to indicate cyclic
600     * references being loaded from the stream.
601     *
602     * @return the next handle to represent the next cyclic reference
603     */
604    private Integer nextHandle() {
605        return nextHandle++;
606    }
607
608    /**
609     * Return the next token code (TC) from the receiver, which indicates what
610     * kind of object follows
611     *
612     * @return the next TC from the receiver
613     *
614     * @throws IOException
615     *             If an IO error occurs
616     *
617     * @see ObjectStreamConstants
618     */
619    private byte nextTC() throws IOException {
620        if (hasPushbackTC) {
621            hasPushbackTC = false; // We are consuming it
622        } else {
623            // Just in case a later call decides to really push it back,
624            // we don't require the caller to pass it as parameter
625            pushbackTC = input.readByte();
626        }
627        return pushbackTC;
628    }
629
630    /**
631     * Pushes back the last TC code read
632     */
633    private void pushbackTC() {
634        hasPushbackTC = true;
635    }
636
637    /**
638     * Reads a single byte from the source stream and returns it as an integer
639     * in the range from 0 to 255. Returns -1 if the end of the source stream
640     * has been reached. Blocks if no input is available.
641     *
642     * @return the byte read or -1 if the end of the source stream has been
643     *         reached.
644     * @throws IOException
645     *             if an error occurs while reading from this stream.
646     */
647    @Override
648    public int read() throws IOException {
649        checkReadPrimitiveTypes();
650        return primitiveData.read();
651    }
652
653    /**
654     * Reads at most {@code length} bytes from the source stream and stores them
655     * in byte array {@code buffer} starting at offset {@code count}. Blocks
656     * until {@code count} bytes have been read, the end of the source stream is
657     * detected or an exception is thrown.
658     *
659     * @param buffer
660     *            the array in which to store the bytes read.
661     * @param offset
662     *            the initial position in {@code buffer} to store the bytes
663     *            read from the source stream.
664     * @param length
665     *            the maximum number of bytes to store in {@code buffer}.
666     * @return the number of bytes read or -1 if the end of the source input
667     *         stream has been reached.
668     * @throws IndexOutOfBoundsException
669     *             if {@code offset < 0} or {@code length < 0}, or if
670     *             {@code offset + length} is greater than the length of
671     *             {@code buffer}.
672     * @throws IOException
673     *             if an error occurs while reading from this stream.
674     * @throws NullPointerException
675     *             if {@code buffer} is {@code null}.
676     */
677    @Override
678    public int read(byte[] buffer, int offset, int length) throws IOException {
679        Arrays.checkOffsetAndCount(buffer.length, offset, length);
680        if (length == 0) {
681            return 0;
682        }
683        checkReadPrimitiveTypes();
684        return primitiveData.read(buffer, offset, length);
685    }
686
687    /**
688     * Reads and returns an array of raw bytes with primitive data. The array
689     * will have up to 255 bytes. The primitive data will be in the format
690     * described by {@code DataOutputStream}.
691     *
692     * @return The primitive data read, as raw bytes
693     *
694     * @throws IOException
695     *             If an IO exception happened when reading the primitive data.
696     */
697    private byte[] readBlockData() throws IOException {
698        byte[] result = new byte[input.readByte() & 0xff];
699        input.readFully(result);
700        return result;
701    }
702
703    /**
704     * Reads and returns an array of raw bytes with primitive data. The array
705     * will have more than 255 bytes. The primitive data will be in the format
706     * described by {@code DataOutputStream}.
707     *
708     * @return The primitive data read, as raw bytes
709     *
710     * @throws IOException
711     *             If an IO exception happened when reading the primitive data.
712     */
713    private byte[] readBlockDataLong() throws IOException {
714        byte[] result = new byte[input.readInt()];
715        input.readFully(result);
716        return result;
717    }
718
719    /**
720     * Reads a boolean from the source stream.
721     *
722     * @return the boolean value read from the source stream.
723     * @throws EOFException
724     *             if the end of the input is reached before the read
725     *             request can be satisfied.
726     * @throws IOException
727     *             if an error occurs while reading from the source stream.
728     */
729    public boolean readBoolean() throws IOException {
730        return primitiveTypes.readBoolean();
731    }
732
733    /**
734     * Reads a byte (8 bit) from the source stream.
735     *
736     * @return the byte value read from the source stream.
737     * @throws EOFException
738     *             if the end of the input is reached before the read
739     *             request can be satisfied.
740     * @throws IOException
741     *             if an error occurs while reading from the source stream.
742     */
743    public byte readByte() throws IOException {
744        return primitiveTypes.readByte();
745    }
746
747    /**
748     * Reads a character (16 bit) from the source stream.
749     *
750     * @return the char value read from the source stream.
751     * @throws EOFException
752     *             if the end of the input is reached before the read
753     *             request can be satisfied.
754     * @throws IOException
755     *             if an error occurs while reading from the source stream.
756     */
757    public char readChar() throws IOException {
758        return primitiveTypes.readChar();
759    }
760
761    /**
762     * Reads and discards block data and objects until TC_ENDBLOCKDATA is found.
763     *
764     * @throws IOException
765     *             If an IO exception happened when reading the optional class
766     *             annotation.
767     * @throws ClassNotFoundException
768     *             If the class corresponding to the class descriptor could not
769     *             be found.
770     */
771    private void discardData() throws ClassNotFoundException, IOException {
772        primitiveData = emptyStream;
773        boolean resolve = mustResolve;
774        mustResolve = false;
775        do {
776            byte tc = nextTC();
777            if (tc == TC_ENDBLOCKDATA) {
778                mustResolve = resolve;
779                return; // End of annotation
780            }
781            readContent(tc);
782        } while (true);
783    }
784
785    /**
786     * Reads a class descriptor (an {@code ObjectStreamClass}) from the
787     * stream.
788     *
789     * @return the class descriptor read from the stream
790     *
791     * @throws IOException
792     *             If an IO exception happened when reading the class
793     *             descriptor.
794     * @throws ClassNotFoundException
795     *             If the class corresponding to the class descriptor could not
796     *             be found.
797     */
798    private ObjectStreamClass readClassDesc() throws ClassNotFoundException, IOException {
799        byte tc = nextTC();
800        switch (tc) {
801            case TC_CLASSDESC:
802                return readNewClassDesc(false);
803            case TC_PROXYCLASSDESC:
804                Class<?> proxyClass = readNewProxyClassDesc();
805                ObjectStreamClass streamClass = ObjectStreamClass.lookup(proxyClass);
806                streamClass.setLoadFields(ObjectStreamClass.NO_FIELDS);
807                registerObjectRead(streamClass, nextHandle(), false);
808                checkedSetSuperClassDesc(streamClass, readClassDesc());
809                return streamClass;
810            case TC_REFERENCE:
811                return (ObjectStreamClass) readCyclicReference();
812            case TC_NULL:
813                return null;
814            default:
815                throw corruptStream(tc);
816        }
817    }
818
819    private StreamCorruptedException corruptStream(byte tc) throws StreamCorruptedException {
820        throw new StreamCorruptedException("Wrong format: " + Integer.toHexString(tc & 0xff));
821    }
822
823    /**
824     * Reads the content of the receiver based on the previously read token
825     * {@code tc}.
826     *
827     * @param tc
828     *            The token code for the next item in the stream
829     * @return the object read from the stream
830     *
831     * @throws IOException
832     *             If an IO exception happened when reading the class
833     *             descriptor.
834     * @throws ClassNotFoundException
835     *             If the class corresponding to the object being read could not
836     *             be found.
837     */
838    private Object readContent(byte tc) throws ClassNotFoundException,
839            IOException {
840        switch (tc) {
841            case TC_BLOCKDATA:
842                return readBlockData();
843            case TC_BLOCKDATALONG:
844                return readBlockDataLong();
845            case TC_CLASS:
846                return readNewClass(false);
847            case TC_CLASSDESC:
848                return readNewClassDesc(false);
849            case TC_ARRAY:
850                return readNewArray(false);
851            case TC_OBJECT:
852                return readNewObject(false);
853            case TC_STRING:
854                return readNewString(false);
855            case TC_LONGSTRING:
856                return readNewLongString(false);
857            case TC_REFERENCE:
858                return readCyclicReference();
859            case TC_NULL:
860                return null;
861            case TC_EXCEPTION:
862                Exception exc = readException();
863                throw new WriteAbortedException("Read an exception", exc);
864            case TC_RESET:
865                resetState();
866                return null;
867            default:
868                throw corruptStream(tc);
869        }
870    }
871
872    /**
873     * Reads the content of the receiver based on the previously read token
874     * {@code tc}. Primitive data content is considered an error.
875     *
876     * @param unshared
877     *            read the object unshared
878     * @return the object read from the stream
879     *
880     * @throws IOException
881     *             If an IO exception happened when reading the class
882     *             descriptor.
883     * @throws ClassNotFoundException
884     *             If the class corresponding to the object being read could not
885     *             be found.
886     */
887    private Object readNonPrimitiveContent(boolean unshared)
888            throws ClassNotFoundException, IOException {
889        checkReadPrimitiveTypes();
890        if (primitiveData.available() > 0) {
891            OptionalDataException e = new OptionalDataException();
892            e.length = primitiveData.available();
893            throw e;
894        }
895
896        do {
897            byte tc = nextTC();
898            switch (tc) {
899                case TC_CLASS:
900                    return readNewClass(unshared);
901                case TC_CLASSDESC:
902                    return readNewClassDesc(unshared);
903                case TC_ARRAY:
904                    return readNewArray(unshared);
905                case TC_OBJECT:
906                    return readNewObject(unshared);
907                case TC_STRING:
908                    return readNewString(unshared);
909                case TC_LONGSTRING:
910                    return readNewLongString(unshared);
911                case TC_ENUM:
912                    return readEnum(unshared);
913                case TC_REFERENCE:
914                    if (unshared) {
915                        readNewHandle();
916                        throw new InvalidObjectException("Unshared read of back reference");
917                    }
918                    return readCyclicReference();
919                case TC_NULL:
920                    return null;
921                case TC_EXCEPTION:
922                    Exception exc = readException();
923                    throw new WriteAbortedException("Read an exception", exc);
924                case TC_RESET:
925                    resetState();
926                    break;
927                case TC_ENDBLOCKDATA: // Can occur reading class annotation
928                    pushbackTC();
929                    OptionalDataException e = new OptionalDataException();
930                    e.eof = true;
931                    throw e;
932                default:
933                    throw corruptStream(tc);
934            }
935            // Only TC_RESET falls through
936        } while (true);
937    }
938
939    /**
940     * Reads the next item from the stream assuming it is a cyclic reference to
941     * an object previously read. Return the actual object previously read.
942     *
943     * @return the object previously read from the stream
944     *
945     * @throws IOException
946     *             If an IO exception happened when reading the class
947     *             descriptor.
948     * @throws InvalidObjectException
949     *             If the cyclic reference is not valid.
950     */
951    private Object readCyclicReference() throws InvalidObjectException,
952            IOException {
953        return registeredObjectRead(readNewHandle());
954    }
955
956    /**
957     * Reads a double (64 bit) from the source stream.
958     *
959     * @return the double value read from the source stream.
960     * @throws EOFException
961     *             if the end of the input is reached before the read
962     *             request can be satisfied.
963     * @throws IOException
964     *             if an error occurs while reading from the source stream.
965     */
966    public double readDouble() throws IOException {
967        return primitiveTypes.readDouble();
968    }
969
970    /**
971     * Read the next item assuming it is an exception. The exception is not a
972     * regular instance in the object graph, but the exception instance that
973     * happened (if any) when dumping the original object graph. The set of seen
974     * objects will be reset just before and just after loading this exception
975     * object.
976     * <p>
977     * When exceptions are found normally in the object graph, they are loaded
978     * as a regular object, and not by this method. In that case, the set of
979     * "known objects" is not reset.
980     *
981     * @return the exception read
982     *
983     * @throws IOException
984     *             If an IO exception happened when reading the exception
985     *             object.
986     * @throws ClassNotFoundException
987     *             If a class could not be found when reading the object graph
988     *             for the exception
989     * @throws OptionalDataException
990     *             If optional data could not be found when reading the
991     *             exception graph
992     * @throws WriteAbortedException
993     *             If another exception was caused when dumping this exception
994     */
995    private Exception readException() throws WriteAbortedException,
996            OptionalDataException, ClassNotFoundException, IOException {
997
998        resetSeenObjects();
999
1000        // Now we read the Throwable object that was saved
1001        // WARNING - the grammar says it is a Throwable, but the
1002        // WriteAbortedException constructor takes an Exception. So, we read an
1003        // Exception from the stream
1004        Exception exc = (Exception) readObject();
1005
1006        // We reset the receiver's state (the grammar has "reset" in normal
1007        // font)
1008        resetSeenObjects();
1009        return exc;
1010    }
1011
1012    /**
1013     * Reads a collection of field descriptors (name, type name, etc) for the
1014     * class descriptor {@code cDesc} (an {@code ObjectStreamClass})
1015     *
1016     * @param cDesc
1017     *            The class descriptor (an {@code ObjectStreamClass})
1018     *            for which to write field information
1019     *
1020     * @throws IOException
1021     *             If an IO exception happened when reading the field
1022     *             descriptors.
1023     * @throws ClassNotFoundException
1024     *             If a class for one of the field types could not be found
1025     *
1026     * @see #readObject()
1027     */
1028    private void readFieldDescriptors(ObjectStreamClass cDesc)
1029            throws ClassNotFoundException, IOException {
1030        short numFields = input.readShort();
1031        ObjectStreamField[] fields = new ObjectStreamField[numFields];
1032
1033        // We set it now, but each element will be inserted in the array further
1034        // down
1035        cDesc.setLoadFields(fields);
1036
1037        // Check ObjectOutputStream.writeFieldDescriptors
1038        for (short i = 0; i < numFields; i++) {
1039            char typecode = (char) input.readByte();
1040            String fieldName = input.readUTF();
1041            boolean isPrimType = ObjectStreamClass.isPrimitiveType(typecode);
1042            String classSig;
1043            if (isPrimType) {
1044                classSig = String.valueOf(typecode);
1045            } else {
1046                // The spec says it is a UTF, but experience shows they dump
1047                // this String using writeObject (unlike the field name, which
1048                // is saved with writeUTF).
1049                // And if resolveObject is enabled, the classSig may be modified
1050                // so that the original class descriptor cannot be read
1051                // properly, so it is disabled.
1052                boolean old = enableResolve;
1053                try {
1054                    enableResolve = false;
1055                    classSig = (String) readObject();
1056                } finally {
1057                    enableResolve = old;
1058                }
1059            }
1060
1061            classSig = formatClassSig(classSig);
1062            ObjectStreamField f = new ObjectStreamField(classSig, fieldName);
1063            fields[i] = f;
1064        }
1065    }
1066
1067    /*
1068     * Format the class signature for ObjectStreamField, for example,
1069     * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;"
1070     */
1071    private static String formatClassSig(String classSig) {
1072        int start = 0;
1073        int end = classSig.length();
1074
1075        if (end <= 0) {
1076            return classSig;
1077        }
1078
1079        while (classSig.startsWith("[L", start)
1080                && classSig.charAt(end - 1) == ';') {
1081            start += 2;
1082            end--;
1083        }
1084
1085        if (start > 0) {
1086            start -= 2;
1087            end++;
1088            return classSig.substring(start, end);
1089        }
1090        return classSig;
1091    }
1092
1093    /**
1094     * Reads the persistent fields of the object that is currently being read
1095     * from the source stream. The values read are stored in a GetField object
1096     * that provides access to the persistent fields. This GetField object is
1097     * then returned.
1098     *
1099     * @return the GetField object from which persistent fields can be accessed
1100     *         by name.
1101     * @throws ClassNotFoundException
1102     *             if the class of an object being deserialized can not be
1103     *             found.
1104     * @throws IOException
1105     *             if an error occurs while reading from this stream.
1106     * @throws NotActiveException
1107     *             if this stream is currently not reading an object.
1108     */
1109    public GetField readFields() throws IOException, ClassNotFoundException, NotActiveException {
1110        // We can't be called from just anywhere. There are rules.
1111        if (currentObject == null) {
1112            throw new NotActiveException();
1113        }
1114        EmulatedFieldsForLoading result = new EmulatedFieldsForLoading(
1115                currentClass);
1116        readFieldValues(result);
1117        return result;
1118    }
1119
1120    /**
1121     * Reads a collection of field values for the emulated fields
1122     * {@code emulatedFields}
1123     *
1124     * @param emulatedFields
1125     *            an {@code EmulatedFieldsForLoading}, concrete subclass
1126     *            of {@code GetField}
1127     *
1128     * @throws IOException
1129     *             If an IO exception happened when reading the field values.
1130     * @throws InvalidClassException
1131     *             If an incompatible type is being assigned to an emulated
1132     *             field.
1133     * @throws OptionalDataException
1134     *             If optional data could not be found when reading the
1135     *             exception graph
1136     *
1137     * @see #readFields
1138     * @see #readObject()
1139     */
1140    private void readFieldValues(EmulatedFieldsForLoading emulatedFields)
1141            throws OptionalDataException, InvalidClassException, IOException {
1142        EmulatedFields.ObjectSlot[] slots = emulatedFields.emulatedFields().slots();
1143        for (ObjectSlot element : slots) {
1144            element.defaulted = false;
1145            Class<?> type = element.field.getType();
1146            if (type == Integer.TYPE) {
1147                element.fieldValue = input.readInt();
1148            } else if (type == Byte.TYPE) {
1149                element.fieldValue = input.readByte();
1150            } else if (type == Character.TYPE) {
1151                element.fieldValue = input.readChar();
1152            } else if (type == Short.TYPE) {
1153                element.fieldValue = input.readShort();
1154            } else if (type == Boolean.TYPE) {
1155                element.fieldValue = input.readBoolean();
1156            } else if (type == Long.TYPE) {
1157                element.fieldValue = input.readLong();
1158            } else if (type == Float.TYPE) {
1159                element.fieldValue = input.readFloat();
1160            } else if (type == Double.TYPE) {
1161                element.fieldValue = input.readDouble();
1162            } else {
1163                // Either array or Object
1164                try {
1165                    element.fieldValue = readObject();
1166                } catch (ClassNotFoundException cnf) {
1167                    // WARNING- Not sure this is the right thing to do. Write
1168                    // test case.
1169                    throw new InvalidClassException(cnf.toString());
1170                }
1171            }
1172        }
1173    }
1174
1175    /**
1176     * Reads a collection of field values for the class descriptor
1177     * {@code classDesc} (an {@code ObjectStreamClass}). The
1178     * values will be used to set instance fields in object {@code obj}.
1179     * This is the default mechanism, when emulated fields (an
1180     * {@code GetField}) are not used. Actual values to load are stored
1181     * directly into the object {@code obj}.
1182     *
1183     * @param obj
1184     *            Instance in which the fields will be set.
1185     * @param classDesc
1186     *            A class descriptor (an {@code ObjectStreamClass})
1187     *            defining which fields should be loaded.
1188     *
1189     * @throws IOException
1190     *             If an IO exception happened when reading the field values.
1191     * @throws InvalidClassException
1192     *             If an incompatible type is being assigned to an emulated
1193     *             field.
1194     * @throws OptionalDataException
1195     *             If optional data could not be found when reading the
1196     *             exception graph
1197     * @throws ClassNotFoundException
1198     *             If a class of an object being de-serialized can not be found
1199     *
1200     * @see #readFields
1201     * @see #readObject()
1202     */
1203    private void readFieldValues(Object obj, ObjectStreamClass classDesc) throws OptionalDataException, ClassNotFoundException, IOException {
1204        // Now we must read all fields and assign them to the receiver
1205        ObjectStreamField[] fields = classDesc.getLoadFields();
1206        fields = (fields == null) ? ObjectStreamClass.NO_FIELDS : fields;
1207        Class<?> declaringClass = classDesc.forClass();
1208        if (declaringClass == null && mustResolve) {
1209            throw new ClassNotFoundException(classDesc.getName());
1210        }
1211
1212        for (ObjectStreamField fieldDesc : fields) {
1213            Field field = classDesc.getReflectionField(fieldDesc);
1214            // We may not have been able to find the field, but we still need to read the value
1215            // and do the other checking, so there's no null check on 'field' here.
1216            try {
1217                switch (fieldDesc.getTypeCode()) {
1218                case 'B':
1219                    byte b = input.readByte();
1220                    if (field != null) {
1221                        field.setByte(obj, b);
1222                    }
1223                    break;
1224                case 'C':
1225                    char c = input.readChar();
1226                    if (field != null) {
1227                        field.setChar(obj, c);
1228                    }
1229                    break;
1230                case 'D':
1231                    double d = input.readDouble();
1232                    if (field != null) {
1233                        field.setDouble(obj, d);
1234                    }
1235                    break;
1236                case 'F':
1237                    float f = input.readFloat();
1238                    if (field != null) {
1239                        field.setFloat(obj, f);
1240                    }
1241                    break;
1242                case 'I':
1243                    int i = input.readInt();
1244                    if (field != null) {
1245                        field.setInt(obj, i);
1246                    }
1247                    break;
1248                case 'J':
1249                    long j = input.readLong();
1250                    if (field != null) {
1251                        field.setLong(obj, j);
1252                    }
1253                    break;
1254                case 'S':
1255                    short s = input.readShort();
1256                    if (field != null) {
1257                        field.setShort(obj, s);
1258                    }
1259                    break;
1260                case 'Z':
1261                    boolean z = input.readBoolean();
1262                    if (field != null) {
1263                        field.setBoolean(obj, z);
1264                    }
1265                    break;
1266                case 'L':
1267                case '[':
1268                    String fieldName = fieldDesc.getName();
1269                    boolean setBack = false;
1270                    ObjectStreamField localFieldDesc = classDesc.getField(fieldName);
1271                    if (mustResolve && fieldDesc == null) {
1272                        setBack = true;
1273                        mustResolve = false;
1274                    }
1275                    boolean unshared = fieldDesc != null && fieldDesc.isUnshared();
1276                    Object toSet = unshared ? readUnshared() : readObject();
1277                    if (setBack) {
1278                        mustResolve = true;
1279                    }
1280                    if (fieldDesc != null) {
1281                        if (toSet != null) {
1282                            // BEGIN android-changed
1283                            // Get the field type from the local field rather than
1284                            // from the stream's supplied data. That's the field
1285                            // we'll be setting, so that's the one that needs to be
1286                            // validated.
1287                            Class<?> fieldType = localFieldDesc.getTypeInternal();
1288                            // END android-added
1289                            Class<?> valueType = toSet.getClass();
1290                            if (!fieldType.isAssignableFrom(valueType)) {
1291                                throw new ClassCastException(classDesc.getName() + "." + fieldName + " - " + fieldType + " not compatible with " + valueType);
1292                            }
1293                            if (field != null) {
1294                                field.set(obj, toSet);
1295                            }
1296                        }
1297                    }
1298                    break;
1299                default:
1300                    throw new StreamCorruptedException("Invalid typecode: " + fieldDesc.getTypeCode());
1301                }
1302            } catch (IllegalAccessException iae) {
1303                // ObjectStreamField should have called setAccessible(true).
1304                throw new AssertionError(iae);
1305            } catch (NoSuchFieldError ignored) {
1306            }
1307        }
1308    }
1309
1310    /**
1311     * Reads a float (32 bit) from the source stream.
1312     *
1313     * @return the float value read from the source stream.
1314     * @throws EOFException
1315     *             if the end of the input is reached before the read
1316     *             request can be satisfied.
1317     * @throws IOException
1318     *             if an error occurs while reading from the source stream.
1319     */
1320    public float readFloat() throws IOException {
1321        return primitiveTypes.readFloat();
1322    }
1323
1324    /**
1325     * Reads bytes from the source stream into the byte array {@code dst}.
1326     * This method will block until {@code dst.length} bytes have been read.
1327     *
1328     * @param dst
1329     *            the array in which to store the bytes read.
1330     * @throws EOFException
1331     *             if the end of the input is reached before the read
1332     *             request can be satisfied.
1333     * @throws IOException
1334     *             if an error occurs while reading from the source stream.
1335     */
1336    public void readFully(byte[] dst) throws IOException {
1337        primitiveTypes.readFully(dst);
1338    }
1339
1340    /**
1341     * Reads {@code byteCount} bytes from the source stream into the byte array {@code dst}.
1342     *
1343     * @param dst
1344     *            the byte array in which to store the bytes read.
1345     * @param offset
1346     *            the initial position in {@code dst} to store the bytes
1347     *            read from the source stream.
1348     * @param byteCount
1349     *            the number of bytes to read.
1350     * @throws EOFException
1351     *             if the end of the input is reached before the read
1352     *             request can be satisfied.
1353     * @throws IOException
1354     *             if an error occurs while reading from the source stream.
1355     */
1356    public void readFully(byte[] dst, int offset, int byteCount) throws IOException {
1357        primitiveTypes.readFully(dst, offset, byteCount);
1358    }
1359
1360    /**
1361     * Walks the hierarchy of classes described by class descriptor
1362     * {@code classDesc} and reads the field values corresponding to
1363     * fields declared by the corresponding class descriptor. The instance to
1364     * store field values into is {@code object}. If the class
1365     * (corresponding to class descriptor {@code classDesc}) defines
1366     * private instance method {@code readObject} it will be used to load
1367     * field values.
1368     *
1369     * @param object
1370     *            Instance into which stored field values loaded.
1371     * @param classDesc
1372     *            A class descriptor (an {@code ObjectStreamClass})
1373     *            defining which fields should be loaded.
1374     *
1375     * @throws IOException
1376     *             If an IO exception happened when reading the field values in
1377     *             the hierarchy.
1378     * @throws ClassNotFoundException
1379     *             If a class for one of the field types could not be found
1380     * @throws NotActiveException
1381     *             If {@code defaultReadObject} is called from the wrong
1382     *             context.
1383     *
1384     * @see #defaultReadObject
1385     * @see #readObject()
1386     */
1387    private void readHierarchy(Object object, ObjectStreamClass classDesc)
1388            throws IOException, ClassNotFoundException, NotActiveException {
1389        // We can't be called from just anywhere. There are rules.
1390        if (object == null && mustResolve) {
1391            throw new NotActiveException();
1392        }
1393
1394        ArrayList<ObjectStreamClass> streamClassList = new ArrayList<ObjectStreamClass>(32);
1395        ObjectStreamClass nextStreamClass = classDesc;
1396        while (nextStreamClass != null) {
1397            streamClassList.add(0, nextStreamClass);
1398            nextStreamClass = nextStreamClass.getSuperclass();
1399        }
1400        if (object == null) {
1401            for (ObjectStreamClass objectStreamClass : streamClassList) {
1402                readObjectForClass(null, objectStreamClass);
1403            }
1404        } else {
1405            ArrayList<Class<?>> classList = new ArrayList<Class<?>>(32);
1406            Class<?> nextClass = object.getClass();
1407            while (nextClass != null) {
1408                Class<?> testClass = nextClass.getSuperclass();
1409                if (testClass != null) {
1410                    classList.add(0, nextClass);
1411                }
1412                nextClass = testClass;
1413            }
1414            int lastIndex = 0;
1415            for (Class<?> superclass : classList) {
1416                int index = findStreamSuperclass(superclass, streamClassList, lastIndex);
1417                if (index == -1) {
1418                    readObjectNoData(object, superclass,
1419                            ObjectStreamClass.lookupStreamClass(superclass));
1420                } else {
1421                    for (int j = lastIndex; j <= index; j++) {
1422                        readObjectForClass(object, streamClassList.get(j));
1423                    }
1424                    lastIndex = index + 1;
1425                }
1426            }
1427        }
1428    }
1429
1430    private int findStreamSuperclass(Class<?> cl,
1431            ArrayList<ObjectStreamClass> classList, int lastIndex) {
1432        ObjectStreamClass objCl;
1433        String forName;
1434
1435        for (int i = lastIndex; i < classList.size(); i++) {
1436            objCl = classList.get(i);
1437            forName = objCl.forClass().getName();
1438
1439            if (objCl.getName().equals(forName)) {
1440                if (cl.getName().equals(objCl.getName())) {
1441                    return i;
1442                }
1443            } else {
1444                // there was a class replacement
1445                if (cl.getName().equals(forName)) {
1446                    return i;
1447                }
1448            }
1449        }
1450        return -1;
1451    }
1452
1453    private void readObjectNoData(Object object, Class<?> cl, ObjectStreamClass classDesc)
1454            throws ObjectStreamException {
1455        if (!classDesc.isSerializable()) {
1456            return;
1457        }
1458        if (classDesc.hasMethodReadObjectNoData()){
1459            final Method readMethod = classDesc.getMethodReadObjectNoData();
1460            try {
1461                readMethod.invoke(object);
1462            } catch (InvocationTargetException e) {
1463                Throwable ex = e.getTargetException();
1464                if (ex instanceof RuntimeException) {
1465                    throw (RuntimeException) ex;
1466                } else if (ex instanceof Error) {
1467                    throw (Error) ex;
1468                }
1469                throw (ObjectStreamException) ex;
1470            } catch (IllegalAccessException e) {
1471                throw new RuntimeException(e.toString());
1472            }
1473        }
1474
1475    }
1476
1477    private void readObjectForClass(Object object, ObjectStreamClass classDesc)
1478            throws IOException, ClassNotFoundException, NotActiveException {
1479        // Have to do this before calling defaultReadObject or anything that
1480        // calls defaultReadObject
1481        currentObject = object;
1482        currentClass = classDesc;
1483
1484        boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
1485        Class<?> targetClass = classDesc.forClass();
1486
1487        final Method readMethod;
1488        if (targetClass == null || !mustResolve) {
1489            readMethod = null;
1490        } else {
1491            readMethod = classDesc.getMethodReadObject();
1492        }
1493        try {
1494            if (readMethod != null) {
1495                // We have to be able to fetch its value, even if it is private
1496                AccessController.doPrivileged(new PriviAction<Object>(
1497                        readMethod));
1498                try {
1499                    readMethod.invoke(object, this);
1500                } catch (InvocationTargetException e) {
1501                    Throwable ex = e.getTargetException();
1502                    if (ex instanceof ClassNotFoundException) {
1503                        throw (ClassNotFoundException) ex;
1504                    } else if (ex instanceof RuntimeException) {
1505                        throw (RuntimeException) ex;
1506                    } else if (ex instanceof Error) {
1507                        throw (Error) ex;
1508                    }
1509                    throw (IOException) ex;
1510                } catch (IllegalAccessException e) {
1511                    throw new RuntimeException(e.toString());
1512                }
1513            } else {
1514                defaultReadObject();
1515            }
1516            if (hadWriteMethod) {
1517                discardData();
1518            }
1519        } finally {
1520            // Cleanup, needs to run always so that we can later detect invalid
1521            // calls to defaultReadObject
1522            currentObject = null; // We did not set this, so we do not need to
1523            // clean it
1524            currentClass = null;
1525        }
1526    }
1527
1528    /**
1529     * Reads an integer (32 bit) from the source stream.
1530     *
1531     * @return the integer value read from the source stream.
1532     * @throws EOFException
1533     *             if the end of the input is reached before the read
1534     *             request can be satisfied.
1535     * @throws IOException
1536     *             if an error occurs while reading from the source stream.
1537     */
1538    public int readInt() throws IOException {
1539        return primitiveTypes.readInt();
1540    }
1541
1542    /**
1543     * Reads the next line from the source stream. Lines are terminated by
1544     * {@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}.
1545     *
1546     * @return the string read from the source stream.
1547     * @throws IOException
1548     *             if an error occurs while reading from the source stream.
1549     * @deprecated Use {@link BufferedReader}
1550     */
1551    @Deprecated
1552    public String readLine() throws IOException {
1553        return primitiveTypes.readLine();
1554    }
1555
1556    /**
1557     * Reads a long (64 bit) from the source stream.
1558     *
1559     * @return the long value read from the source stream.
1560     * @throws EOFException
1561     *             if the end of the input is reached before the read
1562     *             request can be satisfied.
1563     * @throws IOException
1564     *             if an error occurs while reading from the source stream.
1565     */
1566    public long readLong() throws IOException {
1567        return primitiveTypes.readLong();
1568    }
1569
1570    /**
1571     * Read a new array from the receiver. It is assumed the array has not been
1572     * read yet (not a cyclic reference). Return the array read.
1573     *
1574     * @param unshared
1575     *            read the object unshared
1576     * @return the array read
1577     *
1578     * @throws IOException
1579     *             If an IO exception happened when reading the array.
1580     * @throws ClassNotFoundException
1581     *             If a class for one of the objects could not be found
1582     * @throws OptionalDataException
1583     *             If optional data could not be found when reading the array.
1584     */
1585    private Object readNewArray(boolean unshared) throws OptionalDataException,
1586            ClassNotFoundException, IOException {
1587        ObjectStreamClass classDesc = readClassDesc();
1588
1589        if (classDesc == null) {
1590            throw missingClassDescriptor();
1591        }
1592
1593        Integer newHandle = nextHandle();
1594
1595        // Array size
1596        int size = input.readInt();
1597        Class<?> arrayClass = classDesc.forClass();
1598        Class<?> componentType = arrayClass.getComponentType();
1599        Object result = Array.newInstance(componentType, size);
1600
1601        registerObjectRead(result, newHandle, unshared);
1602
1603        // Now we have code duplication just because Java is typed. We have to
1604        // read N elements and assign to array positions, but we must typecast
1605        // the array first, and also call different methods depending on the
1606        // elements.
1607        if (componentType.isPrimitive()) {
1608            if (componentType == Integer.TYPE) {
1609                int[] intArray = (int[]) result;
1610                for (int i = 0; i < size; i++) {
1611                    intArray[i] = input.readInt();
1612                }
1613            } else if (componentType == Byte.TYPE) {
1614                byte[] byteArray = (byte[]) result;
1615                input.readFully(byteArray, 0, size);
1616            } else if (componentType == Character.TYPE) {
1617                char[] charArray = (char[]) result;
1618                for (int i = 0; i < size; i++) {
1619                    charArray[i] = input.readChar();
1620                }
1621            } else if (componentType == Short.TYPE) {
1622                short[] shortArray = (short[]) result;
1623                for (int i = 0; i < size; i++) {
1624                    shortArray[i] = input.readShort();
1625                }
1626            } else if (componentType == Boolean.TYPE) {
1627                boolean[] booleanArray = (boolean[]) result;
1628                for (int i = 0; i < size; i++) {
1629                    booleanArray[i] = input.readBoolean();
1630                }
1631            } else if (componentType == Long.TYPE) {
1632                long[] longArray = (long[]) result;
1633                for (int i = 0; i < size; i++) {
1634                    longArray[i] = input.readLong();
1635                }
1636            } else if (componentType == Float.TYPE) {
1637                float[] floatArray = (float[]) result;
1638                for (int i = 0; i < size; i++) {
1639                    floatArray[i] = input.readFloat();
1640                }
1641            } else if (componentType == Double.TYPE) {
1642                double[] doubleArray = (double[]) result;
1643                for (int i = 0; i < size; i++) {
1644                    doubleArray[i] = input.readDouble();
1645                }
1646            } else {
1647                throw new ClassNotFoundException("Wrong base type in " + classDesc.getName());
1648            }
1649        } else {
1650            // Array of Objects
1651            Object[] objectArray = (Object[]) result;
1652            for (int i = 0; i < size; i++) {
1653                // TODO: This place is the opportunity for enhancement
1654                //      We can implement writing elements through fast-path,
1655                //      without setting up the context (see readObject()) for
1656                //      each element with public API
1657                objectArray[i] = readObject();
1658            }
1659        }
1660        if (enableResolve) {
1661            result = resolveObject(result);
1662            registerObjectRead(result, newHandle, false);
1663        }
1664        return result;
1665    }
1666
1667    /**
1668     * Reads a new class from the receiver. It is assumed the class has not been
1669     * read yet (not a cyclic reference). Return the class read.
1670     *
1671     * @param unshared
1672     *            read the object unshared
1673     * @return The {@code java.lang.Class} read from the stream.
1674     *
1675     * @throws IOException
1676     *             If an IO exception happened when reading the class.
1677     * @throws ClassNotFoundException
1678     *             If a class for one of the objects could not be found
1679     */
1680    private Class<?> readNewClass(boolean unshared) throws ClassNotFoundException, IOException {
1681        ObjectStreamClass classDesc = readClassDesc();
1682        if (classDesc == null) {
1683            throw missingClassDescriptor();
1684        }
1685        Class<?> localClass = classDesc.forClass();
1686        if (localClass != null) {
1687            registerObjectRead(localClass, nextHandle(), unshared);
1688        }
1689        return localClass;
1690    }
1691
1692    /*
1693     * read class type for Enum, note there's difference between enum and normal
1694     * classes
1695     */
1696    private ObjectStreamClass readEnumDesc() throws IOException,
1697            ClassNotFoundException {
1698        byte tc = nextTC();
1699        switch (tc) {
1700            case TC_CLASSDESC:
1701                return readEnumDescInternal();
1702            case TC_REFERENCE:
1703                return (ObjectStreamClass) readCyclicReference();
1704            case TC_NULL:
1705                return null;
1706            default:
1707                throw corruptStream(tc);
1708        }
1709    }
1710
1711    private ObjectStreamClass readEnumDescInternal() throws IOException,
1712            ClassNotFoundException {
1713        ObjectStreamClass classDesc;
1714        primitiveData = input;
1715        Integer oldHandle = descriptorHandle;
1716        descriptorHandle = nextHandle();
1717        classDesc = readClassDescriptor();
1718        registerObjectRead(classDesc, descriptorHandle, false);
1719        descriptorHandle = oldHandle;
1720        primitiveData = emptyStream;
1721        classDesc.setClass(resolveClass(classDesc));
1722        // Consume unread class annotation data and TC_ENDBLOCKDATA
1723        discardData();
1724        ObjectStreamClass superClass = readClassDesc();
1725        checkedSetSuperClassDesc(classDesc, superClass);
1726        // Check SUIDs, note all SUID for Enum is 0L
1727        if (0L != classDesc.getSerialVersionUID() || 0L != superClass.getSerialVersionUID()) {
1728            throw new InvalidClassException(superClass.getName(),
1729                    "Incompatible class (SUID): " + superClass + " but expected " + superClass);
1730        }
1731        byte tc = nextTC();
1732        // discard TC_ENDBLOCKDATA after classDesc if any
1733        if (tc == TC_ENDBLOCKDATA) {
1734            // read next parent class. For enum, it may be null
1735            superClass.setSuperclass(readClassDesc());
1736        } else {
1737            // not TC_ENDBLOCKDATA, push back for next read
1738            pushbackTC();
1739        }
1740        return classDesc;
1741    }
1742
1743    @SuppressWarnings("unchecked")// For the Enum.valueOf call
1744    private Object readEnum(boolean unshared) throws OptionalDataException,
1745            ClassNotFoundException, IOException {
1746        // read classdesc for Enum first
1747        ObjectStreamClass classDesc = readEnumDesc();
1748        Integer newHandle = nextHandle();
1749        // read name after class desc
1750        String name;
1751        byte tc = nextTC();
1752        switch (tc) {
1753            case TC_REFERENCE:
1754                if (unshared) {
1755                    readNewHandle();
1756                    throw new InvalidObjectException("Unshared read of back reference");
1757                }
1758                name = (String) readCyclicReference();
1759                break;
1760            case TC_STRING:
1761                name = (String) readNewString(unshared);
1762                break;
1763            default:
1764                throw corruptStream(tc);
1765        }
1766
1767        Enum<?> result = Enum.valueOf((Class) classDesc.forClass(), name);
1768        registerObjectRead(result, newHandle, unshared);
1769
1770        return result;
1771    }
1772
1773    /**
1774     * Reads a new class descriptor from the receiver. It is assumed the class
1775     * descriptor has not been read yet (not a cyclic reference). Return the
1776     * class descriptor read.
1777     *
1778     * @param unshared
1779     *            read the object unshared
1780     * @return The {@code ObjectStreamClass} read from the stream.
1781     *
1782     * @throws IOException
1783     *             If an IO exception happened when reading the class
1784     *             descriptor.
1785     * @throws ClassNotFoundException
1786     *             If a class for one of the objects could not be found
1787     */
1788    private ObjectStreamClass readNewClassDesc(boolean unshared)
1789            throws ClassNotFoundException, IOException {
1790        // So read...() methods can be used by
1791        // subclasses during readClassDescriptor()
1792        primitiveData = input;
1793        Integer oldHandle = descriptorHandle;
1794        descriptorHandle = nextHandle();
1795        ObjectStreamClass newClassDesc = readClassDescriptor();
1796        registerObjectRead(newClassDesc, descriptorHandle, unshared);
1797        descriptorHandle = oldHandle;
1798        primitiveData = emptyStream;
1799
1800        // We need to map classDesc to class.
1801        try {
1802            newClassDesc.setClass(resolveClass(newClassDesc));
1803            // Check SUIDs & base name of the class
1804            verifyAndInit(newClassDesc);
1805        } catch (ClassNotFoundException e) {
1806            if (mustResolve) {
1807                throw e;
1808                // Just continue, the class may not be required
1809            }
1810        }
1811
1812        // Resolve the field signatures using the class loader of the
1813        // resolved class
1814        ObjectStreamField[] fields = newClassDesc.getLoadFields();
1815        fields = (fields == null) ? ObjectStreamClass.NO_FIELDS : fields;
1816        ClassLoader loader = newClassDesc.forClass() == null ? callerClassLoader
1817                : newClassDesc.forClass().getClassLoader();
1818        for (ObjectStreamField element : fields) {
1819            element.resolve(loader);
1820        }
1821
1822        // Consume unread class annotation data and TC_ENDBLOCKDATA
1823        discardData();
1824        checkedSetSuperClassDesc(newClassDesc, readClassDesc());
1825        return newClassDesc;
1826    }
1827
1828    /**
1829     * Reads a new proxy class descriptor from the receiver. It is assumed the
1830     * proxy class descriptor has not been read yet (not a cyclic reference).
1831     * Return the proxy class descriptor read.
1832     *
1833     * @return The {@code Class} read from the stream.
1834     *
1835     * @throws IOException
1836     *             If an IO exception happened when reading the class
1837     *             descriptor.
1838     * @throws ClassNotFoundException
1839     *             If a class for one of the objects could not be found
1840     */
1841    private Class<?> readNewProxyClassDesc() throws ClassNotFoundException,
1842            IOException {
1843        int count = input.readInt();
1844        String[] interfaceNames = new String[count];
1845        for (int i = 0; i < count; i++) {
1846            interfaceNames[i] = input.readUTF();
1847        }
1848        Class<?> proxy = resolveProxyClass(interfaceNames);
1849        // Consume unread class annotation data and TC_ENDBLOCKDATA
1850        discardData();
1851        return proxy;
1852    }
1853
1854    /**
1855     * Reads a class descriptor from the source stream.
1856     *
1857     * @return the class descriptor read from the source stream.
1858     * @throws ClassNotFoundException
1859     *             if a class for one of the objects cannot be found.
1860     * @throws IOException
1861     *             if an error occurs while reading from the source stream.
1862     */
1863    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
1864        ObjectStreamClass newClassDesc = new ObjectStreamClass();
1865        String name = input.readUTF();
1866        if (name.length() == 0) {
1867            throw new IOException("The stream is corrupted");
1868        }
1869        newClassDesc.setName(name);
1870        newClassDesc.setSerialVersionUID(input.readLong());
1871        newClassDesc.setFlags(input.readByte());
1872
1873        /*
1874         * We must register the class descriptor before reading field
1875         * descriptors. If called outside of readObject, the descriptorHandle
1876         * might be null.
1877         */
1878        descriptorHandle = (descriptorHandle == null) ? nextHandle() : descriptorHandle;
1879        registerObjectRead(newClassDesc, descriptorHandle, false);
1880
1881        readFieldDescriptors(newClassDesc);
1882        return newClassDesc;
1883    }
1884
1885    /**
1886     * Creates the proxy class that implements the interfaces specified in
1887     * {@code interfaceNames}.
1888     *
1889     * @param interfaceNames
1890     *            the interfaces used to create the proxy class.
1891     * @return the proxy class.
1892     * @throws ClassNotFoundException
1893     *             if the proxy class or any of the specified interfaces cannot
1894     *             be created.
1895     * @throws IOException
1896     *             if an error occurs while reading from the source stream.
1897     * @see ObjectOutputStream#annotateProxyClass(Class)
1898     */
1899    protected Class<?> resolveProxyClass(String[] interfaceNames)
1900            throws IOException, ClassNotFoundException {
1901        // TODO: This method is opportunity for performance enhancement
1902        //       We can cache the classloader and recently used interfaces.
1903        // BEGIN android-changed
1904        // ClassLoader loader = VM.getNonBootstrapClassLoader();
1905        ClassLoader loader = ClassLoader.getSystemClassLoader();
1906        // END android-changed
1907        Class<?>[] interfaces = new Class<?>[interfaceNames.length];
1908        for (int i = 0; i < interfaceNames.length; i++) {
1909            interfaces[i] = Class.forName(interfaceNames[i], false, loader);
1910        }
1911        try {
1912            return Proxy.getProxyClass(loader, interfaces);
1913        } catch (IllegalArgumentException e) {
1914            throw new ClassNotFoundException(e.toString(), e);
1915        }
1916    }
1917
1918    /**
1919     * Write a new handle describing a cyclic reference from the stream.
1920     *
1921     * @return the handle read
1922     *
1923     * @throws IOException
1924     *             If an IO exception happened when reading the handle
1925     */
1926    private int readNewHandle() throws IOException {
1927        return input.readInt();
1928    }
1929
1930    private Class<?> resolveConstructorClass(Class<?> objectClass, boolean wasSerializable, boolean wasExternalizable)
1931        throws OptionalDataException, ClassNotFoundException, IOException {
1932
1933            // The class of the instance may not be the same as the class of the
1934            // constructor to run
1935            // This is the constructor to run if Externalizable
1936            Class<?> constructorClass = objectClass;
1937
1938            // WARNING - What if the object is serializable and externalizable ?
1939            // Is that possible ?
1940            if (wasSerializable) {
1941                // Now we must run the constructor of the class just above the
1942                // one that implements Serializable so that slots that were not
1943                // dumped can be initialized properly
1944                while (constructorClass != null
1945                        && ObjectStreamClass.isSerializable(constructorClass)) {
1946                    constructorClass = constructorClass.getSuperclass();
1947                }
1948            }
1949
1950            // Fetch the empty constructor, or null if none.
1951            Constructor<?> constructor = null;
1952            if (constructorClass != null) {
1953                try {
1954                    constructor = constructorClass.getDeclaredConstructor(EmptyArray.CLASS);
1955                } catch (NoSuchMethodException nsmEx) {
1956                    // Ignored
1957                }
1958            }
1959
1960            // Has to have an empty constructor
1961            if (constructor == null) {
1962                String className = constructorClass != null ? constructorClass.getName() : null;
1963                throw new InvalidClassException(className, "IllegalAccessException");
1964            }
1965
1966            int constructorModifiers = constructor.getModifiers();
1967
1968            // Now we must check if the empty constructor is visible to the
1969            // instantiation class
1970            if (Modifier.isPrivate(constructorModifiers)
1971                    || (wasExternalizable && !Modifier.isPublic(constructorModifiers))) {
1972                throw new InvalidClassException(constructorClass.getName(),
1973                        "IllegalAccessException");
1974            }
1975
1976            // We know we are testing from a subclass, so the only other case
1977            // where the visibility is not allowed is when the constructor has
1978            // default visibility and the instantiation class is in a different
1979            // package than the constructor class
1980            if (!Modifier.isPublic(constructorModifiers)
1981                    && !Modifier.isProtected(constructorModifiers)) {
1982                // Not public, not private and not protected...means default
1983                // visibility. Check if same package
1984                if (!inSamePackage(constructorClass, objectClass)) {
1985                    throw new InvalidClassException(constructorClass.getName(),
1986                            "IllegalAccessException");
1987                }
1988            }
1989
1990            return constructorClass;
1991    }
1992
1993    /**
1994     * Read a new object from the stream. It is assumed the object has not been
1995     * loaded yet (not a cyclic reference). Return the object read.
1996     *
1997     * If the object implements <code>Externalizable</code> its
1998     * <code>readExternal</code> is called. Otherwise, all fields described by
1999     * the class hierarchy are loaded. Each class can define how its declared
2000     * instance fields are loaded by defining a private method
2001     * <code>readObject</code>
2002     *
2003     * @param unshared
2004     *            read the object unshared
2005     * @return the object read
2006     *
2007     * @throws IOException
2008     *             If an IO exception happened when reading the object.
2009     * @throws OptionalDataException
2010     *             If optional data could not be found when reading the object
2011     *             graph
2012     * @throws ClassNotFoundException
2013     *             If a class for one of the objects could not be found
2014     */
2015    private Object readNewObject(boolean unshared)
2016            throws OptionalDataException, ClassNotFoundException, IOException {
2017        ObjectStreamClass classDesc = readClassDesc();
2018
2019        if (classDesc == null) {
2020            throw missingClassDescriptor();
2021        }
2022
2023        Integer newHandle = nextHandle();
2024
2025        // Note that these values come from the Stream, and in fact it could be
2026        // that the classes have been changed so that the info below now
2027        // conflicts with the newer class
2028        boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
2029        boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
2030
2031
2032        // Maybe we should cache the values above in classDesc ? It may be the
2033        // case that when reading classDesc we may need to read more stuff
2034        // depending on the values above
2035        Class<?> objectClass = classDesc.forClass();
2036
2037        Object result, registeredResult = null;
2038        if (objectClass != null) {
2039            Class constructorClass = resolveConstructorClass(objectClass, wasSerializable, wasExternalizable);
2040
2041            // Now we know which class to instantiate and which constructor to
2042            // run. We are allowed to run the constructor.
2043            // BEGIN android-changed
2044            // result = accessor.newInstance(objectClass, constructor, null);
2045            result = newInstance(objectClass, constructorClass);
2046            // END android-changed
2047            registerObjectRead(result, newHandle, unshared);
2048
2049            registeredResult = result;
2050        } else {
2051            result = null;
2052        }
2053
2054        try {
2055            // This is how we know what to do in defaultReadObject. And it is
2056            // also used by defaultReadObject to check if it was called from an
2057            // invalid place. It also allows readExternal to call
2058            // defaultReadObject and have it work.
2059            currentObject = result;
2060            currentClass = classDesc;
2061
2062            // If Externalizable, just let the object read itself
2063            if (wasExternalizable) {
2064                boolean blockData = (classDesc.getFlags() & SC_BLOCK_DATA) > 0;
2065                if (!blockData) {
2066                    primitiveData = input;
2067                }
2068                if (mustResolve) {
2069                    Externalizable extern = (Externalizable) result;
2070                    extern.readExternal(this);
2071                }
2072                if (blockData) {
2073                    // Similar to readHierarchy. Anything not read by
2074                    // readExternal has to be consumed here
2075                    discardData();
2076                } else {
2077                    primitiveData = emptyStream;
2078                }
2079            } else {
2080                // If we got here, it is Serializable but not Externalizable.
2081                // Walk the hierarchy reading each class' slots
2082                readHierarchy(result, classDesc);
2083            }
2084        } finally {
2085            // Cleanup, needs to run always so that we can later detect invalid
2086            // calls to defaultReadObject
2087            currentObject = null;
2088            currentClass = null;
2089        }
2090
2091        if (objectClass != null) {
2092
2093            if (classDesc.hasMethodReadResolve()){
2094                Method methodReadResolve = classDesc.getMethodReadResolve();
2095                try {
2096                    result = methodReadResolve.invoke(result, (Object[]) null);
2097                } catch (IllegalAccessException ignored) {
2098                } catch (InvocationTargetException ite) {
2099                    Throwable target = ite.getTargetException();
2100                    if (target instanceof ObjectStreamException) {
2101                        throw (ObjectStreamException) target;
2102                    } else if (target instanceof Error) {
2103                        throw (Error) target;
2104                    } else {
2105                        throw (RuntimeException) target;
2106                    }
2107                }
2108
2109            }
2110        }
2111        // We get here either if class-based replacement was not needed or if it
2112        // was needed but produced the same object or if it could not be
2113        // computed.
2114
2115        // The object to return is the one we instantiated or a replacement for
2116        // it
2117        if (result != null && enableResolve) {
2118            result = resolveObject(result);
2119        }
2120        if (registeredResult != result) {
2121            registerObjectRead(result, newHandle, unshared);
2122        }
2123        return result;
2124    }
2125
2126    private InvalidClassException missingClassDescriptor() throws InvalidClassException {
2127        throw new InvalidClassException("Read null attempting to read class descriptor for object");
2128    }
2129
2130    /**
2131     * Read a string encoded in {@link DataInput modified UTF-8} from the
2132     * receiver. Return the string read.
2133     *
2134     * @param unshared
2135     *            read the object unshared
2136     * @return the string just read.
2137     * @throws IOException
2138     *             If an IO exception happened when reading the String.
2139     */
2140    private Object readNewString(boolean unshared) throws IOException {
2141        Object result = input.readUTF();
2142        if (enableResolve) {
2143            result = resolveObject(result);
2144        }
2145        registerObjectRead(result, nextHandle(), unshared);
2146
2147        return result;
2148    }
2149
2150    /**
2151     * Read a new String in UTF format from the receiver. Return the string
2152     * read.
2153     *
2154     * @param unshared
2155     *            read the object unshared
2156     * @return the string just read.
2157     *
2158     * @throws IOException
2159     *             If an IO exception happened when reading the String.
2160     */
2161    private Object readNewLongString(boolean unshared) throws IOException {
2162        long length = input.readLong();
2163        Object result = input.decodeUTF((int) length);
2164        if (enableResolve) {
2165            result = resolveObject(result);
2166        }
2167        registerObjectRead(result, nextHandle(), unshared);
2168
2169        return result;
2170    }
2171
2172    /**
2173     * Reads the next object from the source stream.
2174     *
2175     * @return the object read from the source stream.
2176     * @throws ClassNotFoundException
2177     *             if the class of one of the objects in the object graph cannot
2178     *             be found.
2179     * @throws IOException
2180     *             if an error occurs while reading from the source stream.
2181     * @throws OptionalDataException
2182     *             if primitive data types were found instead of an object.
2183     * @see ObjectOutputStream#writeObject(Object)
2184     */
2185    public final Object readObject() throws OptionalDataException,
2186            ClassNotFoundException, IOException {
2187        return readObject(false);
2188    }
2189
2190    /**
2191     * Reads the next unshared object from the source stream.
2192     *
2193     * @return the new object read.
2194     * @throws ClassNotFoundException
2195     *             if the class of one of the objects in the object graph cannot
2196     *             be found.
2197     * @throws IOException
2198     *             if an error occurs while reading from the source stream.
2199     * @see ObjectOutputStream#writeUnshared
2200     */
2201    public Object readUnshared() throws IOException, ClassNotFoundException {
2202        return readObject(true);
2203    }
2204
2205    private Object readObject(boolean unshared) throws OptionalDataException,
2206            ClassNotFoundException, IOException {
2207        boolean restoreInput = (primitiveData == input);
2208        if (restoreInput) {
2209            primitiveData = emptyStream;
2210        }
2211
2212        // This is the spec'ed behavior in JDK 1.2. Very bizarre way to allow
2213        // behavior overriding.
2214        if (subclassOverridingImplementation && !unshared) {
2215            return readObjectOverride();
2216        }
2217
2218        // If we still had primitive types to read, should we discard them
2219        // (reset the primitiveTypes stream) or leave as is, so that attempts to
2220        // read primitive types won't read 'past data' ???
2221        Object result;
2222        try {
2223            // We need this so we can tell when we are returning to the
2224            // original/outside caller
2225            if (++nestedLevels == 1) {
2226                // Remember the caller's class loader
2227                // BEGIN android-changed
2228                callerClassLoader = getClosestUserClassLoader();
2229                // END android-changed
2230            }
2231
2232            result = readNonPrimitiveContent(unshared);
2233            if (restoreInput) {
2234                primitiveData = input;
2235            }
2236        } finally {
2237            // We need this so we can tell when we are returning to the
2238            // original/outside caller
2239            if (--nestedLevels == 0) {
2240                // We are going to return to the original caller, perform
2241                // cleanups.
2242                // No more need to remember the caller's class loader
2243                callerClassLoader = null;
2244            }
2245        }
2246
2247        // Done reading this object. Is it time to return to the original
2248        // caller? If so we need to perform validations first.
2249        if (nestedLevels == 0 && validations != null) {
2250            // We are going to return to the original caller. If validation is
2251            // enabled we need to run them now and then cleanup the validation
2252            // collection
2253            try {
2254                for (InputValidationDesc element : validations) {
2255                    element.validator.validateObject();
2256                }
2257            } finally {
2258                // Validations have to be renewed, since they are only called
2259                // from readObject
2260                validations = null;
2261            }
2262        }
2263        return result;
2264    }
2265
2266    // BEGIN android-added
2267    private static final ClassLoader bootstrapLoader
2268            = Object.class.getClassLoader();
2269    private static final ClassLoader systemLoader
2270            = ClassLoader.getSystemClassLoader();
2271
2272    /**
2273     * Searches up the call stack to find the closest user-defined class loader.
2274     *
2275     * @return a user-defined class loader or null if one isn't found
2276     */
2277    private static ClassLoader getClosestUserClassLoader() {
2278        Class<?>[] stackClasses = VMStack.getClasses(-1, false);
2279        for (Class<?> stackClass : stackClasses) {
2280            ClassLoader loader = stackClass.getClassLoader();
2281            if (loader != null && loader != bootstrapLoader
2282                    && loader != systemLoader) {
2283                return loader;
2284            }
2285        }
2286        return null;
2287    }
2288    // END android-added
2289
2290    /**
2291     * Method to be overridden by subclasses to read the next object from the
2292     * source stream.
2293     *
2294     * @return the object read from the source stream.
2295     * @throws ClassNotFoundException
2296     *             if the class of one of the objects in the object graph cannot
2297     *             be found.
2298     * @throws IOException
2299     *             if an error occurs while reading from the source stream.
2300     * @throws OptionalDataException
2301     *             if primitive data types were found instead of an object.
2302     * @see ObjectOutputStream#writeObjectOverride
2303     */
2304    protected Object readObjectOverride() throws OptionalDataException,
2305            ClassNotFoundException, IOException {
2306        if (input == null) {
2307            return null;
2308        }
2309        // Subclasses must override.
2310        throw new IOException();
2311    }
2312
2313    /**
2314     * Reads a short (16 bit) from the source stream.
2315     *
2316     * @return the short value read from the source stream.
2317     * @throws IOException
2318     *             if an error occurs while reading from the source stream.
2319     */
2320    public short readShort() throws IOException {
2321        return primitiveTypes.readShort();
2322    }
2323
2324    /**
2325     * Reads and validates the ObjectInputStream header from the source stream.
2326     *
2327     * @throws IOException
2328     *             if an error occurs while reading from the source stream.
2329     * @throws StreamCorruptedException
2330     *             if the source stream does not contain readable serialized
2331     *             objects.
2332     */
2333    protected void readStreamHeader() throws IOException,
2334            StreamCorruptedException {
2335        if (input.readShort() == STREAM_MAGIC
2336                && input.readShort() == STREAM_VERSION) {
2337            return;
2338        }
2339        throw new StreamCorruptedException();
2340    }
2341
2342    /**
2343     * Reads an unsigned byte (8 bit) from the source stream.
2344     *
2345     * @return the unsigned byte value read from the source stream packaged in
2346     *         an integer.
2347     * @throws EOFException
2348     *             if the end of the input is reached before the read
2349     *             request can be satisfied.
2350     * @throws IOException
2351     *             if an error occurs while reading from the source stream.
2352     */
2353    public int readUnsignedByte() throws IOException {
2354        return primitiveTypes.readUnsignedByte();
2355    }
2356
2357    /**
2358     * Reads an unsigned short (16 bit) from the source stream.
2359     *
2360     * @return the unsigned short value read from the source stream packaged in
2361     *         an integer.
2362     * @throws EOFException
2363     *             if the end of the input is reached before the read
2364     *             request can be satisfied.
2365     * @throws IOException
2366     *             if an error occurs while reading from the source stream.
2367     */
2368    public int readUnsignedShort() throws IOException {
2369        return primitiveTypes.readUnsignedShort();
2370    }
2371
2372    /**
2373     * Reads a string encoded in {@link DataInput modified UTF-8} from the
2374     * source stream.
2375     *
2376     * @return the string encoded in {@link DataInput modified UTF-8} read from
2377     *         the source stream.
2378     * @throws EOFException
2379     *             if the end of the input is reached before the read
2380     *             request can be satisfied.
2381     * @throws IOException
2382     *             if an error occurs while reading from the source stream.
2383     */
2384    public String readUTF() throws IOException {
2385        return primitiveTypes.readUTF();
2386    }
2387
2388    /**
2389     * Return the object previously read tagged with handle {@code handle}.
2390     *
2391     * @param handle
2392     *            The handle that this object was assigned when it was read.
2393     * @return the object previously read.
2394     *
2395     * @throws InvalidObjectException
2396     *             If there is no previously read object with this handle
2397     */
2398    private Object registeredObjectRead(Integer handle) throws InvalidObjectException {
2399        Object res = objectsRead.get(handle);
2400        if (res == UNSHARED_OBJ) {
2401            throw new InvalidObjectException("Cannot read back reference to unshared object");
2402        }
2403        return res;
2404    }
2405
2406    /**
2407     * Assume object {@code obj} has been read, and assign a handle to
2408     * it, {@code handle}.
2409     *
2410     * @param obj
2411     *            Non-null object being loaded.
2412     * @param handle
2413     *            An Integer, the handle to this object
2414     * @param unshared
2415     *            Boolean, indicates that caller is reading in unshared mode
2416     *
2417     * @see #nextHandle
2418     */
2419    private void registerObjectRead(Object obj, Integer handle, boolean unshared) {
2420        objectsRead.put(handle, unshared ? UNSHARED_OBJ : obj);
2421    }
2422
2423    /**
2424     * Registers a callback for post-deserialization validation of objects. It
2425     * allows to perform additional consistency checks before the {@code
2426     * readObject()} method of this class returns its result to the caller. This
2427     * method can only be called from within the {@code readObject()} method of
2428     * a class that implements "special" deserialization rules. It can be called
2429     * multiple times. Validation callbacks are then done in order of decreasing
2430     * priority, defined by {@code priority}.
2431     *
2432     * @param object
2433     *            an object that can validate itself by receiving a callback.
2434     * @param priority
2435     *            the validator's priority.
2436     * @throws InvalidObjectException
2437     *             if {@code object} is {@code null}.
2438     * @throws NotActiveException
2439     *             if this stream is currently not reading objects. In that
2440     *             case, calling this method is not allowed.
2441     * @see ObjectInputValidation#validateObject()
2442     */
2443    public synchronized void registerValidation(ObjectInputValidation object,
2444            int priority) throws NotActiveException, InvalidObjectException {
2445        // Validation can only be registered when inside readObject calls
2446        Object instanceBeingRead = this.currentObject;
2447
2448        // We can't be called from just anywhere. There are rules.
2449        if (instanceBeingRead == null && nestedLevels == 0) {
2450            throw new NotActiveException();
2451        }
2452        if (object == null) {
2453            throw new InvalidObjectException("Callback object cannot be null");
2454        }
2455        // From now on it is just insertion in a SortedCollection. Since
2456        // the Java class libraries don't provide that, we have to
2457        // implement it from scratch here.
2458        InputValidationDesc desc = new InputValidationDesc();
2459        desc.validator = object;
2460        desc.priority = priority;
2461        // No need for this, validateObject does not take a parameter
2462        // desc.toValidate = instanceBeingRead;
2463        if (validations == null) {
2464            validations = new InputValidationDesc[1];
2465            validations[0] = desc;
2466        } else {
2467            int i = 0;
2468            for (; i < validations.length; i++) {
2469                InputValidationDesc validation = validations[i];
2470                // Sorted, higher priority first.
2471                if (priority >= validation.priority) {
2472                    break; // Found the index where to insert
2473                }
2474            }
2475            InputValidationDesc[] oldValidations = validations;
2476            int currentSize = oldValidations.length;
2477            validations = new InputValidationDesc[currentSize + 1];
2478            System.arraycopy(oldValidations, 0, validations, 0, i);
2479            System.arraycopy(oldValidations, i, validations, i + 1, currentSize
2480                    - i);
2481            validations[i] = desc;
2482        }
2483    }
2484
2485    /**
2486     * Reset the collection of objects already loaded by the receiver.
2487     */
2488    private void resetSeenObjects() {
2489        objectsRead = new HashMap<Integer, Object>();
2490        nextHandle = baseWireHandle;
2491        primitiveData = emptyStream;
2492    }
2493
2494    /**
2495     * Reset the receiver. The collection of objects already read by the
2496     * receiver is reset, and internal structures are also reset so that the
2497     * receiver knows it is in a fresh clean state.
2498     */
2499    private void resetState() {
2500        resetSeenObjects();
2501        hasPushbackTC = false;
2502        pushbackTC = 0;
2503        // nestedLevels = 0;
2504    }
2505
2506    /**
2507     * Loads the Java class corresponding to the class descriptor {@code
2508     * osClass} that has just been read from the source stream.
2509     *
2510     * @param osClass
2511     *            an ObjectStreamClass read from the source stream.
2512     * @return a Class corresponding to the descriptor {@code osClass}.
2513     * @throws ClassNotFoundException
2514     *             if the class for an object cannot be found.
2515     * @throws IOException
2516     *             if an I/O error occurs while creating the class.
2517     * @see ObjectOutputStream#annotateClass(Class)
2518     */
2519    protected Class<?> resolveClass(ObjectStreamClass osClass)
2520            throws IOException, ClassNotFoundException {
2521        // fastpath: obtain cached value
2522        Class<?> cls = osClass.forClass();
2523        if (cls == null) {
2524            // slowpath: resolve the class
2525            String className = osClass.getName();
2526
2527            // if it is primitive class, for example, long.class
2528            cls = PRIMITIVE_CLASSES.get(className);
2529
2530            if (cls == null) {
2531                // not primitive class
2532                // Use the first non-null ClassLoader on the stack. If null, use
2533                // the system class loader
2534                cls = Class.forName(className, true, callerClassLoader);
2535            }
2536        }
2537        return cls;
2538    }
2539
2540    /**
2541     * Allows trusted subclasses to substitute the specified original {@code
2542     * object} with a new object. Object substitution has to be activated first
2543     * with calling {@code enableResolveObject(true)}. This implementation just
2544     * returns {@code object}.
2545     *
2546     * @param object
2547     *            the original object for which a replacement may be defined.
2548     * @return the replacement object for {@code object}.
2549     * @throws IOException
2550     *             if any I/O error occurs while creating the replacement
2551     *             object.
2552     * @see #enableResolveObject
2553     * @see ObjectOutputStream#enableReplaceObject
2554     * @see ObjectOutputStream#replaceObject
2555     */
2556    protected Object resolveObject(Object object) throws IOException {
2557        // By default no object replacement. Subclasses can override
2558        return object;
2559    }
2560
2561    /**
2562     * Skips {@code length} bytes on the source stream. This method should not
2563     * be used to skip bytes at any arbitrary position, just when reading
2564     * primitive data types (int, char etc).
2565     *
2566     * @param length
2567     *            the number of bytes to skip.
2568     * @return the number of bytes actually skipped.
2569     * @throws IOException
2570     *             if an error occurs while skipping bytes on the source stream.
2571     * @throws NullPointerException
2572     *             if the source stream is {@code null}.
2573     */
2574    public int skipBytes(int length) throws IOException {
2575        // To be used with available. Ok to call if reading primitive buffer
2576        if (input == null) {
2577            throw new NullPointerException();
2578        }
2579
2580        int offset = 0;
2581        while (offset < length) {
2582            checkReadPrimitiveTypes();
2583            long skipped = primitiveData.skip(length - offset);
2584            if (skipped == 0) {
2585                return offset;
2586            }
2587            offset += (int) skipped;
2588        }
2589        return length;
2590    }
2591
2592    /**
2593     * Verify if the SUID & the base name for descriptor
2594     * <code>loadedStreamClass</code>matches
2595     * the SUID & the base name of the corresponding loaded class and
2596     * init private fields.
2597     *
2598     * @param loadedStreamClass
2599     *            An ObjectStreamClass that was loaded from the stream.
2600     *
2601     * @throws InvalidClassException
2602     *             If the SUID of the stream class does not match the VM class
2603     */
2604    private void verifyAndInit(ObjectStreamClass loadedStreamClass)
2605            throws InvalidClassException {
2606
2607        Class<?> localClass = loadedStreamClass.forClass();
2608        ObjectStreamClass localStreamClass = ObjectStreamClass
2609                .lookupStreamClass(localClass);
2610
2611        if (loadedStreamClass.getSerialVersionUID() != localStreamClass
2612                .getSerialVersionUID()) {
2613            throw new InvalidClassException(loadedStreamClass.getName(),
2614                    "Incompatible class (SUID): " + loadedStreamClass +
2615                            " but expected " + localStreamClass);
2616        }
2617
2618        String loadedClassBaseName = getBaseName(loadedStreamClass.getName());
2619        String localClassBaseName = getBaseName(localStreamClass.getName());
2620
2621        if (!loadedClassBaseName.equals(localClassBaseName)) {
2622            throw new InvalidClassException(loadedStreamClass.getName(),
2623                    String.format("Incompatible class (base name): %s but expected %s",
2624                            loadedClassBaseName, localClassBaseName));
2625        }
2626
2627        loadedStreamClass.initPrivateFields(localStreamClass);
2628    }
2629
2630    private static String getBaseName(String fullName) {
2631        int k = fullName.lastIndexOf('.');
2632
2633        if (k == -1 || k == (fullName.length() - 1)) {
2634            return fullName;
2635        }
2636        return fullName.substring(k + 1);
2637    }
2638
2639    // Avoid recursive defining.
2640    private static void checkedSetSuperClassDesc(ObjectStreamClass desc,
2641            ObjectStreamClass superDesc) throws StreamCorruptedException {
2642        if (desc.equals(superDesc)) {
2643            throw new StreamCorruptedException();
2644        }
2645        desc.setSuperclass(superDesc);
2646    }
2647}
2648