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
2056e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughesimport java.lang.ref.SoftReference;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Constructor;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Field;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Method;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.reflect.Modifier;
25f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonimport java.lang.reflect.Proxy;
26b5bde2fd72189192b52e726a2d606d70c3c8a34bElliott Hughesimport java.nio.ByteOrder;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.MessageDigest;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.NoSuchAlgorithmException;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Comparator;
327d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughesimport java.util.HashMap;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.WeakHashMap;
35f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesimport libcore.io.Memory;
366186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.EmptyArray;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Represents a descriptor for identifying a class during serialization and
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * deserialization. Information contained in the descriptor includes the name
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and SUID of the class as well as field names and types. Information inherited
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from the superclasses is also taken into account.
43f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see ObjectOutputStream
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see ObjectInputStream
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.Class
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ObjectStreamClass implements Serializable {
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // No need to compute the SUID for ObjectStreamClass, just use the value
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // below
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -6120832682080437368L;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Name of the field that contains the SUID value (if present)
55f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final String UID_FIELD_NAME = "serialVersionUID";
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
57f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    static final long CONSTRUCTOR_IS_NOT_RESOLVED = -1;
58f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
59693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes    private static final int CLASS_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.FINAL |
60693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            Modifier.INTERFACE | Modifier.ABSTRACT;
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes    private static final int FIELD_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.PRIVATE |
63693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
64693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            Modifier.TRANSIENT;
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
66693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes    private static final int METHOD_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.PRIVATE |
67693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED |
68693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT;
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes    private static final Class<?>[] READ_PARAM_TYPES = new Class[] { ObjectInputStream.class };
71693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes    private static final Class<?>[] WRITE_PARAM_TYPES = new Class[] { ObjectOutputStream.class };
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant indicating that the class has no Serializable fields.
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * used to fetch field serialPersistentFields and checking its type
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static final Class<?> ARRAY_OF_FIELDS;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static {
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
85f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            ARRAY_OF_FIELDS = Class.forName("[Ljava.io.ObjectStreamField;");
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (ClassNotFoundException e) {
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // This should not happen
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new AssertionError(e);
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final String CLINIT_NAME = "<clinit>";
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int CLINIT_MODIFIERS = Modifier.STATIC;
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final String CLINIT_SIGNATURE = "()V";
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Used to determine if an object is Serializable or Externalizable
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final Class<Serializable> SERIALIZABLE = Serializable.class;
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final Class<Externalizable> EXTERNALIZABLE = Externalizable.class;
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Used to test if the object is a String or a class.
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static final Class<String> STRINGCLASS = String.class;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static final Class<?> CLASSCLASS = Class.class;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static final Class<ObjectStreamClass> OBJECTSTREAMCLASSCLASS = ObjectStreamClass.class;
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
110f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient Method methodWriteReplace;
111f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
112f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient Method methodReadResolve;
113f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
114f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient Method methodWriteObject;
115f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
116f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient Method methodReadObject;
117f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
118f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient Method methodReadObjectNoData;
119f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
120f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
121f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Indicates whether the class properties resolved
122f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
123f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #resolveProperties()
124f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     */
125f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient boolean arePropertiesResolved;
126f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
127f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
128f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Cached class properties
129f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
130f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #resolveProperties()
131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isSerializable()
132f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isExternalizable()
133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isProxy()
134f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isEnum()
135f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     */
136f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient boolean isSerializable;
137f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient boolean isExternalizable;
138f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient boolean isProxy;
139f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient boolean isEnum;
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ClassDesc //
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Name of the class this descriptor represents
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient String className;
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Corresponding loaded class with the name above
14732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    private transient Class<?> resolvedClass;
14832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
14932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    private transient Class<?> resolvedConstructorClass;
150a40dc9f768eb02dcfd7b1a659333757b148f7becJoel Dice    private transient long resolvedConstructorMethodId;
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Serial version UID of the class the descriptor represents
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient long svUID;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ClassDescInfo //
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Any combination of SC_WRITE_METHOD, SC_SERIALIZABLE and SC_EXTERNALIZABLE
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // (see ObjectStreamConstants)
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient byte flags;
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Descriptor for the superclass of the class associated with this
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // descriptor
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient ObjectStreamClass superclass;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Array of ObjectStreamField (see below) describing the fields of this
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // class
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient ObjectStreamField[] fields;
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Array of ObjectStreamField describing the serialized fields of this class
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient ObjectStreamField[] loadFields;
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1727d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes    // ObjectStreamField doesn't override hashCode or equals, so this is equivalent to an
1737d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes    // IdentityHashMap, which is fine for our purposes.
1747d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes    private transient HashMap<ObjectStreamField, Field> reflectionFields =
1757d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            new HashMap<ObjectStreamField, Field>();
1767d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes
177f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    // MethodID for deserialization constructor
178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private transient long constructor = CONSTRUCTOR_IS_NOT_RESOLVED;
179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    void setConstructor(long newConstructor) {
181f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        constructor = newConstructor;
182f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
183f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
184f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    long getConstructor() {
185f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return constructor;
186f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
187f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1887d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes    Field getReflectionField(ObjectStreamField osf) {
1897d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        synchronized (reflectionFields) {
1907d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            Field field = reflectionFields.get(osf);
1917d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            if (field != null) {
1927d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                return field;
1937d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            }
1947d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        }
1957d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes
1967d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        try {
1977d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            Class<?> declaringClass = forClass();
1987d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            Field field = declaringClass.getDeclaredField(osf.getName());
1997d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            field.setAccessible(true);
2007d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            synchronized (reflectionFields) {
2017d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                reflectionFields.put(osf, field);
2027d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            }
2037d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            return reflectionFields.get(osf);
2047d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        } catch (NoSuchFieldException ex) {
2057d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            // The caller messed up. We'll return null and won't try to resolve this again.
2067d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            return null;
2077d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        }
2087d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes    }
2097d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If an ObjectStreamClass describes an Externalizable class, it (the
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * descriptor) should not have field descriptors (ObjectStreamField) at all.
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The ObjectStreamClass that gets saved should simply have no field info.
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is a footnote in page 1511 (class Serializable) of "The Java Class
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Libraries, Second Edition, Vol. I".
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new instance of this class.
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ObjectStreamClass() {
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
225f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Compute class descriptor for a given class <code>cl</code>.
226f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.langClass for which to compute the corresponding
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            descriptor
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the computer class descriptor
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
232f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private static ObjectStreamClass createClassDesc(Class<?> cl) {
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectStreamClass result = new ObjectStreamClass();
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
236f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        boolean isArray = cl.isArray();
237f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        boolean serializable = isSerializable(cl);
238f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        boolean externalizable = isExternalizable(cl);
239f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
240f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        result.isSerializable = serializable;
241f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        result.isExternalizable = externalizable;
242f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Now we fill in the values
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result.setName(cl.getName());
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result.setClass(cl);
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Class<?> superclass = cl.getSuperclass();
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (superclass != null) {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result.setSuperclass(lookup(superclass));
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Field[] declaredFields = null;
252f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
253f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        // Compute the SUID
2547d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        if (serializable || externalizable) {
255f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (result.isEnum() || result.isProxy()) {
256f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                result.setSerialVersionUID(0L);
257f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
258f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                declaredFields = cl.getDeclaredFields();
2597d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                result.setSerialVersionUID(computeSerialVersionUID(cl, declaredFields));
260f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Serializables need field descriptors
264f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (serializable && !isArray) {
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (declaredFields == null) {
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                declaredFields = cl.getDeclaredFields();
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result.buildFieldDescriptors(declaredFields);
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Externalizables or arrays do not need FieldDesc info
271f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            result.setFields(NO_FIELDS);
272f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
273f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
274f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        // Copy all fields to loadFields - they should be read by default in
275f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        // ObjectInputStream.defaultReadObject() method
276f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        ObjectStreamField[] fields = result.getFields();
277f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
278f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (fields != null) {
279f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            ObjectStreamField[] loadFields = new ObjectStreamField[fields.length];
280f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
281f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            for (int i = 0; i < fields.length; ++i) {
282f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                loadFields[i] = new ObjectStreamField(fields[i].getName(),
283f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        fields[i].getType(), fields[i].isUnshared());
284f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
285f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // resolve type string to init typeString field in
286f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // ObjectStreamField
287f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                loadFields[i].getTypeString();
288f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
289f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            result.setLoadFields(loadFields);
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte flags = 0;
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (externalizable) {
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
295f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (serializable) {
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            flags |= ObjectStreamConstants.SC_SERIALIZABLE;
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
299f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        result.methodWriteReplace = findMethod(cl, "writeReplace");
300f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        result.methodReadResolve = findMethod(cl, "readResolve");
301693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes        result.methodWriteObject = findPrivateMethod(cl, "writeObject", WRITE_PARAM_TYPES);
302693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes        result.methodReadObject = findPrivateMethod(cl, "readObject", READ_PARAM_TYPES);
303693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes        result.methodReadObjectNoData = findPrivateMethod(cl, "readObjectNoData", EmptyArray.CLASS);
304f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (result.hasMethodWriteObject()) {
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            flags |= ObjectStreamConstants.SC_WRITE_METHOD;
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result.setFlags(flags);
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Builds the collection of field descriptors for the receiver
314f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param declaredFields
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            collection of java.lang.reflect.Field for which to compute
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            field descriptors
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void buildFieldDescriptors(Field[] declaredFields) {
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // We could find the field ourselves in the collection, but calling
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // reflect is easier. Optimize if needed.
3227d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        final Field f = ObjectStreamClass.fieldSerialPersistentFields(this.forClass());
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If we could not find the emulated fields, we'll have to compute
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // dumpable fields from reflect fields
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean useReflectFields = f == null; // Assume we will compute the
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // fields to dump based on the
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // reflect fields
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectStreamField[] _fields = null;
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!useReflectFields) {
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // The user declared a collection of emulated fields. Use them.
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // We have to be able to fetch its value, even if it is private
333ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes            f.setAccessible(true);
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // static field, pass null
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                _fields = (ObjectStreamField[]) f.get(null);
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IllegalAccessException ex) {
3387d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                throw new AssertionError(ex);
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Compute collection of dumpable fields based on reflect fields
3427d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            List<ObjectStreamField> serializableFields =
3437d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                    new ArrayList<ObjectStreamField>(declaredFields.length);
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Filter, we are only interested in fields that are serializable
3457d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes            for (Field declaredField : declaredFields) {
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int modifiers = declaredField.getModifiers();
3477d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
3487d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                    ObjectStreamField field = new ObjectStreamField(declaredField.getName(),
3497d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                            declaredField.getType());
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serializableFields.add(field);
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (serializableFields.size() == 0) {
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                _fields = NO_FIELDS; // If no serializable fields, share the
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // special value so that users can test
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
3587d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes                _fields = serializableFields.toArray(new ObjectStreamField[serializableFields.size()]);
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
3617d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        Arrays.sort(_fields);
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // assign offsets
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int primOffset = 0, objectOffset = 0;
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < _fields.length; i++) {
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?> type = _fields[i].getType();
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (type.isPrimitive()) {
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                _fields[i].offset = primOffset;
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                primOffset += primitiveSize(type);
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                _fields[i].offset = objectOffset++;
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields = _fields;
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
375f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compute and return the Serial Version UID of the class {@code cl}.
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The value is computed based on the class name, superclass chain, field
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * names, method names, modifiers, etc.
380f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class for which to compute the SUID
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param fields
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            cl.getDeclaredFields(), pre-computed by the caller
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the value of SUID of this class
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static long computeSerialVersionUID(Class<?> cl, Field[] fields) {
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * First we should try to fetch the static slot 'static final long
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * serialVersionUID'. If it is defined, return it. If not defined, we
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * really need to compute SUID using SHAOutputStream
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < fields.length; i++) {
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            final Field field = fields[i];
395e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            if (field.getType() == long.class) {
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int modifiers = field.getModifiers();
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (UID_FIELD_NAME.equals(field.getName())) {
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /*
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * We need to be able to see it even if we have no
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * visibility. That is why we set accessible first (new
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * API in reflect 1.2)
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         */
404ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes                        field.setAccessible(true);
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        try {
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // Static field, parameter is ignored
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return field.getLong(null);
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } catch (IllegalAccessException iae) {
409b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                            throw new RuntimeException("Error fetching SUID: " + iae);
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        MessageDigest digest;
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
418f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            digest = MessageDigest.getInstance("SHA");
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (NoSuchAlgorithmException e) {
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new Error(e);
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ByteArrayOutputStream sha = new ByteArrayOutputStream();
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            DataOutputStream output = new DataOutputStream(sha);
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            output.writeUTF(cl.getName());
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int classModifiers = CLASS_MODIFIERS_MASK & cl.getModifiers();
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * Workaround for 1F9LOQO. Arrays are ABSTRACT in JDK, but that is
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * not in the specification. Since we want to be compatible for
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * X-loading, we have to pretend we have the same shape
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean isArray = cl.isArray();
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isArray) {
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                classModifiers |= Modifier.ABSTRACT;
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Required for JDK UID compatibility
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (cl.isInterface() && !Modifier.isPublic(classModifiers)) {
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                classModifiers &= ~Modifier.ABSTRACT;
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            output.writeInt(classModifiers);
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * In JDK1.2 arrays implement Cloneable and Serializable but not in
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * JDK 1.1.7. So, JDK 1.2 "pretends" arrays have no interfaces when
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * computing SHA-1 to be compatible.
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isArray) {
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Interface information
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Class<?>[] interfaces = cl.getInterfaces();
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (interfaces.length > 1) {
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // Only attempt to sort if really needed (saves object
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // creation, etc)
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    Comparator<Class<?>> interfaceComparator = new Comparator<Class<?>>() {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        public int compare(Class<?> itf1, Class<?> itf2) {
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return itf1.getName().compareTo(itf2.getName());
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    };
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    Arrays.sort(interfaces, interfaceComparator);
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Dump them
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int i = 0; i < interfaces.length; i++) {
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeUTF(interfaces[i].getName());
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Field information
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields.length > 1) {
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Only attempt to sort if really needed (saves object creation,
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // etc)
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Comparator<Field> fieldComparator = new Comparator<Field>() {
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    public int compare(Field field1, Field field2) {
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return field1.getName().compareTo(field2.getName());
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                };
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Arrays.sort(fields, fieldComparator);
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Dump them
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < fields.length; i++) {
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Field field = fields[i];
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int modifiers = field.getModifiers() & FIELD_MODIFIERS_MASK;
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48405895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes                boolean skip = Modifier.isPrivate(modifiers) &&
48505895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes                        (Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers));
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!skip) {
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // write name, modifier & "descriptor" of all but private
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // static and private transient
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeUTF(field.getName());
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeInt(modifiers);
49105895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes                    output.writeUTF(descriptorForFieldSignature(getFieldSignature(field)));
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * Normally constructors come before methods (because <init> <
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * anyMethodName). However, <clinit> is an exception. Besides,
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * reflect will not let us get to it.
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (hasClinit(cl)) {
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // write name, modifier & "descriptor"
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                output.writeUTF(CLINIT_NAME);
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                output.writeInt(CLINIT_MODIFIERS);
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                output.writeUTF(CLINIT_SIGNATURE);
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Constructor information
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Constructor<?>[] constructors = cl.getDeclaredConstructors();
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (constructors.length > 1) {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Only attempt to sort if really needed (saves object creation,
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // etc)
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Comparator<Constructor<?>> constructorComparator = new Comparator<Constructor<?>>() {
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    public int compare(Constructor<?> ctr1, Constructor<?> ctr2) {
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // All constructors have same name, so we sort based on
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // signature
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return (getConstructorSignature(ctr1)
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                .compareTo(getConstructorSignature(ctr2)));
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                };
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Arrays.sort(constructors, constructorComparator);
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Dump them
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < constructors.length; i++) {
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Constructor<?> constructor = constructors[i];
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int modifiers = constructor.getModifiers()
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        & METHOD_MODIFIERS_MASK;
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                boolean isPrivate = Modifier.isPrivate(modifiers);
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isPrivate) {
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * write name, modifier & "descriptor" of all but private
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * ones
533f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                     *
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * constructor.getName() returns the constructor name as
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * typed, not the VM name
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
537f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    output.writeUTF("<init>");
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeInt(modifiers);
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeUTF(descriptorForSignature(
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            getConstructorSignature(constructor)).replace('/',
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            '.'));
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Method information
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Method[] methods = cl.getDeclaredMethods();
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (methods.length > 1) {
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Comparator<Method> methodComparator = new Comparator<Method>() {
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    public int compare(Method m1, Method m2) {
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        int result = m1.getName().compareTo(m2.getName());
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (result == 0) {
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // same name, signature will tell which one comes
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // first
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return getMethodSignature(m1).compareTo(
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    getMethodSignature(m2));
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return result;
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                };
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Arrays.sort(methods, methodComparator);
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Dump them
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < methods.length; i++) {
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Method method = methods[i];
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int modifiers = method.getModifiers() & METHOD_MODIFIERS_MASK;
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                boolean isPrivate = Modifier.isPrivate(modifiers);
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isPrivate) {
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // write name, modifier & "descriptor" of all but private
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // ones
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeUTF(method.getName());
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeInt(modifiers);
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    output.writeUTF(descriptorForSignature(
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            getMethodSignature(method)).replace('/', '.'));
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IOException e) {
578b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new RuntimeException(e + " computing SHA-1/SUID");
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // now compute the UID based on the SHA
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] hash = digest.digest(sha.toByteArray());
583f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes        return Memory.peekLong(hash, 0, ByteOrder.LITTLE_ENDIAN);
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
587b5bde2fd72189192b52e726a2d606d70c3c8a34bElliott Hughes     * Returns what the serialization specification calls "descriptor" given a
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field signature.
589f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param signature
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a field signature
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return containing the descriptor
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static String descriptorForFieldSignature(String signature) {
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return signature.replace('.', '/');
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
599b5bde2fd72189192b52e726a2d606d70c3c8a34bElliott Hughes     * Return what the serialization specification calls "descriptor" given a
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method/constructor signature.
601f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param signature
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a method or constructor signature
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return containing the descriptor
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static String descriptorForSignature(String signature) {
607f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        return signature.substring(signature.indexOf("("));
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return the java.lang.reflect.Field {@code serialPersistentFields}
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if class {@code cl} implements it. Return null otherwise.
613f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code java.lang.reflect.Field} if the class has
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         serialPersistentFields {@code null} if the class does not
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         have serialPersistentFields
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static Field fieldSerialPersistentFields(Class<?> cl) {
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
622f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            Field f = cl.getDeclaredField("serialPersistentFields");
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int modifiers = f.getModifiers();
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (Modifier.isStatic(modifiers) && Modifier.isPrivate(modifiers)
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && Modifier.isFinal(modifiers)) {
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (f.getType() == ARRAY_OF_FIELDS) {
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return f;
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (NoSuchFieldException nsm) {
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Ignored
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the class (java.lang.Class) for this descriptor.
638f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the class in the local VM that this descriptor represents;
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code null} if there is no corresponding class.
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Class<?> forClass() {
64332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        return resolvedClass;
64432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    }
64532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
6466523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes    /**
6476523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes     * Create and return a new instance of class 'instantiationClass'
6486523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes     * using JNI to call the constructor chosen by resolveConstructorClass.
6496523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes     *
6506523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes     * The returned instance may have uninitialized fields, including final fields.
6516523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes     */
6526523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes    Object newInstance(Class<?> instantiationClass) throws InvalidClassException {
6536523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes        resolveConstructorClass(instantiationClass);
6546523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes        return newInstance(instantiationClass, resolvedConstructorMethodId);
6556523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes    }
656a40dc9f768eb02dcfd7b1a659333757b148f7becJoel Dice    private static native Object newInstance(Class<?> instantiationClass, long methodId);
6576523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes
6586523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes    private Class<?> resolveConstructorClass(Class<?> objectClass) throws InvalidClassException {
65932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (resolvedConstructorClass != null) {
66032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            return resolvedConstructorClass;
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
66232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
66332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // The class of the instance may not be the same as the class of the
66432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // constructor to run
66532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // This is the constructor to run if Externalizable
66632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        Class<?> constructorClass = objectClass;
66732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
66832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // WARNING - What if the object is serializable and externalizable ?
66932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // Is that possible ?
67032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        boolean wasSerializable = (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
67132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (wasSerializable) {
67232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            // Now we must run the constructor of the class just above the
67332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            // one that implements Serializable so that slots that were not
67432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            // dumped can be initialized properly
67532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            while (constructorClass != null && ObjectStreamClass.isSerializable(constructorClass)) {
67632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes                constructorClass = constructorClass.getSuperclass();
67732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            }
67832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
67932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
68032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // Fetch the empty constructor, or null if none.
68132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        Constructor<?> constructor = null;
68232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (constructorClass != null) {
68332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            try {
68432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes                constructor = constructorClass.getDeclaredConstructor(EmptyArray.CLASS);
68532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            } catch (NoSuchMethodException ignored) {
68632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            }
68732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
68832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
68932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // Has to have an empty constructor
69032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (constructor == null) {
69132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            String className = constructorClass != null ? constructorClass.getName() : null;
69232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            throw new InvalidClassException(className, "IllegalAccessException");
69332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
69432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
69532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        int constructorModifiers = constructor.getModifiers();
69632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        boolean isPublic = Modifier.isPublic(constructorModifiers);
69732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        boolean isProtected = Modifier.isProtected(constructorModifiers);
69832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        boolean isPrivate = Modifier.isPrivate(constructorModifiers);
69932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
70032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // Now we must check if the empty constructor is visible to the
70132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // instantiation class
70232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        boolean wasExternalizable = (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
70332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (isPrivate || (wasExternalizable && !isPublic)) {
70432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            throw new InvalidClassException(constructorClass.getName(), "IllegalAccessException");
70532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
70632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
70732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // We know we are testing from a subclass, so the only other case
70832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // where the visibility is not allowed is when the constructor has
70932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // default visibility and the instantiation class is in a different
71032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        // package than the constructor class
71132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (!isPublic && !isProtected) {
71232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            // Not public, not private and not protected...means default
71332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            // visibility. Check if same package
71432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            if (!inSamePackage(constructorClass, objectClass)) {
71532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes                throw new InvalidClassException(constructorClass.getName(), "IllegalAccessException");
71632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            }
71732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
71832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
71932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        resolvedConstructorClass = constructorClass;
7206523532145f06d8c208ed7a9374d3ab6d8132e66Elliott Hughes        resolvedConstructorMethodId = getConstructorId(resolvedConstructorClass);
72132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        return constructorClass;
72232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    }
723a40dc9f768eb02dcfd7b1a659333757b148f7becJoel Dice    private static native long getConstructorId(Class<?> c);
72432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes
72532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    /**
72632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     * Checks if two classes belong to the same package.
72732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     *
72832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     * @param c1
72932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     *            one of the classes to test.
73032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     * @param c2
73132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     *            the other class to test.
73232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     * @return {@code true} if the two classes belong to the same package,
73332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     *         {@code false} otherwise.
73432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes     */
73532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes    private boolean inSamePackage(Class<?> c1, Class<?> c2) {
73632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        String nameC1 = c1.getName();
73732ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        String nameC2 = c2.getName();
73832ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        int indexDotC1 = nameC1.lastIndexOf('.');
73932ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        int indexDotC2 = nameC2.lastIndexOf('.');
74032ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (indexDotC1 != indexDotC2) {
74132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            return false; // cannot be in the same package if indices are not the same
74232ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
74332ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        if (indexDotC1 == -1) {
74432ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes            return true; // both of them are in default package
74532ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        }
74632ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        return nameC1.regionMatches(0, nameC2, 0, indexDotC1);
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return a String representing the signature for a Constructor {@code c}.
751f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.reflect.Constructor for which to compute the
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            signature
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the constructor's signature
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static native String getConstructorSignature(Constructor<?> c);
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a field descriptor of the class represented by this class
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * descriptor.
762f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the desired field.
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the field identified by {@code name} or {@code null} if there is
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         no such field.
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ObjectStreamField getField(String name) {
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectStreamField[] allFields = getFields();
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < allFields.length; i++) {
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ObjectStreamField f = allFields[i];
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (f.getName().equals(name)) {
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return f;
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the collection of field descriptors for the fields of the
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * corresponding class
782f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the receiver's collection of declared fields for the class it
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         represents
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ObjectStreamField[] fields() {
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields == null) {
788f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            Class<?> forCl = forClass();
789f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (forCl != null && isSerializable() && !forCl.isArray()) {
790f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                buildFieldDescriptors(forCl.getDeclaredFields());
791f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
792f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // Externalizables or arrays do not need FieldDesc info
793f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                setFields(NO_FIELDS);
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return fields;
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a collection of field descriptors for the serialized fields of
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the class represented by this class descriptor.
802f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of field descriptors or an array of length zero if there
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         are no fields in this descriptor's class.
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ObjectStreamField[] getFields() {
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        copyFieldAttributes();
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return loadFields == null ? fields().clone() : loadFields.clone();
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
81178b020b8412d212fa052b7ddf630ca6058c846beElliott Hughes    private transient volatile List<ObjectStreamClass> cachedHierarchy;
81246241f2f67d7b90e20f3301861f807f330687821Elliott Hughes
81346241f2f67d7b90e20f3301861f807f330687821Elliott Hughes    List<ObjectStreamClass> getHierarchy() {
81446241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        List<ObjectStreamClass> result = cachedHierarchy;
81546241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        if (result == null) {
81646241f2f67d7b90e20f3301861f807f330687821Elliott Hughes            cachedHierarchy = result = makeHierarchy();
81746241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        }
81846241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        return result;
81946241f2f67d7b90e20f3301861f807f330687821Elliott Hughes    }
82046241f2f67d7b90e20f3301861f807f330687821Elliott Hughes
82146241f2f67d7b90e20f3301861f807f330687821Elliott Hughes    private List<ObjectStreamClass> makeHierarchy() {
82246241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        ArrayList<ObjectStreamClass> result = new ArrayList<ObjectStreamClass>();
82346241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuperclass()) {
82446241f2f67d7b90e20f3301861f807f330687821Elliott Hughes            result.add(0, osc);
82546241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        }
82646241f2f67d7b90e20f3301861f807f330687821Elliott Hughes        return result;
82746241f2f67d7b90e20f3301861f807f330687821Elliott Hughes    }
82846241f2f67d7b90e20f3301861f807f330687821Elliott Hughes
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
830f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * If a Class uses "serialPersistentFields" to define the serialized fields,
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this.loadFields cannot get the "unshared" information when deserializing
832f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * fields using current implementation of ObjectInputStream. This method
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provides a way to copy the "unshared" attribute from this.fields.
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void copyFieldAttributes() {
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((loadFields == null) || fields == null) {
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
840f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < loadFields.length; i++) {
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ObjectStreamField loadField = loadFields[i];
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String name = loadField.getName();
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int j = 0; j < fields.length; j++) {
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ObjectStreamField field = fields[j];
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (name.equals(field.getName())) {
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    loadField.setUnshared(field.isUnshared());
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    loadField.setOffset(field.getOffset());
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the collection of field descriptors for the input fields of the
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * corresponding class
858f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the receiver's collection of input fields for the class it
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         represents
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ObjectStreamField[] getLoadFields() {
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return loadFields;
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return a String representing the signature for a field {@code f}.
868f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param f
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.reflect.Field for which to compute the signature
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the field's signature
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static native String getFieldSignature(Field f);
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the flags for this descriptor, where possible combined values are
877f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_WRITE_METHOD
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_SERIALIZABLE
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_EXTERNALIZABLE
881f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return byte the receiver's flags for the class it represents
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    byte getFlags() {
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return flags;
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return a String representing the signature for a method {@code m}.
890f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param m
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.reflect.Method for which to compute the signature
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the method's signature
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static native String getMethodSignature(Method m);
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the name of the class represented by this descriptor.
899f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the fully qualified name of the class this descriptor represents.
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return className;
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the Serial Version User ID of the class represented by this
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * descriptor.
909f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the SUID for the class represented by this descriptor.
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public long getSerialVersionUID() {
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return svUID;
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the descriptor (ObjectStreamClass) of the superclass of the class
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * represented by the receiver.
919f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an ObjectStreamClass representing the superclass of the class
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         represented by the receiver.
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ObjectStreamClass getSuperclass() {
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return superclass;
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return true if the given class {@code cl} has the
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * compiler-generated method {@code clinit}. Even though it is
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * compiler-generated, it is used by the serialization code to compute SUID.
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is unfortunate, since it may depend on compiler optimizations in
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * some cases.
933f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the class has <clinit> {@code false}
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         if the class does not have <clinit>
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static native boolean hasClinit(Class<?> cl);
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return true if instances of class {@code cl} are Externalizable,
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * false otherwise.
944f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if instances of the class are Externalizable
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} if instances of the class are not
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Externalizable
950f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see Object#hashCode
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static boolean isExternalizable(Class<?> cl) {
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return EXTERNALIZABLE.isAssignableFrom(cl);
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return true if the type code
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <code>typecode<code> describes a primitive type
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param typecode a char describing the typecode
962f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @return {@code true} if the typecode represents a primitive type
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code false} if the typecode represents an Object type (including arrays)
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see Object#hashCode
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static boolean isPrimitiveType(char typecode) {
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return !(typecode == '[' || typecode == 'L');
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return true if instances of class {@code cl} are Serializable,
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * false otherwise.
974f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if instances of the class are Serializable
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} if instances of the class are not
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Serializable
980f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see Object#hashCode
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static boolean isSerializable(Class<?> cl) {
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return SERIALIZABLE.isAssignableFrom(cl);
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
988f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Resolves the class properties, if they weren't already
989f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     */
990f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private void resolveProperties() {
991f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (arePropertiesResolved) {
992f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            return;
993f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
994f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
995f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        Class<?> cl = forClass();
996f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        isProxy = Proxy.isProxyClass(cl);
997f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        isEnum = Enum.class.isAssignableFrom(cl);
998f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        isSerializable = isSerializable(cl);
999f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        isExternalizable = isExternalizable(cl);
1000f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1001f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        arePropertiesResolved = true;
1002f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1003f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1004f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean isSerializable() {
1005f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        resolveProperties();
1006f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return isSerializable;
1007f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1008f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1009f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean isExternalizable() {
1010f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        resolveProperties();
1011f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return isExternalizable;
1012f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1013f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1014f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean isProxy() {
1015f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        resolveProperties();
1016f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return isProxy;
1017f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1018f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1019f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean isEnum() {
1020f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        resolveProperties();
1021f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return isEnum;
1022f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1023f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1024f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /**
1025a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * Returns the descriptor for a serializable class.
1026a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * Returns null if the class doesn't implement {@code Serializable} or {@code Externalizable}.
1027f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
1029a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     *            a java.lang.Class for which to obtain the corresponding
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            descriptor
1031a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * @return the corresponding descriptor if the class is serializable or
1032a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     *         externalizable; null otherwise.
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static ObjectStreamClass lookup(Class<?> cl) {
1035f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        ObjectStreamClass osc = lookupStreamClass(cl);
10367d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        return (osc.isSerializable() || osc.isExternalizable()) ? osc : null;
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1040a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * Returns the descriptor for any class, whether or not the class
1041a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * implements Serializable or Externalizable.
1042f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
1043a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * @param cl
1044a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     *            a java.lang.Class for which to obtain the corresponding
1045a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     *            descriptor
1046a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * @return the descriptor
1047a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     * @since 1.6
1048a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes     */
1049a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes    public static ObjectStreamClass lookupAny(Class<?> cl) {
10507d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        return lookupStreamClass(cl);
1051a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes    }
1052a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes
1053a845eec505ce5314b1a8be3d8dd6cc46bda782f7Elliott Hughes    /**
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return the descriptor (ObjectStreamClass) corresponding to the class
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code cl}. Returns an ObjectStreamClass even if instances of the
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * class cannot be serialized
1057f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.langClass for which to obtain the corresponding
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            descriptor
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the corresponding descriptor
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static ObjectStreamClass lookupStreamClass(Class<?> cl) {
10647d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        WeakHashMap<Class<?>, ObjectStreamClass> tlc = getCache();
1065f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        ObjectStreamClass cachedValue = tlc.get(cl);
1066f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (cachedValue == null) {
1067f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            cachedValue = createClassDesc(cl);
1068f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            tlc.put(cl, cachedValue);
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1070f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return cachedValue;
1071f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1074adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
107556e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes     * A ThreadLocal cache for lookupStreamClass, with the possibility of discarding the thread
107656e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes     * local storage content when the heap is exhausted.
107756e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes     */
107856e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes    private static SoftReference<ThreadLocal<WeakHashMap<Class<?>, ObjectStreamClass>>> storage =
107956e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes            new SoftReference<ThreadLocal<WeakHashMap<Class<?>, ObjectStreamClass>>>(null);
108056e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes
108156e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes    private static WeakHashMap<Class<?>, ObjectStreamClass> getCache() {
108256e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes        ThreadLocal<WeakHashMap<Class<?>, ObjectStreamClass>> tls = storage.get();
108356e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes        if (tls == null) {
108456e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes            tls = new ThreadLocal<WeakHashMap<Class<?>, ObjectStreamClass>>() {
108556e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes                public WeakHashMap<Class<?>, ObjectStreamClass> initialValue() {
108656e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes                    return new WeakHashMap<Class<?>, ObjectStreamClass>();
108756e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes                }
108856e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes            };
108956e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes            storage = new SoftReference<ThreadLocal<WeakHashMap<Class<?>, ObjectStreamClass>>>(tls);
109056e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes        }
109156e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes        return tls.get();
109256e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes    }
109356e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes
109456e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes    /**
1095f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Return the java.lang.reflect.Method if class <code>cl</code> implements
1096f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * <code>methodName</code> . Return null otherwise.
1097f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
1100f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @return <code>java.lang.reflect.Method</code> if the class implements
1101f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *         writeReplace <code>null</code> if the class does not implement
1102f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *         writeReplace
1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1104f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    static Method findMethod(Class<?> cl, String methodName) {
1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Class<?> search = cl;
1106f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        Method method = null;
1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (search != null) {
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
1109f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                method = search.getDeclaredMethod(methodName, (Class[]) null);
1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (search == cl
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        || (method.getModifiers() & Modifier.PRIVATE) == 0) {
1112f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    method.setAccessible(true);
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return method;
1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (NoSuchMethodException nsm) {
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            search = search.getSuperclass();
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1123f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Return the java.lang.reflect.Method if class <code>cl</code> implements
1124f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * private <code>methodName</code> . Return null otherwise.
1125f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a java.lang.Class which to test
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code java.lang.reflect.Method} if the class implements
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         writeReplace {@code null} if the class does not implement
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         writeReplace
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1132f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    static Method findPrivateMethod(Class<?> cl, String methodName,
1133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            Class<?>[] param) {
1134f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        try {
1135f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            Method method = cl.getDeclaredMethod(methodName, param);
1136e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            if (Modifier.isPrivate(method.getModifiers()) && method.getReturnType() == void.class) {
1137f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                method.setAccessible(true);
1138f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                return method;
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1140f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        } catch (NoSuchMethodException nsm) {
1141f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            // Ignored
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1146f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean hasMethodWriteReplace() {
1147f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return (methodWriteReplace != null);
1148f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1149f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1150f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    Method getMethodWriteReplace() {
1151f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return methodWriteReplace;
1152f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1153f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1154f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean hasMethodReadResolve() {
1155f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return (methodReadResolve != null);
1156f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1158f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    Method getMethodReadResolve() {
1159f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return methodReadResolve;
1160f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1161f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1162f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean hasMethodWriteObject() {
1163f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return (methodWriteObject != null);
1164f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1165f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1166f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    Method getMethodWriteObject() {
1167f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return methodWriteObject;
1168f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1169f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean hasMethodReadObject() {
1171f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return (methodReadObject != null);
1172f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1173f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1174f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    Method getMethodReadObject() {
1175f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return methodReadObject;
1176f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1177f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    boolean hasMethodReadObjectNoData() {
1179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return (methodReadObjectNoData != null);
1180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1181f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1182f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    Method getMethodReadObjectNoData() {
1183f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return methodReadObjectNoData;
1184f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1185f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1186f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    void initPrivateFields(ObjectStreamClass desc) {
1187f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        methodWriteReplace = desc.methodWriteReplace;
1188f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        methodReadResolve = desc.methodReadResolve;
1189f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        methodWriteObject = desc.methodWriteObject;
1190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        methodReadObject = desc.methodReadObject;
1191f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        methodReadObjectNoData = desc.methodReadObjectNoData;
1192f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
1193f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the class (java.lang.Class) that the receiver represents
1196f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
1198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            aClass, the new class that the receiver describes
1199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setClass(Class<?> c) {
120132ef29bcbfdce08d58ea72bd15a12a96065bdbb6Elliott Hughes        resolvedClass = c;
1202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the collection of field descriptors for the fields of the
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * corresponding class
1207f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param f
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            ObjectStreamField[], the receiver's new collection of declared
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            fields for the class it represents
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setFields(ObjectStreamField[] f) {
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields = f;
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the collection of field descriptors for the input fields of the
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * corresponding class
1219f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param f
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            ObjectStreamField[], the receiver's new collection of input
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            fields for the class it represents
1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setLoadFields(ObjectStreamField[] f) {
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        loadFields = f;
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the flags for this descriptor, where possible combined values are
1230f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_WRITE_METHOD
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_SERIALIZABLE
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ObjectStreamConstants.SC_EXTERNALIZABLE
1234f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param b
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            byte, the receiver's new flags for the class it represents
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setFlags(byte b) {
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        flags = b;
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the name of the class represented by the receiver
1244f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newName
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a String, the new fully qualified name of the class the
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            receiver represents
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setName(String newName) {
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        className = newName;
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the Serial Version User ID of the class represented by the receiver
1255f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param l
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a long, the new SUID for the class represented by the receiver
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setSerialVersionUID(long l) {
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        svUID = l;
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the descriptor for the superclass of the class described by the
1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * receiver
1266f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param c
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            an ObjectStreamClass, the new ObjectStreamClass for the
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            superclass of the class represented by the receiver
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setSuperclass(ObjectStreamClass c) {
1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        superclass = c;
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int primitiveSize(Class<?> type) {
1276e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        if (type == byte.class || type == boolean.class) {
1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 1;
1278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1279e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        if (type == short.class || type == char.class) {
1280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 2;
1281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1282e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        if (type == int.class || type == float.class) {
1283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 4;
1284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1285e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        if (type == long.class || type == double.class) {
1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 8;
1287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1288e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        throw new AssertionError();
1289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a string containing a concise, human-readable description of this
1293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * descriptor.
1294f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a printable representation of this descriptor.
1296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
129956e742806ebb265e77de750cdb4575cff781fdf8Elliott Hughes        return getName() + ": static final long serialVersionUID =" + getSerialVersionUID() + "L;";
1300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1302