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