summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/io/ObjectStreamField.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/io/ObjectStreamField.java')
-rw-r--r--luni/src/main/java/java/io/ObjectStreamField.java410
1 files changed, 410 insertions, 0 deletions
diff --git a/luni/src/main/java/java/io/ObjectStreamField.java b/luni/src/main/java/java/io/ObjectStreamField.java
new file mode 100644
index 0000000..95deb7b
--- /dev/null
+++ b/luni/src/main/java/java/io/ObjectStreamField.java
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Describes a field for the purpose of serialization. Classes can define the
+ * collection of fields that are serialized, which may be different from the set
+ * of all declared fields.
+ *
+ * @see ObjectOutputStream#writeFields()
+ * @see ObjectInputStream#readFields()
+ *
+ * @since Android 1.0
+ */
+public class ObjectStreamField implements Comparable<Object> {
+
+ // Declared name of the field
+ private String name;
+
+ // Declared type of the field
+ private Object type;
+
+ // offset of this field in the object
+ int offset;
+
+ // Cached version of intern'ed type String
+ private String typeString;
+
+ private boolean unshared;
+
+ private boolean isDeserialized;
+
+ /**
+ * Constructs an ObjectStreamField with the specified name and type.
+ *
+ * @param name
+ * the name of the field.
+ * @param cl
+ * the type of the field.
+ * @throws NullPointerException
+ * if {@code name} or {@code cl} is {@code null}.
+ * @since Android 1.0
+ */
+ public ObjectStreamField(String name, Class<?> cl) {
+ if (name == null || cl == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ this.type = new WeakReference<Class<?>>(cl);
+ }
+
+ /**
+ * Constructs an ObjectStreamField with the specified name, type and the
+ * indication if it is unshared.
+ *
+ * @param name
+ * the name of the field.
+ * @param cl
+ * the type of the field.
+ * @param unshared
+ * {@code true} if the field is written and read unshared;
+ * {@code false} otherwise.
+ * @throws NullPointerException
+ * if {@code name} or {@code cl} is {@code null}.
+ * @see ObjectOutputStream#writeUnshared(Object)
+ * @since Android 1.0
+ */
+ public ObjectStreamField(String name, Class<?> cl, boolean unshared) {
+ if (name == null || cl == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ this.type = (cl.getClassLoader() == null) ? cl
+ : new WeakReference<Class<?>>(cl);
+ this.unshared = unshared;
+ }
+
+ /**
+ * Constructs an ObjectStreamField with the given name and the given type.
+ * The type may be null.
+ *
+ * @param signature
+ * A String representing the type of the field
+ * @param name
+ * a String, the name of the field, or null
+ */
+ ObjectStreamField(String signature, String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ this.name = name;
+ this.typeString = signature.replace('.', '/').intern();
+ this.isDeserialized = true;
+ }
+
+ /**
+ * Compares this field descriptor to the specified one. Checks first if one
+ * of the compared fields has a primitive type and the other one not. If so,
+ * the field with the primitive type is considered to be "smaller". If both
+ * fields are equal, their names are compared.
+ *
+ * @param o
+ * the object to compare with.
+ * @return -1 if this field is "smaller" than field {@code o}, 0 if both
+ * fields are equal; 1 if this field is "greater" than field {@code
+ * o}.
+ * @since Android 1.0
+ */
+ public int compareTo(Object o) {
+ ObjectStreamField f = (ObjectStreamField) o;
+ boolean thisPrimitive = this.isPrimitive();
+ boolean fPrimitive = f.isPrimitive();
+
+ // If one is primitive and the other isn't, we have enough info to
+ // compare
+ if (thisPrimitive != fPrimitive) {
+ return thisPrimitive ? -1 : 1;
+ }
+
+ // Either both primitives or both not primitives. Compare based on name.
+ return this.getName().compareTo(f.getName());
+ }
+
+ // BEGIN android-removed
+ // There shouldn't be an implementation of these methods.
+ // /**
+ // * Indicates if this field descriptor is equal to {@code arg0}. Field
+ // * descriptors are equal if their name is equal.
+ // *
+ // * @param arg0
+ // * the object to check equality with.
+ // * @return {@code true} if the name of this field descriptor is equal to the
+ // * name of {@code arg0}, {@code false} otherwise.
+ // * @since Android 1.0
+ // */
+ // @Override
+ // public boolean equals(Object arg0) {
+ // // BEGIN android-changed
+ // // copied from newer harmony version
+ // return (arg0 instanceof ObjectStreamField) && compareTo(arg0) == 0;
+ // // END android-changed
+ // }
+ //
+ // /**
+ // * Returns a hash code for this field descriptor. The hash code of this
+ // * field's name is returned.
+ // *
+ // * @return the field's hash code.
+ // * @since Android 1.0
+ // */
+ // @Override
+ // public int hashCode() {
+ // return getName().hashCode();
+ // }
+ // END android-removed
+
+ /**
+ * Gets the name of this field.
+ *
+ * @return the field's name.
+ * @since Android 1.0
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the offset of this field in the object.
+ *
+ * @return this field's offset.
+ * @since Android 1.0
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Return the type of the field the receiver represents, this is an internal
+ * method
+ *
+ * @return A Class object representing the type of the field
+ */
+ // BEGIN android-note
+ // Changed from private to default visibility for usage in ObjectStreamClass
+ // END android-note
+ /* package */ Class<?> getTypeInternal() {
+ if (type instanceof WeakReference) {
+ return (Class<?>) ((WeakReference<?>) type).get();
+ }
+ return (Class<?>) type;
+ }
+
+ /**
+ * Gets the type of this field.
+ *
+ * @return a {@code Class} object representing the type of the field.
+ * @since Android 1.0
+ */
+ public Class<?> getType() {
+ Class<?> cl = getTypeInternal();
+ if (isDeserialized && !cl.isPrimitive()) {
+ return Object.class;
+ }
+ return cl;
+ }
+
+ /**
+ * Gets a character code for the type of this field. The following codes are
+ * used:
+ *
+ * <pre>
+ * B byte
+ * C char
+ * D double
+ * F float
+ * I int
+ * J long
+ * L class or interface
+ * S short
+ * Z boolean
+ * [ array
+ * </pre>
+ *
+ * @return the field's type code.
+ * @since Android 1.0
+ */
+ public char getTypeCode() {
+ Class<?> t = getTypeInternal();
+ if (t == Integer.TYPE) {
+ return 'I';
+ }
+ if (t == Byte.TYPE) {
+ return 'B';
+ }
+ if (t == Character.TYPE) {
+ return 'C';
+ }
+ if (t == Short.TYPE) {
+ return 'S';
+ }
+ if (t == Boolean.TYPE) {
+ return 'Z';
+ }
+ if (t == Long.TYPE) {
+ return 'J';
+ }
+ if (t == Float.TYPE) {
+ return 'F';
+ }
+ if (t == Double.TYPE) {
+ return 'D';
+ }
+ if (t.isArray()) {
+ return '[';
+ }
+ return 'L';
+ }
+
+ /**
+ * Gets the type signature used by the VM to represent the type of this
+ * field.
+ *
+ * @return the signature of this field's class or {@code null} if this
+ * field's type is primitive.
+ * @since Android 1.0
+ */
+ public String getTypeString() {
+ if (isPrimitive()) {
+ return null;
+ }
+ if (typeString == null) {
+ Class<?> t = getTypeInternal();
+ String typeName = t.getName().replace('.', '/');
+ String str = (t.isArray()) ? typeName : ("L" + typeName + ';'); //$NON-NLS-1$
+ typeString = str.intern();
+ }
+ return typeString;
+ }
+
+ /**
+ * Indicates whether this field's type is a primitive type.
+ *
+ * @return {@code true} if this field's type is primitive; {@code false} if
+ * the type of this field is a regular class.
+ * @since Android 1.0
+ */
+ public boolean isPrimitive() {
+ Class<?> t = getTypeInternal();
+ return t != null && t.isPrimitive();
+ }
+
+ /**
+ * Sets this field's offset in the object.
+ *
+ * @param newValue
+ * the field's new offset.
+ * @since Android 1.0
+ */
+ protected void setOffset(int newValue) {
+ this.offset = newValue;
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * field descriptor.
+ *
+ * @return a printable representation of this descriptor.
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getName() + '(' + getName() + ':'
+ + getTypeInternal() + ')';
+ }
+
+ /**
+ * Sorts the fields for dumping. Primitive types come first, then regular
+ * types.
+ *
+ * @param fields
+ * ObjectStreamField[] fields to be sorted
+ */
+ static void sortFields(ObjectStreamField[] fields) {
+ // Sort if necessary
+ if (fields.length > 1) {
+ Comparator<ObjectStreamField> fieldDescComparator = new Comparator<ObjectStreamField>() {
+ public int compare(ObjectStreamField f1, ObjectStreamField f2) {
+ return f1.compareTo(f2);
+ }
+ };
+ Arrays.sort(fields, fieldDescComparator);
+ }
+ }
+
+ void resolve(ClassLoader loader) {
+ if (typeString.length() == 1) {
+ switch (typeString.charAt(0)) {
+ case 'I':
+ type = Integer.TYPE;
+ return;
+ case 'B':
+ type = Byte.TYPE;
+ return;
+ case 'C':
+ type = Character.TYPE;
+ return;
+ case 'S':
+ type = Short.TYPE;
+ return;
+ case 'Z':
+ type = Boolean.TYPE;
+ return;
+ case 'J':
+ type = Long.TYPE;
+ return;
+ case 'F':
+ type = Float.TYPE;
+ return;
+ case 'D':
+ type = Double.TYPE;
+ return;
+ }
+ }
+ String className = typeString.replace('/', '.');
+ if (className.charAt(0) == 'L') {
+ // remove L and ;
+ className = className.substring(1, className.length() - 1);
+ }
+ try {
+ Class<?> cl = Class.forName(className, false, loader);
+ type = (cl.getClassLoader() == null) ? cl
+ : new WeakReference<Class<?>>(cl);
+ } catch (ClassNotFoundException e) {
+ // Ignored
+ }
+ }
+
+ /**
+ * Indicats whether this field is unshared.
+ *
+ * @return {@code true} if this field is unshared, {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean isUnshared() {
+ return unshared;
+ }
+
+ void setUnshared(boolean unshared) {
+ this.unshared = unshared;
+ }
+}