1/* 2 * Copyright (c) 1998, 2014, 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 26package com.sun.tools.javadoc.main; 27 28import com.sun.javadoc.*; 29import com.sun.tools.javac.code.*; 30import com.sun.tools.javac.code.Symbol.ClassSymbol; 31import com.sun.tools.javac.code.Symbol.MethodSymbol; 32import com.sun.tools.javac.code.Symbol.VarSymbol; 33import com.sun.tools.javac.util.*; 34 35import static com.sun.tools.javac.code.Kinds.Kind.*; 36import 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 70class SerializedForm { 71 ListBuffer<MethodDoc> methods = new ListBuffer<>(); 72 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<>(); 79 80 /* True if class specifies serializable fields explicitly. 81 * using special static member, serialPersistentFields. 82 */ 83 private boolean definesSerializableFields = false; 84 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"; 92 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()) { 118 119 VarSymbol dsf = getDefinedSerializableFields(def); 120 if (dsf != null) { 121 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 { 132 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 } 139 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 } 150 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; 158 159 /* SERIALIZABLE_FIELDS can be private, 160 * so must lookup by ClassSymbol, not by ClassDocImpl. 161 */ 162 for (Symbol sym : def.members().getSymbolsByName(names.fromString(SERIALIZABLE_FIELDS))) { 163 if (sym.kind == VAR) { 164 VarSymbol f = (VarSymbol)sym; 165 if ((f.flags() & Flags.STATIC) != 0 && 166 (f.flags() & Flags.PRIVATE) != 0) { 167 return f; 168 } 169 } 170 } 171 return null; 172 } 173 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 (Symbol sym : def.members().getSymbols(NON_RECURSIVE)) { 184 if (sym != null && sym.kind == VAR) { 185 VarSymbol f = (VarSymbol)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 } 197 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; 211 212 for (Symbol sym : def.members().getSymbolsByName(names.fromString(methodName))) { 213 if (sym.kind == MTH) { 214 MethodSymbol md = (MethodSymbol)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 } 227 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; 237 for (SerialFieldTag tag : spfDoc.serialFieldTags()) { 238 if (tag.fieldName() == null || tag.fieldType() == null) // ignore malformed @serialField tags 239 continue; 240 241 Name fieldName = names.fromString(tag.fieldName()); 242 243 // Look for a FieldDocImpl that is documented by serialFieldTagImpl. 244 for (Symbol sym : def.members().getSymbolsByName(fieldName)) { 245 if (sym.kind == VAR) { 246 VarSymbol f = (VarSymbol) sym; 247 FieldDocImpl fdi = env.getFieldDoc(f); 248 ((SerialFieldTagImpl) (tag)).mapToFieldDocImpl(fdi); 249 break; 250 } 251 } 252 } 253 } 254 255 /** 256 * Return serializable fields in class. <p> 257 * 258 * Returns either a list of default fields documented by serial tag comment or 259 * javadoc comment<p> 260 * Or Returns a single FieldDocImpl for serialPersistentField. There is a 261 * serialField tag for each serializable field.<p> 262 * 263 * @return an array of FieldDocImpl for representing the visible 264 * fields in this class. 265 */ 266 FieldDoc[] fields() { 267 return (FieldDoc[])fields.toArray(new FieldDocImpl[fields.length()]); 268 } 269 270 /** 271 * Return serialization methods in class. 272 * 273 * @return an array of MethodDocImpl for serialization methods in this class. 274 */ 275 MethodDoc[] methods() { 276 return methods.toArray(new MethodDoc[methods.length()]); 277 } 278 279 /** 280 * Returns true if Serializable fields are defined explicitly using 281 * member, serialPersistentFields. 282 * 283 * @see #fields() 284 */ 285 boolean definesSerializableFields() { 286 return definesSerializableFields; 287 } 288} 289