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