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
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.ref.WeakReference;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Comparator;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Describes a field for the purpose of serialization. Classes can define the
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * collection of fields that are serialized, which may be different from the set
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of all declared fields.
28f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see ObjectOutputStream#writeFields()
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see ObjectInputStream#readFields()
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ObjectStreamField implements Comparable<Object> {
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Declared name of the field
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String name;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Declared type of the field
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Object type;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // offset of this field in the object
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int offset;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Cached version of intern'ed type String
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String typeString;
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean unshared;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isDeserialized;
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an ObjectStreamField with the specified name and type.
52f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the field.
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the type of the field.
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code name} or {@code cl} is {@code null}.
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ObjectStreamField(String name, Class<?> cl) {
6186acc043d3334651ee26c65467d78d6cefedd397Kenny Root        if (name == null) {
6286acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("name == null");
6386acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (cl == null) {
6486acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("cl == null");
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.type = new WeakReference<Class<?>>(cl);
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an ObjectStreamField with the specified name, type and the
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * indication if it is unshared.
73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the field.
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the type of the field.
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param unshared
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} if the field is written and read unshared;
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code false} otherwise.
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code name} or {@code cl} is {@code null}.
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see ObjectOutputStream#writeUnshared(Object)
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ObjectStreamField(String name, Class<?> cl, boolean unshared) {
8686acc043d3334651ee26c65467d78d6cefedd397Kenny Root        if (name == null) {
8786acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("name == null");
8886acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (cl == null) {
8986acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("cl == null");
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
927d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        this.type = (cl.getClassLoader() == null) ? cl : new WeakReference<Class<?>>(cl);
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.unshared = unshared;
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an ObjectStreamField with the given name and the given type.
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The type may be null.
99f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param signature
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            A String representing the type of the field
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a String, the name of the field, or null
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ObjectStreamField(String signature, String name) {
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
10786acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("name == null");
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.typeString = signature.replace('.', '/').intern();
111b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        defaultResolve();
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.isDeserialized = true;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares this field descriptor to the specified one. Checks first if one
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the compared fields has a primitive type and the other one not. If so,
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the field with the primitive type is considered to be "smaller". If both
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * fields are equal, their names are compared.
120f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param o
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the object to compare with.
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return -1 if this field is "smaller" than field {@code o}, 0 if both
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         fields are equal; 1 if this field is "greater" than field {@code
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         o}.
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int compareTo(Object o) {
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectStreamField f = (ObjectStreamField) o;
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean thisPrimitive = this.isPrimitive();
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean fPrimitive = f.isPrimitive();
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If one is primitive and the other isn't, we have enough info to
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // compare
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (thisPrimitive != fPrimitive) {
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return thisPrimitive ? -1 : 1;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Either both primitives or both not primitives. Compare based on name.
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this.getName().compareTo(f.getName());
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
141f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the name of this field.
144f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the field's name.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the offset of this field in the object.
153f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this field's offset.
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getOffset() {
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return offset;
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Return the type of the field the receiver represents, this is an internal
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method
163f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return A Class object representing the type of the field
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Changed from private to default visibility for usage in ObjectStreamClass
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /* package */ Class<?> getTypeInternal() {
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (type instanceof WeakReference) {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (Class<?>) ((WeakReference<?>) type).get();
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (Class<?>) type;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the type of this field.
176f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a {@code Class} object representing the type of the field.
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Class<?> getType() {
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Class<?> cl = getTypeInternal();
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isDeserialized && !cl.isPrimitive()) {
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return Object.class;
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return cl;
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a character code for the type of this field. The following codes are
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * used:
190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <pre>
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * B     byte
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * C     char
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * D     double
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * F     float
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * I     int
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * J     long
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * L     class or interface
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * S     short
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Z     boolean
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [     array
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * </pre>
203f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the field's type code.
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public char getTypeCode() {
207af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        return typeCodeOf(getTypeInternal());
208af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes    }
209af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes
210af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes    private char typeCodeOf(Class<?> type) {
211e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        if (type == int.class) {
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'I';
213e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == byte.class) {
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'B';
215e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == char.class) {
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'C';
217e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == short.class) {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'S';
219e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == boolean.class) {
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'Z';
221e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == long.class) {
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'J';
223e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == float.class) {
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'F';
225e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        } else if (type == double.class) {
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 'D';
227af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        } else if (type.isArray()) {
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return '[';
229af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        } else {
230af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes            return 'L';
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the type signature used by the VM to represent the type of this
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field.
237f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the signature of this field's class or {@code null} if this
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         field's type is primitive.
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getTypeString() {
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isPrimitive()) {
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (typeString == null) {
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?> t = getTypeInternal();
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String typeName = t.getName().replace('.', '/');
248f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            String str = (t.isArray()) ? typeName : ("L" + typeName + ';');
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            typeString = str.intern();
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return typeString;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this field's type is a primitive type.
256f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this field's type is primitive; {@code false} if
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         the type of this field is a regular class.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isPrimitive() {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Class<?> t = getTypeInternal();
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return t != null && t.isPrimitive();
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
265af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes    boolean writeField(DataOutputStream out) throws IOException {
266af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        Class<?> t = getTypeInternal();
267af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        out.writeByte(typeCodeOf(t));
268af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        out.writeUTF(name);
269af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        return (t != null && t.isPrimitive());
270af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes    }
271af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets this field's offset in the object.
274f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newValue
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field's new offset.
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void setOffset(int newValue) {
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.offset = newValue;
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a string containing a concise, human-readable description of this
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field descriptor.
285f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a printable representation of this descriptor.
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
2907d0d108593ac30e19b8f2a5a157f697f3f46c041Elliott Hughes        return this.getClass().getName() + '(' + getName() + ':' + getTypeInternal() + ')';
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void resolve(ClassLoader loader) {
294af338385e1cfb40a856bf11d8ddd682ea7602164Elliott Hughes        if (typeString == null && isPrimitive()) {
295b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            // primitive type declared in a serializable class
296b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            typeString = String.valueOf(getTypeCode());
297b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        }
298b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (typeString.length() == 1) {
300b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            if (defaultResolve()) {
301b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes                return;
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
304b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String className = typeString.replace('/', '.');
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (className.charAt(0) == 'L') {
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // remove L and ;
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            className = className.substring(1, className.length() - 1);
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?> cl = Class.forName(className, false, loader);
312b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            type = (cl.getClassLoader() == null) ? cl : new WeakReference<Class<?>>(cl);
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (ClassNotFoundException e) {
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Ignored
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
319b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes     * Indicates whether this field is unshared.
320f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this field is unshared, {@code false} otherwise.
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isUnshared() {
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return unshared;
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
326f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void setUnshared(boolean unshared) {
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.unshared = unshared;
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
330b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes
331b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes    /**
332b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes     * Resolves typeString into type. Returns true if the type is primitive
333b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes     * and false otherwise.
334b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes     */
335b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes    private boolean defaultResolve() {
336b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        switch (typeString.charAt(0)) {
337b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'I':
338e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = int.class;
339b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
340b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'B':
341e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = byte.class;
342b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
343b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'C':
344e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = char.class;
345b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
346b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'S':
347e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = short.class;
348b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
349b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'Z':
350e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = boolean.class;
351b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
352b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'J':
353e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = long.class;
354b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
355b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'F':
356e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = float.class;
357b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
358b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        case 'D':
359e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes            type = double.class;
360b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return true;
361b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        default:
362b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            type = Object.class;
363b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes            return false;
364b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes        }
365b57e439ac3f5401e39dbe4d9097e476fe20b889eElliott Hughes    }
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
367