rt/emul/compact/src/main/java/java/io/ObjectStreamField.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 17 Jan 2017 07:04:06 +0100
changeset 1985 cd1cc103a03c
parent 601 5198affdb915
permissions -rw-r--r--
Implementation of ClassValue for bck2brwsr
     1 /*
     2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.io;
    27 
    28 import java.lang.reflect.Field;
    29 
    30 /**
    31  * A description of a Serializable field from a Serializable class.  An array
    32  * of ObjectStreamFields is used to declare the Serializable fields of a class.
    33  *
    34  * @author      Mike Warres
    35  * @author      Roger Riggs
    36  * @see ObjectStreamClass
    37  * @since 1.2
    38  */
    39 public class ObjectStreamField
    40     implements Comparable<Object>
    41 {
    42 
    43     /** field name */
    44     private final String name;
    45     /** canonical JVM signature of field type */
    46     private final String signature;
    47     /** field type (Object.class if unknown non-primitive type) */
    48     private final Class<?> type;
    49     /** whether or not to (de)serialize field values as unshared */
    50     private final boolean unshared;
    51     /** corresponding reflective field object, if any */
    52     private final Field field;
    53     /** offset of field value in enclosing field group */
    54     private int offset = 0;
    55 
    56     /**
    57      * Create a Serializable field with the specified type.  This field should
    58      * be documented with a <code>serialField</code> tag.
    59      *
    60      * @param   name the name of the serializable field
    61      * @param   type the <code>Class</code> object of the serializable field
    62      */
    63     public ObjectStreamField(String name, Class<?> type) {
    64         this(name, type, false);
    65     }
    66 
    67     /**
    68      * Creates an ObjectStreamField representing a serializable field with the
    69      * given name and type.  If unshared is false, values of the represented
    70      * field are serialized and deserialized in the default manner--if the
    71      * field is non-primitive, object values are serialized and deserialized as
    72      * if they had been written and read by calls to writeObject and
    73      * readObject.  If unshared is true, values of the represented field are
    74      * serialized and deserialized as if they had been written and read by
    75      * calls to writeUnshared and readUnshared.
    76      *
    77      * @param   name field name
    78      * @param   type field type
    79      * @param   unshared if false, write/read field values in the same manner
    80      *          as writeObject/readObject; if true, write/read in the same
    81      *          manner as writeUnshared/readUnshared
    82      * @since   1.4
    83      */
    84     public ObjectStreamField(String name, Class<?> type, boolean unshared) {
    85         if (name == null) {
    86             throw new NullPointerException();
    87         }
    88         this.name = name;
    89         this.type = type;
    90         this.unshared = unshared;
    91         signature = getClassSignature(type).intern();
    92         field = null;
    93     }
    94 
    95     /**
    96      * Creates an ObjectStreamField representing a field with the given name,
    97      * signature and unshared setting.
    98      */
    99     ObjectStreamField(String name, String signature, boolean unshared) {
   100         if (name == null) {
   101             throw new NullPointerException();
   102         }
   103         this.name = name;
   104         this.signature = signature.intern();
   105         this.unshared = unshared;
   106         field = null;
   107 
   108         switch (signature.charAt(0)) {
   109             case 'Z': type = Boolean.TYPE; break;
   110             case 'B': type = Byte.TYPE; break;
   111             case 'C': type = Character.TYPE; break;
   112             case 'S': type = Short.TYPE; break;
   113             case 'I': type = Integer.TYPE; break;
   114             case 'J': type = Long.TYPE; break;
   115             case 'F': type = Float.TYPE; break;
   116             case 'D': type = Double.TYPE; break;
   117             case 'L':
   118             case '[': type = Object.class; break;
   119             default: throw new IllegalArgumentException("illegal signature");
   120         }
   121     }
   122 
   123     /**
   124      * Creates an ObjectStreamField representing the given field with the
   125      * specified unshared setting.  For compatibility with the behavior of
   126      * earlier serialization implementations, a "showType" parameter is
   127      * necessary to govern whether or not a getType() call on this
   128      * ObjectStreamField (if non-primitive) will return Object.class (as
   129      * opposed to a more specific reference type).
   130      */
   131     ObjectStreamField(Field field, boolean unshared, boolean showType) {
   132         this.field = field;
   133         this.unshared = unshared;
   134         name = field.getName();
   135         Class<?> ftype = field.getType();
   136         type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
   137         signature = getClassSignature(ftype).intern();
   138     }
   139 
   140     /**
   141      * Get the name of this field.
   142      *
   143      * @return  a <code>String</code> representing the name of the serializable
   144      *          field
   145      */
   146     public String getName() {
   147         return name;
   148     }
   149 
   150     /**
   151      * Get the type of the field.  If the type is non-primitive and this
   152      * <code>ObjectStreamField</code> was obtained from a deserialized {@link
   153      * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
   154      * Otherwise, the <code>Class</code> object for the type of the field is
   155      * returned.
   156      *
   157      * @return  a <code>Class</code> object representing the type of the
   158      *          serializable field
   159      */
   160     public Class<?> getType() {
   161         return type;
   162     }
   163 
   164     /**
   165      * Returns character encoding of field type.  The encoding is as follows:
   166      * <blockquote><pre>
   167      * B            byte
   168      * C            char
   169      * D            double
   170      * F            float
   171      * I            int
   172      * J            long
   173      * L            class or interface
   174      * S            short
   175      * Z            boolean
   176      * [            array
   177      * </pre></blockquote>
   178      *
   179      * @return  the typecode of the serializable field
   180      */
   181     // REMIND: deprecate?
   182     public char getTypeCode() {
   183         return signature.charAt(0);
   184     }
   185 
   186     /**
   187      * Return the JVM type signature.
   188      *
   189      * @return  null if this field has a primitive type.
   190      */
   191     // REMIND: deprecate?
   192     public String getTypeString() {
   193         return isPrimitive() ? null : signature;
   194     }
   195 
   196     /**
   197      * Offset of field within instance data.
   198      *
   199      * @return  the offset of this field
   200      * @see #setOffset
   201      */
   202     // REMIND: deprecate?
   203     public int getOffset() {
   204         return offset;
   205     }
   206 
   207     /**
   208      * Offset within instance data.
   209      *
   210      * @param   offset the offset of the field
   211      * @see #getOffset
   212      */
   213     // REMIND: deprecate?
   214     protected void setOffset(int offset) {
   215         this.offset = offset;
   216     }
   217 
   218     /**
   219      * Return true if this field has a primitive type.
   220      *
   221      * @return  true if and only if this field corresponds to a primitive type
   222      */
   223     // REMIND: deprecate?
   224     public boolean isPrimitive() {
   225         char tcode = signature.charAt(0);
   226         return ((tcode != 'L') && (tcode != '['));
   227     }
   228 
   229     /**
   230      * Returns boolean value indicating whether or not the serializable field
   231      * represented by this ObjectStreamField instance is unshared.
   232      *
   233      * @since 1.4
   234      */
   235     public boolean isUnshared() {
   236         return unshared;
   237     }
   238 
   239     /**
   240      * Compare this field with another <code>ObjectStreamField</code>.  Return
   241      * -1 if this is smaller, 0 if equal, 1 if greater.  Types that are
   242      * primitives are "smaller" than object types.  If equal, the field names
   243      * are compared.
   244      */
   245     // REMIND: deprecate?
   246     public int compareTo(Object obj) {
   247         ObjectStreamField other = (ObjectStreamField) obj;
   248         boolean isPrim = isPrimitive();
   249         if (isPrim != other.isPrimitive()) {
   250             return isPrim ? -1 : 1;
   251         }
   252         return name.compareTo(other.name);
   253     }
   254 
   255     /**
   256      * Return a string that describes this field.
   257      */
   258     public String toString() {
   259         return signature + ' ' + name;
   260     }
   261 
   262     /**
   263      * Returns field represented by this ObjectStreamField, or null if
   264      * ObjectStreamField is not associated with an actual field.
   265      */
   266     Field getField() {
   267         return field;
   268     }
   269 
   270     /**
   271      * Returns JVM type signature of field (similar to getTypeString, except
   272      * that signature strings are returned for primitive fields as well).
   273      */
   274     String getSignature() {
   275         return signature;
   276     }
   277 
   278     /**
   279      * Returns JVM type signature for given class.
   280      */
   281     private static String getClassSignature(Class<?> cl) {
   282         StringBuilder sbuf = new StringBuilder();
   283         while (cl.isArray()) {
   284             sbuf.append('[');
   285             cl = cl.getComponentType();
   286         }
   287         if (cl.isPrimitive()) {
   288             if (cl == Integer.TYPE) {
   289                 sbuf.append('I');
   290             } else if (cl == Byte.TYPE) {
   291                 sbuf.append('B');
   292             } else if (cl == Long.TYPE) {
   293                 sbuf.append('J');
   294             } else if (cl == Float.TYPE) {
   295                 sbuf.append('F');
   296             } else if (cl == Double.TYPE) {
   297                 sbuf.append('D');
   298             } else if (cl == Short.TYPE) {
   299                 sbuf.append('S');
   300             } else if (cl == Character.TYPE) {
   301                 sbuf.append('C');
   302             } else if (cl == Boolean.TYPE) {
   303                 sbuf.append('Z');
   304             } else if (cl == Void.TYPE) {
   305                 sbuf.append('V');
   306             } else {
   307                 throw new InternalError();
   308             }
   309         } else {
   310             sbuf.append('L' + cl.getName().replace('.', '/') + ';');
   311         }
   312         return sbuf.toString();
   313     }
   314 }