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