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