1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javadoc/SerializedForm.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,290 @@ 1.4 +/* 1.5 + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javadoc; 1.30 + 1.31 +import com.sun.javadoc.*; 1.32 +import com.sun.tools.javac.code.Flags; 1.33 +import com.sun.tools.javac.code.Kinds; 1.34 +import com.sun.tools.javac.code.Scope; 1.35 +import com.sun.tools.javac.code.Symbol.ClassSymbol; 1.36 +import com.sun.tools.javac.code.Symbol.MethodSymbol; 1.37 +import com.sun.tools.javac.code.Symbol.VarSymbol; 1.38 +import com.sun.tools.javac.util.ListBuffer; 1.39 +import com.sun.tools.javac.util.Name; 1.40 +import com.sun.tools.javac.util.Names; 1.41 + 1.42 +/** 1.43 + * The serialized form is the specification of a class' serialization 1.44 + * state. <p> 1.45 + * 1.46 + * It consists of the following information:<p> 1.47 + * 1.48 + * <pre> 1.49 + * 1. Whether class is Serializable or Externalizable. 1.50 + * 2. Javadoc for serialization methods. 1.51 + * a. For Serializable, the optional readObject, writeObject, 1.52 + * readResolve and writeReplace. 1.53 + * serialData tag describes, in prose, the sequence and type 1.54 + * of optional data written by writeObject. 1.55 + * b. For Externalizable, writeExternal and readExternal. 1.56 + * serialData tag describes, in prose, the sequence and type 1.57 + * of optional data written by writeExternal. 1.58 + * 3. Javadoc for serialization data layout. 1.59 + * a. For Serializable, the name,type and description 1.60 + * of each Serializable fields. 1.61 + * b. For Externalizable, data layout is described by 2(b). 1.62 + * </pre> 1.63 + * 1.64 + * <p><b>This is NOT part of any supported API. 1.65 + * If you write code that depends on this, you do so at your own risk. 1.66 + * This code and its internal interfaces are subject to change or 1.67 + * deletion without notice.</b> 1.68 + * 1.69 + * @since 1.2 1.70 + * @author Joe Fialli 1.71 + * @author Neal Gafter (rewrite but not too proud) 1.72 + */ 1.73 +class SerializedForm { 1.74 + ListBuffer<MethodDoc> methods = new ListBuffer<MethodDoc>(); 1.75 + 1.76 + /* List of FieldDocImpl - Serializable fields. 1.77 + * Singleton list if class defines Serializable fields explicitly. 1.78 + * Otherwise, list of default serializable fields. 1.79 + * 0 length list for Externalizable. 1.80 + */ 1.81 + private final ListBuffer<FieldDocImpl> fields = new ListBuffer<FieldDocImpl>(); 1.82 + 1.83 + /* True if class specifies serializable fields explicitly. 1.84 + * using special static member, serialPersistentFields. 1.85 + */ 1.86 + private boolean definesSerializableFields = false; 1.87 + 1.88 + // Specially treated field/method names defined by Serialization. 1.89 + private static final String SERIALIZABLE_FIELDS = "serialPersistentFields"; 1.90 + private static final String READOBJECT = "readObject"; 1.91 + private static final String WRITEOBJECT = "writeObject"; 1.92 + private static final String READRESOLVE = "readResolve"; 1.93 + private static final String WRITEREPLACE = "writeReplace"; 1.94 + private static final String READOBJECTNODATA = "readObjectNoData"; 1.95 + 1.96 + /** 1.97 + * Constructor. 1.98 + * 1.99 + * Catalog Serializable fields for Serializable class. 1.100 + * Catalog serialization methods for Serializable and 1.101 + * Externalizable classes. 1.102 + */ 1.103 + SerializedForm(DocEnv env, ClassSymbol def, ClassDocImpl cd) { 1.104 + if (cd.isExternalizable()) { 1.105 + /* look up required public accessible methods, 1.106 + * writeExternal and readExternal. 1.107 + */ 1.108 + String[] readExternalParamArr = { "java.io.ObjectInput" }; 1.109 + String[] writeExternalParamArr = { "java.io.ObjectOutput" }; 1.110 + MethodDoc md = cd.findMethod("readExternal", readExternalParamArr); 1.111 + if (md != null) { 1.112 + methods.append(md); 1.113 + } 1.114 + md = cd.findMethod("writeExternal", writeExternalParamArr); 1.115 + if (md != null) { 1.116 + methods.append(md); 1.117 + Tag tag[] = md.tags("serialData"); 1.118 + } 1.119 + // } else { // isSerializable() //### ??? 1.120 + } else if (cd.isSerializable()) { 1.121 + 1.122 + VarSymbol dsf = getDefinedSerializableFields(def); 1.123 + if (dsf != null) { 1.124 + 1.125 + /* Define serializable fields with array of ObjectStreamField. 1.126 + * Each ObjectStreamField should be documented by a 1.127 + * serialField tag. 1.128 + */ 1.129 + definesSerializableFields = true; 1.130 + //### No modifier filtering applied here. 1.131 + FieldDocImpl dsfDoc = env.getFieldDoc(dsf); 1.132 + fields.append(dsfDoc); 1.133 + mapSerialFieldTagImplsToFieldDocImpls(dsfDoc, env, def); 1.134 + } else { 1.135 + 1.136 + /* Calculate default Serializable fields as all 1.137 + * non-transient, non-static fields. 1.138 + * Fields should be documented by serial tag. 1.139 + */ 1.140 + computeDefaultSerializableFields(env, def, cd); 1.141 + } 1.142 + 1.143 + /* Check for optional customized readObject, writeObject, 1.144 + * readResolve and writeReplace, which can all contain 1.145 + * the serialData tag. */ 1.146 + addMethodIfExist(env, def, READOBJECT); 1.147 + addMethodIfExist(env, def, WRITEOBJECT); 1.148 + addMethodIfExist(env, def, READRESOLVE); 1.149 + addMethodIfExist(env, def, WRITEREPLACE); 1.150 + addMethodIfExist(env, def, READOBJECTNODATA); 1.151 + } 1.152 + } 1.153 + 1.154 + /* 1.155 + * Check for explicit Serializable fields. 1.156 + * Check for a private static array of ObjectStreamField with 1.157 + * name SERIALIZABLE_FIELDS. 1.158 + */ 1.159 + private VarSymbol getDefinedSerializableFields(ClassSymbol def) { 1.160 + Names names = def.name.table.names; 1.161 + 1.162 + /* SERIALIZABLE_FIELDS can be private, 1.163 + * so must lookup by ClassSymbol, not by ClassDocImpl. 1.164 + */ 1.165 + for (Scope.Entry e = def.members().lookup(names.fromString(SERIALIZABLE_FIELDS)); e.scope != null; e = e.next()) { 1.166 + if (e.sym.kind == Kinds.VAR) { 1.167 + VarSymbol f = (VarSymbol)e.sym; 1.168 + if ((f.flags() & Flags.STATIC) != 0 && 1.169 + (f.flags() & Flags.PRIVATE) != 0) { 1.170 + return f; 1.171 + } 1.172 + } 1.173 + } 1.174 + return null; 1.175 + } 1.176 + 1.177 + /* 1.178 + * Compute default Serializable fields from all members of ClassSymbol. 1.179 + * 1.180 + * Since the fields of ClassDocImpl might not contain private or 1.181 + * package accessible fields, must walk over all members of ClassSymbol. 1.182 + */ 1.183 + private void computeDefaultSerializableFields(DocEnv env, 1.184 + ClassSymbol def, 1.185 + ClassDocImpl cd) { 1.186 + for (Scope.Entry e = def.members().elems; e != null; e = e.sibling) { 1.187 + if (e.sym != null && e.sym.kind == Kinds.VAR) { 1.188 + VarSymbol f = (VarSymbol)e.sym; 1.189 + if ((f.flags() & Flags.STATIC) == 0 && 1.190 + (f.flags() & Flags.TRANSIENT) == 0) { 1.191 + //### No modifier filtering applied here. 1.192 + FieldDocImpl fd = env.getFieldDoc(f); 1.193 + //### Add to beginning. 1.194 + //### Preserve order used by old 'javadoc'. 1.195 + fields.prepend(fd); 1.196 + } 1.197 + } 1.198 + } 1.199 + } 1.200 + 1.201 + /* 1.202 + * Catalog Serializable method if it exists in current ClassSymbol. 1.203 + * Do not look for method in superclasses. 1.204 + * 1.205 + * Serialization requires these methods to be non-static. 1.206 + * 1.207 + * @param method should be an unqualified Serializable method 1.208 + * name either READOBJECT, WRITEOBJECT, READRESOLVE 1.209 + * or WRITEREPLACE. 1.210 + * @param visibility the visibility flag for the given method. 1.211 + */ 1.212 + private void addMethodIfExist(DocEnv env, ClassSymbol def, String methodName) { 1.213 + Names names = def.name.table.names; 1.214 + 1.215 + for (Scope.Entry e = def.members().lookup(names.fromString(methodName)); e.scope != null; e = e.next()) { 1.216 + if (e.sym.kind == Kinds.MTH) { 1.217 + MethodSymbol md = (MethodSymbol)e.sym; 1.218 + if ((md.flags() & Flags.STATIC) == 0) { 1.219 + /* 1.220 + * WARNING: not robust if unqualifiedMethodName is overloaded 1.221 + * method. Signature checking could make more robust. 1.222 + * READOBJECT takes a single parameter, java.io.ObjectInputStream. 1.223 + * WRITEOBJECT takes a single parameter, java.io.ObjectOutputStream. 1.224 + */ 1.225 + methods.append(env.getMethodDoc(md)); 1.226 + } 1.227 + } 1.228 + } 1.229 + } 1.230 + 1.231 + /* 1.232 + * Associate serialField tag fieldName with FieldDocImpl member. 1.233 + * Note: A serialField tag does not have to map an existing field 1.234 + * of a class. 1.235 + */ 1.236 + private void mapSerialFieldTagImplsToFieldDocImpls(FieldDocImpl spfDoc, 1.237 + DocEnv env, 1.238 + ClassSymbol def) { 1.239 + Names names = def.name.table.names; 1.240 + 1.241 + SerialFieldTag[] sfTag = spfDoc.serialFieldTags(); 1.242 + for (int i = 0; i < sfTag.length; i++) { 1.243 + if (sfTag[i].fieldName() == null || sfTag[i].fieldType() == null) // ignore malformed @serialField tags 1.244 + continue; 1.245 + 1.246 + Name fieldName = names.fromString(sfTag[i].fieldName()); 1.247 + 1.248 + // Look for a FieldDocImpl that is documented by serialFieldTagImpl. 1.249 + for (Scope.Entry e = def.members().lookup(fieldName); e.scope != null; e = e.next()) { 1.250 + if (e.sym.kind == Kinds.VAR) { 1.251 + VarSymbol f = (VarSymbol)e.sym; 1.252 + FieldDocImpl fdi = env.getFieldDoc(f); 1.253 + ((SerialFieldTagImpl)(sfTag[i])).mapToFieldDocImpl(fdi); 1.254 + break; 1.255 + } 1.256 + } 1.257 + } 1.258 + } 1.259 + 1.260 + /** 1.261 + * Return serializable fields in class. <p> 1.262 + * 1.263 + * Returns either a list of default fields documented by serial tag comment or 1.264 + * javadoc comment<p> 1.265 + * Or Returns a single FieldDocImpl for serialPersistentField. There is a 1.266 + * serialField tag for each serializable field.<p> 1.267 + * 1.268 + * @return an array of FieldDocImpl for representing the visible 1.269 + * fields in this class. 1.270 + */ 1.271 + FieldDoc[] fields() { 1.272 + return (FieldDoc[])fields.toArray(new FieldDocImpl[fields.length()]); 1.273 + } 1.274 + 1.275 + /** 1.276 + * Return serialization methods in class. 1.277 + * 1.278 + * @return an array of MethodDocImpl for serialization methods in this class. 1.279 + */ 1.280 + MethodDoc[] methods() { 1.281 + return methods.toArray(new MethodDoc[methods.length()]); 1.282 + } 1.283 + 1.284 + /** 1.285 + * Returns true if Serializable fields are defined explicitly using 1.286 + * member, serialPersistentFields. 1.287 + * 1.288 + * @see #fields() 1.289 + */ 1.290 + boolean definesSerializableFields() { 1.291 + return definesSerializableFields; 1.292 + } 1.293 +}