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