src/share/classes/com/sun/tools/javadoc/SerializedForm.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 1372
78962d89f283
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

     1 /*
     2  * Copyright (c) 1998, 2012, 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  */
    26 package com.sun.tools.javadoc;
    28 import com.sun.javadoc.*;
    29 import com.sun.tools.javac.code.Flags;
    30 import com.sun.tools.javac.code.Kinds;
    31 import com.sun.tools.javac.code.Scope;
    32 import com.sun.tools.javac.code.Symbol.ClassSymbol;
    33 import com.sun.tools.javac.code.Symbol.MethodSymbol;
    34 import com.sun.tools.javac.code.Symbol.VarSymbol;
    35 import com.sun.tools.javac.util.ListBuffer;
    36 import com.sun.tools.javac.util.Name;
    37 import com.sun.tools.javac.util.Names;
    39 /**
    40  * The serialized form is the specification of a class' serialization
    41  * state. <p>
    42  *
    43  * It consists of the following information:<p>
    44  *
    45  * <pre>
    46  * 1. Whether class is Serializable or Externalizable.
    47  * 2. Javadoc for serialization methods.
    48  *    a. For Serializable, the optional readObject, writeObject,
    49  *       readResolve and writeReplace.
    50  *       serialData tag describes, in prose, the sequence and type
    51  *       of optional data written by writeObject.
    52  *    b. For Externalizable, writeExternal and readExternal.
    53  *       serialData tag describes, in prose, the sequence and type
    54  *       of optional data written by writeExternal.
    55  * 3. Javadoc for serialization data layout.
    56  *    a. For Serializable, the name,type and description
    57  *       of each Serializable fields.
    58  *    b. For Externalizable, data layout is described by 2(b).
    59  * </pre>
    60  *
    61  *  <p><b>This is NOT part of any supported API.
    62  *  If you write code that depends on this, you do so at your own risk.
    63  *  This code and its internal interfaces are subject to change or
    64  *  deletion without notice.</b>
    65  *
    66  * @since 1.2
    67  * @author Joe Fialli
    68  * @author Neal Gafter (rewrite but not too proud)
    69  */
    70 class SerializedForm {
    71     ListBuffer<MethodDoc> methods = new ListBuffer<MethodDoc>();
    73     /* List of FieldDocImpl - Serializable fields.
    74      * Singleton list if class defines Serializable fields explicitly.
    75      * Otherwise, list of default serializable fields.
    76      * 0 length list for Externalizable.
    77      */
    78     private final ListBuffer<FieldDocImpl> fields = new ListBuffer<FieldDocImpl>();
    80     /* True if class specifies serializable fields explicitly.
    81      * using special static member, serialPersistentFields.
    82      */
    83     private boolean definesSerializableFields = false;
    85     // Specially treated field/method names defined by Serialization.
    86     private static final String SERIALIZABLE_FIELDS = "serialPersistentFields";
    87     private static final String READOBJECT  = "readObject";
    88     private static final String WRITEOBJECT = "writeObject";
    89     private static final String READRESOLVE  = "readResolve";
    90     private static final String WRITEREPLACE = "writeReplace";
    91     private static final String READOBJECTNODATA = "readObjectNoData";
    93     /**
    94      * Constructor.
    95      *
    96      * Catalog Serializable fields for Serializable class.
    97      * Catalog serialization methods for Serializable and
    98      * Externalizable classes.
    99      */
   100     SerializedForm(DocEnv env, ClassSymbol def, ClassDocImpl cd) {
   101         if (cd.isExternalizable()) {
   102             /* look up required public accessible methods,
   103              *   writeExternal and readExternal.
   104              */
   105             String[] readExternalParamArr = { "java.io.ObjectInput" };
   106             String[] writeExternalParamArr = { "java.io.ObjectOutput" };
   107             MethodDoc md = cd.findMethod("readExternal", readExternalParamArr);
   108             if (md != null) {
   109                 methods.append(md);
   110             }
   111             md = cd.findMethod("writeExternal", writeExternalParamArr);
   112             if (md != null) {
   113                 methods.append(md);
   114                 Tag tag[] = md.tags("serialData");
   115             }
   116         // } else { // isSerializable() //### ???
   117         } else if (cd.isSerializable()) {
   119             VarSymbol dsf = getDefinedSerializableFields(def);
   120             if (dsf != null) {
   122                 /* Define serializable fields with array of ObjectStreamField.
   123                  * Each ObjectStreamField should be documented by a
   124                  * serialField tag.
   125                  */
   126                 definesSerializableFields = true;
   127                 //### No modifier filtering applied here.
   128                 FieldDocImpl dsfDoc = env.getFieldDoc(dsf);
   129                 fields.append(dsfDoc);
   130                 mapSerialFieldTagImplsToFieldDocImpls(dsfDoc, env, def);
   131             } else {
   133                 /* Calculate default Serializable fields as all
   134                  * non-transient, non-static fields.
   135                  * Fields should be documented by serial tag.
   136                  */
   137                 computeDefaultSerializableFields(env, def, cd);
   138             }
   140            /* Check for optional customized readObject, writeObject,
   141             * readResolve and writeReplace, which can all contain
   142             * the serialData tag.        */
   143             addMethodIfExist(env, def, READOBJECT);
   144             addMethodIfExist(env, def, WRITEOBJECT);
   145             addMethodIfExist(env, def, READRESOLVE);
   146             addMethodIfExist(env, def, WRITEREPLACE);
   147             addMethodIfExist(env, def, READOBJECTNODATA);
   148         }
   149     }
   151     /*
   152      * Check for explicit Serializable fields.
   153      * Check for a private static array of ObjectStreamField with
   154      * name SERIALIZABLE_FIELDS.
   155      */
   156     private VarSymbol getDefinedSerializableFields(ClassSymbol def) {
   157         Names names = def.name.table.names;
   159         /* SERIALIZABLE_FIELDS can be private,
   160          * so must lookup by ClassSymbol, not by ClassDocImpl.
   161          */
   162         for (Scope.Entry e = def.members().lookup(names.fromString(SERIALIZABLE_FIELDS)); e.scope != null; e = e.next()) {
   163             if (e.sym.kind == Kinds.VAR) {
   164                 VarSymbol f = (VarSymbol)e.sym;
   165                 if ((f.flags() & Flags.STATIC) != 0 &&
   166                     (f.flags() & Flags.PRIVATE) != 0) {
   167                     return f;
   168                 }
   169             }
   170         }
   171         return null;
   172     }
   174     /*
   175      * Compute default Serializable fields from all members of ClassSymbol.
   176      *
   177      * Since the fields of ClassDocImpl might not contain private or
   178      * package accessible fields, must walk over all members of ClassSymbol.
   179      */
   180     private void computeDefaultSerializableFields(DocEnv env,
   181                                                   ClassSymbol def,
   182                                                   ClassDocImpl cd) {
   183         for (Scope.Entry e = def.members().elems; e != null; e = e.sibling) {
   184             if (e.sym != null && e.sym.kind == Kinds.VAR) {
   185                 VarSymbol f = (VarSymbol)e.sym;
   186                 if ((f.flags() & Flags.STATIC) == 0 &&
   187                     (f.flags() & Flags.TRANSIENT) == 0) {
   188                     //### No modifier filtering applied here.
   189                     FieldDocImpl fd = env.getFieldDoc(f);
   190                     //### Add to beginning.
   191                     //### Preserve order used by old 'javadoc'.
   192                     fields.prepend(fd);
   193                 }
   194             }
   195         }
   196     }
   198     /*
   199      * Catalog Serializable method if it exists in current ClassSymbol.
   200      * Do not look for method in superclasses.
   201      *
   202      * Serialization requires these methods to be non-static.
   203      *
   204      * @param method should be an unqualified Serializable method
   205      *               name either READOBJECT, WRITEOBJECT, READRESOLVE
   206      *               or WRITEREPLACE.
   207      * @param visibility the visibility flag for the given method.
   208      */
   209     private void addMethodIfExist(DocEnv env, ClassSymbol def, String methodName) {
   210         Names names = def.name.table.names;
   212         for (Scope.Entry e = def.members().lookup(names.fromString(methodName)); e.scope != null; e = e.next()) {
   213             if (e.sym.kind == Kinds.MTH) {
   214                 MethodSymbol md = (MethodSymbol)e.sym;
   215                 if ((md.flags() & Flags.STATIC) == 0) {
   216                     /*
   217                      * WARNING: not robust if unqualifiedMethodName is overloaded
   218                      *          method. Signature checking could make more robust.
   219                      * READOBJECT takes a single parameter, java.io.ObjectInputStream.
   220                      * WRITEOBJECT takes a single parameter, java.io.ObjectOutputStream.
   221                      */
   222                     methods.append(env.getMethodDoc(md));
   223                 }
   224             }
   225         }
   226     }
   228     /*
   229      * Associate serialField tag fieldName with FieldDocImpl member.
   230      * Note: A serialField tag does not have to map an existing field
   231      *       of a class.
   232      */
   233     private void mapSerialFieldTagImplsToFieldDocImpls(FieldDocImpl spfDoc,
   234                                                        DocEnv env,
   235                                                        ClassSymbol def) {
   236         Names names = def.name.table.names;
   238         SerialFieldTag[] sfTag = spfDoc.serialFieldTags();
   239         for (int i = 0; i < sfTag.length; i++) {
   240             if (sfTag[i].fieldName() == null || sfTag[i].fieldType() == null) // ignore malformed @serialField tags
   241                 continue;
   243             Name fieldName = names.fromString(sfTag[i].fieldName());
   245             // Look for a FieldDocImpl that is documented by serialFieldTagImpl.
   246             for (Scope.Entry e = def.members().lookup(fieldName); e.scope != null; e = e.next()) {
   247                 if (e.sym.kind == Kinds.VAR) {
   248                     VarSymbol f = (VarSymbol)e.sym;
   249                     FieldDocImpl fdi = env.getFieldDoc(f);
   250                     ((SerialFieldTagImpl)(sfTag[i])).mapToFieldDocImpl(fdi);
   251                     break;
   252                 }
   253             }
   254         }
   255     }
   257     /**
   258      * Return serializable fields in class. <p>
   259      *
   260      * Returns either a list of default fields documented by serial tag comment or
   261      *         javadoc comment<p>
   262      * Or Returns a single FieldDocImpl for serialPersistentField. There is a
   263      *         serialField tag for each serializable field.<p>
   264      *
   265      * @return an array of FieldDocImpl for representing the visible
   266      *         fields in this class.
   267      */
   268     FieldDoc[] fields() {
   269         return (FieldDoc[])fields.toArray(new FieldDocImpl[fields.length()]);
   270     }
   272     /**
   273      * Return serialization methods in class.
   274      *
   275      * @return an array of MethodDocImpl for serialization methods in this class.
   276      */
   277     MethodDoc[] methods() {
   278         return methods.toArray(new MethodDoc[methods.length()]);
   279     }
   281     /**
   282      * Returns true if Serializable fields are defined explicitly using
   283      * member, serialPersistentFields.
   284      *
   285      * @see #fields()
   286      */
   287     boolean definesSerializableFields() {
   288         return definesSerializableFields;
   289     }
   290 }

mercurial