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