Skip to content

Commit 41a4321

Browse files
author
zhourenjian
committed
Add ObjectStreamField class
1 parent a02d8e3 commit 41a4321

File tree

1 file changed

+347
-0
lines changed

1 file changed

+347
-0
lines changed
Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package java.io;
19+
20+
//import java.lang.ref.WeakReference;
21+
import java.util.Arrays;
22+
import java.util.Comparator;
23+
24+
/**
25+
* This class represents object fields that are saved to the stream, by
26+
* serialization. Classes can define the collection of fields to be dumped,
27+
* which can differ from the actual object's declared fields.
28+
*
29+
* @see ObjectOutputStream#writeFields()
30+
* @see ObjectInputStream#readFields()
31+
*
32+
*/
33+
public class ObjectStreamField implements Comparable<Object> {
34+
35+
// Declared name of the field
36+
private String name;
37+
38+
// Declared type of the field
39+
private Object type;
40+
41+
// offset of this field in the object
42+
int offset;
43+
44+
// Cached version of intern'ed type String
45+
private String typeString;
46+
47+
private boolean unshared;
48+
49+
private boolean isDeserialized;
50+
51+
/**
52+
* Constructs an ObjectStreamField with the given name and the given type
53+
*
54+
* @param name
55+
* a String, the name of the field
56+
* @param cl
57+
* A Class object representing the type of the field
58+
*/
59+
public ObjectStreamField(String name, Class<?> cl) {
60+
if (name == null || cl == null) {
61+
throw new NullPointerException();
62+
}
63+
this.name = name;
64+
// this.type = new WeakReference<Class<?>>(cl);
65+
this.type = cl;
66+
}
67+
68+
/**
69+
* Constructs an ObjectStreamField with the given name and the given type
70+
*
71+
* @param name
72+
* a String, the name of the field
73+
* @param cl
74+
* A Class object representing the type of the field
75+
* @param unshared
76+
* write and read the field unshared
77+
*/
78+
public ObjectStreamField(String name, Class<?> cl, boolean unshared) {
79+
if (name == null || cl == null) {
80+
throw new NullPointerException();
81+
}
82+
this.name = name;
83+
// this.type = (cl.getClassLoader() == null) ? cl
84+
// : new WeakReference<Class<?>>(cl);
85+
this.type = cl;
86+
this.unshared = unshared;
87+
}
88+
89+
/**
90+
* Constructs an ObjectStreamField with the given name and the given type.
91+
* The type may be null.
92+
*
93+
* @param signature
94+
* A String representing the type of the field
95+
* @param name
96+
* a String, the name of the field, or null
97+
*/
98+
ObjectStreamField(String signature, String name) {
99+
if (name == null) {
100+
throw new NullPointerException();
101+
}
102+
this.name = name;
103+
this.typeString = signature.replace('.', '/');
104+
this.isDeserialized = true;
105+
}
106+
107+
/**
108+
* Comparing the receiver to the parameter, according to the Comparable
109+
* interface.
110+
*
111+
* @param o
112+
* The object to compare against
113+
*
114+
* @return -1 if the receiver is "smaller" than the parameter. 0 if the
115+
* receiver is "equal" to the parameter. 1 if the receiver is
116+
* "greater" than the parameter.
117+
*/
118+
public int compareTo(Object o) {
119+
ObjectStreamField f = (ObjectStreamField) o;
120+
boolean thisPrimitive = this.isPrimitive();
121+
boolean fPrimitive = f.isPrimitive();
122+
123+
// If one is primitive and the other isn't, we have enough info to
124+
// compare
125+
if (thisPrimitive != fPrimitive) {
126+
return thisPrimitive ? -1 : 1;
127+
}
128+
129+
// Either both primitives or both not primitives. Compare based on name.
130+
return this.getName().compareTo(f.getName());
131+
}
132+
133+
134+
public boolean equals(Object arg0) {
135+
return compareTo(arg0) == 0;
136+
}
137+
138+
public int hashCode() {
139+
return getName().hashCode();
140+
}
141+
142+
/**
143+
* Return the name of the field the receiver represents
144+
*
145+
* @return a String, the name of the field
146+
*/
147+
public String getName() {
148+
return name;
149+
}
150+
151+
/**
152+
* Return the offset of this field in the object
153+
*
154+
* @return an int, the offset
155+
*/
156+
public int getOffset() {
157+
return offset;
158+
}
159+
160+
/**
161+
* Return the type of the field the receiver represents,
162+
* this is an internal method
163+
*
164+
* @return A Class object representing the type of the field
165+
*/
166+
private Class<?> getTypeInternal() {
167+
// if (type instanceof WeakReference) {
168+
// return (Class<?>)((WeakReference) type).get();
169+
// }
170+
return (Class<?>) type;
171+
}
172+
173+
/**
174+
* Return the type of the field the receiver represents
175+
*
176+
* @return A Class object representing the type of the field
177+
*/
178+
public Class<?> getType() {
179+
Class<?> cl = getTypeInternal();
180+
if (isDeserialized && !cl.isPrimitive()) {
181+
return Object.class;
182+
}
183+
return cl;
184+
}
185+
186+
/**
187+
* Return the type code that corresponds to the class the receiver
188+
* represents
189+
*
190+
* @return A char, the typecode of the class
191+
*/
192+
public char getTypeCode() {
193+
Class<?> t = getTypeInternal();
194+
if (t == Integer.TYPE) {
195+
return 'I';
196+
}
197+
if (t == Byte.TYPE) {
198+
return 'B';
199+
}
200+
if (t == Character.TYPE) {
201+
return 'C';
202+
}
203+
if (t == Short.TYPE) {
204+
return 'S';
205+
}
206+
if (t == Boolean.TYPE) {
207+
return 'Z';
208+
}
209+
if (t == Long.TYPE) {
210+
return 'J';
211+
}
212+
if (t == Float.TYPE) {
213+
return 'F';
214+
}
215+
if (t == Double.TYPE) {
216+
return 'D';
217+
}
218+
if (t.isArray()) {
219+
return '[';
220+
}
221+
return 'L';
222+
}
223+
224+
/**
225+
* Return the type signature used by the VM to represent the type for this
226+
* field.
227+
*
228+
* @return A String, the signature for the class of this field.
229+
*/
230+
public String getTypeString() {
231+
if (isPrimitive()) {
232+
return null;
233+
}
234+
if (typeString == null) {
235+
Class<?> t = getTypeInternal();
236+
String typeName = t.getName().replace('.', '/');
237+
String str = (t.isArray()) ? typeName : ("L" + typeName + ';'); //$NON-NLS-1$
238+
typeString = str.intern();
239+
}
240+
return typeString;
241+
}
242+
243+
/**
244+
* Return a boolean indicating whether the class of this field is a
245+
* primitive type or not
246+
*
247+
* @return true if the type of this field is a primitive type false if the
248+
* type of this field is a regular class.
249+
*/
250+
public boolean isPrimitive() {
251+
Class<?> t = getTypeInternal();
252+
return t != null && t.isPrimitive();
253+
}
254+
255+
/**
256+
* Set the offset this field represents in the object
257+
*
258+
* @param newValue
259+
* an int, the offset
260+
*/
261+
protected void setOffset(int newValue) {
262+
this.offset = newValue;
263+
}
264+
265+
/**
266+
* Answers a string containing a concise, human-readable description of the
267+
* receiver.
268+
*
269+
* @return a printable representation for the receiver.
270+
*/
271+
@Override
272+
public String toString() {
273+
return this.getClass().getName() + '(' + getName() + ':' + getTypeInternal()
274+
+ ')';
275+
}
276+
277+
/**
278+
* Sorts the fields for dumping. Primitive types come first, then regular
279+
* types.
280+
*
281+
* @param fields
282+
* ObjectStreamField[] fields to be sorted
283+
*/
284+
static void sortFields(ObjectStreamField[] fields) {
285+
// Sort if necessary
286+
if (fields.length > 1) {
287+
Comparator<ObjectStreamField> fieldDescComparator = new Comparator<ObjectStreamField>() {
288+
public int compare(ObjectStreamField f1, ObjectStreamField f2) {
289+
return f1.compareTo(f2);
290+
}
291+
};
292+
Arrays.sort(fields, fieldDescComparator);
293+
}
294+
}
295+
296+
void resolve(ClassLoader loader) {
297+
if (typeString.length() == 1) {
298+
switch (typeString.charAt(0)) {
299+
case 'I':
300+
type = Integer.TYPE;
301+
return;
302+
case 'B':
303+
type = Byte.TYPE;
304+
return;
305+
case 'C':
306+
type = Character.TYPE;
307+
return;
308+
case 'S':
309+
type = Short.TYPE;
310+
return;
311+
case 'Z':
312+
type = Boolean.TYPE;
313+
return;
314+
case 'J':
315+
type = Long.TYPE;
316+
return;
317+
case 'F':
318+
type = Float.TYPE;
319+
return;
320+
case 'D':
321+
type = Double.TYPE;
322+
return;
323+
}
324+
}
325+
String className = typeString.replace('/', '.');
326+
if (className.charAt(0) == 'L') {
327+
// remove L and ;
328+
className = className.substring(1, className.length() - 1);
329+
}
330+
try {
331+
Class<?> cl = Class.forName(className, false, loader);
332+
// type = (cl.getClassLoader() == null) ? cl : new WeakReference<Class<?>>(cl);
333+
type = cl;
334+
} catch (ClassNotFoundException e) {
335+
// Ignored
336+
}
337+
}
338+
339+
/**
340+
* Answers whether this serialized field is unshared.
341+
*
342+
* @return true if the field is unshared, false otherwise.
343+
*/
344+
public boolean isUnshared() {
345+
return unshared;
346+
}
347+
}

0 commit comments

Comments
 (0)