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