1 /* 2 * Copyright (c) 2003, 2015, 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.doclets.internal.toolkit.builders; 27 28 import java.io.*; 29 import java.util.*; 30 31 import com.sun.javadoc.*; 32 import com.sun.tools.doclets.internal.toolkit.*; 33 import com.sun.tools.doclets.internal.toolkit.util.*; 34 import com.sun.tools.javac.util.StringUtils; 35 36 /** 37 * Builds the serialized form. 38 * 39 * <p><b>This is NOT part of any supported API. 40 * If you write code that depends on this, you do so at your own risk. 41 * This code and its internal interfaces are subject to change or 42 * deletion without notice.</b> 43 * 44 * @author Jamie Ho 45 * @author Bhavesh Patel (Modified) 46 * @since 1.5 47 */ 48 public class SerializedFormBuilder extends AbstractBuilder { 49 50 /** 51 * The root element of the serialized form XML is {@value}. 52 */ 53 public static final String NAME = "SerializedForm"; 54 55 /** 56 * The writer for this builder. 57 */ 58 private SerializedFormWriter writer; 59 60 /** 61 * The writer for serializable fields. 62 */ 63 private SerializedFormWriter.SerialFieldWriter fieldWriter; 64 65 /** 66 * The writer for serializable method documentation. 67 */ 68 private SerializedFormWriter.SerialMethodWriter methodWriter; 69 70 /** 71 * The header for the serial version UID. Save the string 72 * here instead of the properties file because we do not want 73 * this string to be localized. 74 */ 75 private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:"; 76 77 /** 78 * The current package being documented. 79 */ 80 private PackageDoc currentPackage; 81 82 /** 83 * The current class being documented. 84 */ 85 private ClassDoc currentClass; 86 87 /** 88 * The current member being documented. 89 */ 90 protected MemberDoc currentMember; 91 92 /** 93 * The content that will be added to the serialized form documentation tree. 94 */ 95 private Content contentTree; 96 97 98 /** 99 * Construct a new SerializedFormBuilder. 100 * @param context the build context. 101 */ 102 private SerializedFormBuilder(Context context) { 103 super(context); 104 } 105 106 /** 107 * Construct a new SerializedFormBuilder. 108 * @param context the build context. 109 */ 110 public static SerializedFormBuilder getInstance(Context context) { 111 return new SerializedFormBuilder(context); 112 } 113 114 /** 115 * Build the serialized form. 116 */ 117 public void build() throws IOException { 118 if (! serialClassFoundToDocument(configuration.root.classes())) { 119 //Nothing to document. 120 return; 121 } 122 try { 123 writer = configuration.getWriterFactory().getSerializedFormWriter(); 124 if (writer == null) { 125 //Doclet does not support this output. 126 return; 127 } 128 } catch (Exception e) { 129 throw new DocletAbortException(e); 130 } 131 build(layoutParser.parseXML(NAME), contentTree); 132 writer.close(); 133 } 134 135 /** 136 * {@inheritDoc} 137 */ 138 public String getName() { 145 * @param node the XML element that specifies which components to document 146 * @param serializedTree content tree to which the documentation will be added 147 */ 148 public void buildSerializedForm(XMLNode node, Content serializedTree) throws Exception { 149 serializedTree = writer.getHeader(configuration.getText( 150 "doclet.Serialized_Form")); 151 buildChildren(node, serializedTree); 152 writer.addFooter(serializedTree); 153 writer.printDocument(serializedTree); 154 writer.close(); 155 } 156 157 /** 158 * Build the serialized form summaries. 159 * 160 * @param node the XML element that specifies which components to document 161 * @param serializedTree content tree to which the documentation will be added 162 */ 163 public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) { 164 Content serializedSummariesTree = writer.getSerializedSummariesHeader(); 165 for (PackageDoc pkg : configuration.packages) { 166 currentPackage = pkg; 167 buildChildren(node, serializedSummariesTree); 168 } 169 serializedTree.addContent(writer.getSerializedContent( 170 serializedSummariesTree)); 171 } 172 173 /** 174 * Build the package serialized form for the current package being processed. 175 * 176 * @param node the XML element that specifies which components to document 177 * @param serializedSummariesTree content tree to which the documentation will be added 178 */ 179 public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) { 180 Content packageSerializedTree = writer.getPackageSerializedHeader(); 181 String foo = currentPackage.name(); 182 ClassDoc[] classes = currentPackage.allClasses(false); 183 if (classes == null || classes.length == 0) { 184 return; 185 } 186 if (!serialInclude(currentPackage)) { 187 return; 188 } 189 if (!serialClassFoundToDocument(classes)) { 190 return; 191 } 192 buildChildren(node, packageSerializedTree); 193 writer.addPackageSerializedTree(serializedSummariesTree, packageSerializedTree); 194 } 195 196 /** 197 * Build the package header. 198 * 199 * @param node the XML element that specifies which components to document 200 * @param packageSerializedTree content tree to which the documentation will be added 201 */ 202 public void buildPackageHeader(XMLNode node, Content packageSerializedTree) { 203 packageSerializedTree.addContent(writer.getPackageHeader( 204 utils.getPackageName(currentPackage))); 205 } 206 207 /** 208 * Build the class serialized form. 209 * 210 * @param node the XML element that specifies which components to document 211 * @param packageSerializedTree content tree to which the documentation will be added 212 */ 213 public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) { 214 Content classSerializedTree = writer.getClassSerializedHeader(); 215 ClassDoc[] classes = currentPackage.allClasses(false); 216 Arrays.sort(classes); 217 for (ClassDoc classDoc : classes) { 218 currentClass = classDoc; 219 fieldWriter = writer.getSerialFieldWriter(currentClass); 220 methodWriter = writer.getSerialMethodWriter(currentClass); 221 if (currentClass.isClass() && currentClass.isSerializable()) { 222 if (!serialClassInclude(currentClass)) { 223 continue; 224 } 225 Content classTree = writer.getClassHeader(currentClass); 226 buildChildren(node, classTree); 227 classSerializedTree.addContent(classTree); 228 } 229 } 230 packageSerializedTree.addContent(classSerializedTree); 231 } 232 233 /** 234 * Build the serial UID information for the given class. 235 * 236 * @param node the XML element that specifies which components to document 237 * @param classTree content tree to which the serial UID information will be added 238 */ 239 public void buildSerialUIDInfo(XMLNode node, Content classTree) { 240 Content serialUidTree = writer.getSerialUIDInfoHeader(); 241 for (FieldDoc field : currentClass.fields(false)) { 242 if (field.name().equals("serialVersionUID") && 243 field.constantValueExpression() != null) { 244 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER, 245 field.constantValueExpression(), serialUidTree); 246 break; 247 } 248 } 249 classTree.addContent(serialUidTree); 250 } 251 252 /** 253 * Build the summaries for the methods and fields. 254 * 255 * @param node the XML element that specifies which components to document 256 * @param classTree content tree to which the documentation will be added 257 */ 258 public void buildClassContent(XMLNode node, Content classTree) { 259 Content classContentTree = writer.getClassContentHeader(); 260 buildChildren(node, classContentTree); 261 classTree.addContent(classContentTree); 262 } 263 264 /** 265 * Build the summaries for the methods that belong to the given 266 * class. 267 * 268 * @param node the XML element that specifies which components to document 269 * @param classContentTree content tree to which the documentation will be added 270 */ 271 public void buildSerializableMethods(XMLNode node, Content classContentTree) { 272 Content serializableMethodTree = methodWriter.getSerializableMethodsHeader(); 273 MemberDoc[] members = currentClass.serializationMethods(); 274 int membersLength = members.length; 275 if (membersLength > 0) { 276 for (int i = 0; i < membersLength; i++) { 277 currentMember = members[i]; 278 Content methodsContentTree = methodWriter.getMethodsContentHeader( 279 (i == membersLength - 1)); 280 buildChildren(node, methodsContentTree); 281 serializableMethodTree.addContent(methodsContentTree); 282 } 283 } 284 if (currentClass.serializationMethods().length > 0) { 285 classContentTree.addContent(methodWriter.getSerializableMethods( 286 configuration.getText("doclet.Serialized_Form_methods"), 287 serializableMethodTree)); 288 if (currentClass.isSerializable() && !currentClass.isExternalizable()) { 289 if (currentClass.serializationMethods().length == 0) { 290 Content noCustomizationMsg = methodWriter.getNoCustomizationMsg( 291 configuration.getText( 292 "doclet.Serializable_no_customization")); 293 classContentTree.addContent(methodWriter.getSerializableMethods( 294 configuration.getText("doclet.Serialized_Form_methods"), 295 noCustomizationMsg)); 296 } 297 } 298 } 299 } 300 301 /** 302 * Build the method sub header. 303 * 304 * @param node the XML element that specifies which components to document 305 * @param methodsContentTree content tree to which the documentation will be added 306 */ 307 public void buildMethodSubHeader(XMLNode node, Content methodsContentTree) { 308 methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree); 309 } 310 311 /** 312 * Build the deprecated method description. 313 * 314 * @param node the XML element that specifies which components to document 315 * @param methodsContentTree content tree to which the documentation will be added 316 */ 317 public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) { 318 methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree); 319 } 320 321 /** 322 * Build the information for the method. 323 * 324 * @param node the XML element that specifies which components to document 325 * @param methodsContentTree content tree to which the documentation will be added 326 */ 327 public void buildMethodInfo(XMLNode node, Content methodsContentTree) { 328 if(configuration.nocomment){ 329 return; 330 } 331 buildChildren(node, methodsContentTree); 332 } 333 334 /** 335 * Build method description. 336 * 337 * @param node the XML element that specifies which components to document 338 * @param methodsContentTree content tree to which the documentation will be added 339 */ 340 public void buildMethodDescription(XMLNode node, Content methodsContentTree) { 341 methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree); 342 } 343 344 /** 345 * Build the method tags. 346 * 347 * @param node the XML element that specifies which components to document 348 * @param methodsContentTree content tree to which the documentation will be added 349 */ 350 public void buildMethodTags(XMLNode node, Content methodsContentTree) { 351 methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree); 352 MethodDoc method = (MethodDoc)currentMember; 353 if (method.name().compareTo("writeExternal") == 0 354 && method.tags("serialData").length == 0) { 355 if (configuration.serialwarn) { 356 configuration.getDocletSpecificMsg().warning( 357 currentMember.position(), "doclet.MissingSerialDataTag", 358 method.containingClass().qualifiedName(), method.name()); 359 } 360 } 361 } 362 363 /** 364 * Build the field header. 365 * 366 * @param node the XML element that specifies which components to document 367 * @param classContentTree content tree to which the documentation will be added 368 */ 369 public void buildFieldHeader(XMLNode node, Content classContentTree) { 370 if (currentClass.serializableFields().length > 0) { 371 buildFieldSerializationOverview(currentClass, classContentTree); 372 } 373 } 374 375 /** 376 * Build the serialization overview for the given class. 377 * 378 * @param classDoc the class to print the overview for. 379 * @param classContentTree content tree to which the documentation will be added 380 */ 381 public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) { 382 if (classDoc.definesSerializableFields()) { 383 FieldDoc serialPersistentField = classDoc.serializableFields()[0]; 384 // Check to see if there are inline comments, tags or deprecation 385 // information to be printed. 386 if (fieldWriter.shouldPrintOverview(serialPersistentField)) { 387 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); 388 Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true); 389 fieldWriter.addMemberDeprecatedInfo(serialPersistentField, 390 fieldsOverviewContentTree); 391 if (!configuration.nocomment) { 392 fieldWriter.addMemberDescription(serialPersistentField, 393 fieldsOverviewContentTree); 394 fieldWriter.addMemberTags(serialPersistentField, 395 fieldsOverviewContentTree); 396 } 397 serializableFieldsTree.addContent(fieldsOverviewContentTree); 398 classContentTree.addContent(fieldWriter.getSerializableFields( 399 configuration.getText("doclet.Serialized_Form_class"), 400 serializableFieldsTree)); 401 } 402 } 403 } 404 405 /** 406 * Build the summaries for the fields that belong to the given class. 407 * 408 * @param node the XML element that specifies which components to document 409 * @param classContentTree content tree to which the documentation will be added 410 */ 411 public void buildSerializableFields(XMLNode node, Content classContentTree) { 412 MemberDoc[] members = currentClass.serializableFields(); 413 int membersLength = members.length; 414 if (membersLength > 0) { 415 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); 416 for (int i = 0; i < membersLength; i++) { 417 currentMember = members[i]; 418 if (!currentClass.definesSerializableFields()) { 419 Content fieldsContentTree = fieldWriter.getFieldsContentHeader( 420 (i == membersLength - 1)); 421 buildChildren(node, fieldsContentTree); 422 serializableFieldsTree.addContent(fieldsContentTree); 423 } 424 else { 425 buildSerialFieldTagsInfo(serializableFieldsTree); 426 } 427 } 428 classContentTree.addContent(fieldWriter.getSerializableFields( 429 configuration.getText("doclet.Serialized_Form_fields"), 430 serializableFieldsTree)); 431 } 432 } 433 434 /** 435 * Build the field sub header. 436 * 437 * @param node the XML element that specifies which components to document 438 * @param fieldsContentTree content tree to which the documentation will be added 439 */ 440 public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) { 441 if (!currentClass.definesSerializableFields()) { 442 FieldDoc field = (FieldDoc) currentMember; 443 fieldWriter.addMemberHeader(field.type().asClassDoc(), 444 field.type().typeName(), field.type().dimension(), field.name(), 445 fieldsContentTree); 446 } 447 } 448 449 /** 450 * Build the field deprecation information. 451 * 452 * @param node the XML element that specifies which components to document 453 * @param fieldsContentTree content tree to which the documentation will be added 454 */ 455 public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) { 456 if (!currentClass.definesSerializableFields()) { 457 FieldDoc field = (FieldDoc)currentMember; 458 fieldWriter.addMemberDeprecatedInfo(field, fieldsContentTree); 459 } 460 } 461 462 /** 463 * Build the serial field tags information. 464 * 465 * @param serializableFieldsTree content tree to which the documentation will be added 466 */ 467 public void buildSerialFieldTagsInfo(Content serializableFieldsTree) { 468 if(configuration.nocomment){ 469 return; 470 } 471 FieldDoc field = (FieldDoc)currentMember; 472 // Process Serializable Fields specified as array of 473 // ObjectStreamFields. Print a member for each serialField tag. 474 // (There should be one serialField tag per ObjectStreamField 475 // element.) 476 SerialFieldTag[] tags = field.serialFieldTags(); 477 Arrays.sort(tags); 478 int tagsLength = tags.length; 479 for (int i = 0; i < tagsLength; i++) { 480 if (tags[i].fieldName() == null || tags[i].fieldType() == null) // ignore malformed @serialField tags 481 continue; 482 Content fieldsContentTree = fieldWriter.getFieldsContentHeader( 483 (i == tagsLength - 1)); 484 fieldWriter.addMemberHeader(tags[i].fieldTypeDoc(), 485 tags[i].fieldType(), "", tags[i].fieldName(), fieldsContentTree); 486 fieldWriter.addMemberDescription(tags[i], fieldsContentTree); 487 serializableFieldsTree.addContent(fieldsContentTree); 488 } 489 } 490 491 /** 492 * Build the field information. 493 * 494 * @param node the XML element that specifies which components to document 495 * @param fieldsContentTree content tree to which the documentation will be added 496 */ 497 public void buildFieldInfo(XMLNode node, Content fieldsContentTree) { 498 if(configuration.nocomment){ 499 return; 500 } 501 FieldDoc field = (FieldDoc)currentMember; 502 ClassDoc cd = field.containingClass(); 503 // Process default Serializable field. 504 if ((field.tags("serial").length == 0) && ! field.isSynthetic() 505 && configuration.serialwarn) { 506 configuration.message.warning(field.position(), 507 "doclet.MissingSerialTag", cd.qualifiedName(), 508 field.name()); 509 } 510 fieldWriter.addMemberDescription(field, fieldsContentTree); 511 fieldWriter.addMemberTags(field, fieldsContentTree); 512 } 513 514 /** 515 * Return true if the given Doc should be included 516 * in the serialized form. 517 * 518 * @param doc the Doc object to check for serializability. 519 */ 520 public static boolean serialInclude(Doc doc) { 521 if (doc == null) { 522 return false; 523 } 524 return doc.isClass() ? 525 serialClassInclude((ClassDoc)doc) : 526 serialDocInclude(doc); 527 } 528 529 /** 530 * Return true if the given ClassDoc should be included 531 * in the serialized form. 532 * 533 * @param cd the ClassDoc object to check for serializability. 534 */ 535 private static boolean serialClassInclude(ClassDoc cd) { 536 if (cd.isEnum()) { 537 return false; 538 } 539 try { 540 cd.superclassType(); 541 } catch (NullPointerException e) { 542 //Workaround for null pointer bug in ClassDoc.superclassType(). 543 return false; 544 } 545 if (cd.isSerializable()) { 546 if (cd.tags("serial").length > 0) { 547 return serialDocInclude(cd); 548 } else if (cd.isPublic() || cd.isProtected()) { 549 return true; 550 } else { 551 return false; 552 } 553 } 554 return false; 555 } 556 557 /** 558 * Return true if the given Doc should be included 559 * in the serialized form. 560 * 561 * @param doc the Doc object to check for serializability. 562 */ 563 private static boolean serialDocInclude(Doc doc) { 564 if (doc.isEnum()) { 565 return false; 566 } 567 Tag[] serial = doc.tags("serial"); 568 if (serial.length > 0) { 569 String serialtext = StringUtils.toLowerCase(serial[0].text()); 570 if (serialtext.contains("exclude")) { 571 return false; 572 } else if (serialtext.contains("include")) { 573 return true; 574 } 575 } 576 return true; 577 } 578 579 /** 580 * Return true if any of the given classes have a @serialinclude tag. 581 * 582 * @param classes the classes to check. 583 * @return true if any of the given classes have a @serialinclude tag. 584 */ 585 private boolean serialClassFoundToDocument(ClassDoc[] classes) { 586 for (ClassDoc aClass : classes) { 587 if (serialClassInclude(aClass)) { 588 return true; 589 } 590 } 591 return false; 592 } 593 } | 1 /* 2 * Copyright (c) 2003, 2016, 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 jdk.javadoc.internal.doclets.toolkit.builders; 27 28 import java.io.*; 29 import java.util.*; 30 31 import javax.lang.model.element.Element; 32 import javax.lang.model.element.ExecutableElement; 33 import javax.lang.model.element.PackageElement; 34 import javax.lang.model.element.TypeElement; 35 import javax.lang.model.element.VariableElement; 36 37 import com.sun.source.doctree.DocTree; 38 import com.sun.source.doctree.SerialFieldTree; 39 import jdk.javadoc.internal.doclets.toolkit.Content; 40 import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; 41 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; 42 import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; 43 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 44 45 /** 46 * Builds the serialized form. 47 * 48 * <p><b>This is NOT part of any supported API. 49 * If you write code that depends on this, you do so at your own risk. 50 * This code and its internal interfaces are subject to change or 51 * deletion without notice.</b> 52 * 53 * @author Jamie Ho 54 * @author Bhavesh Patel (Modified) 55 * @since 1.5 56 */ 57 public class SerializedFormBuilder extends AbstractBuilder { 58 59 /** 60 * The root element of the serialized form XML is {@value}. 61 */ 62 public static final String NAME = "SerializedForm"; 63 64 /** 65 * The writer for this builder. 66 */ 67 private SerializedFormWriter writer; 68 69 /** 70 * The writer for serializable fields. 71 */ 72 private SerializedFormWriter.SerialFieldWriter fieldWriter; 73 74 /** 75 * The writer for serializable method documentation. 76 */ 77 private SerializedFormWriter.SerialMethodWriter methodWriter; 78 79 /** 80 * The header for the serial version UID. Save the string 81 * here instead of the properties file because we do not want 82 * this string to be localized. 83 */ 84 private static final String SERIAL_VERSION_UID = "serialVersionUID"; 85 private static final String SERIAL_VERSION_UID_HEADER = SERIAL_VERSION_UID + ":"; 86 87 /** 88 * The current package being documented. 89 */ 90 private PackageElement currentPackage; 91 92 /** 93 * The current class being documented. 94 */ 95 private TypeElement currentTypeElement; 96 97 /** 98 * The current member being documented. 99 */ 100 protected Element currentMember; 101 102 /** 103 * The content that will be added to the serialized form documentation tree. 104 */ 105 private Content contentTree; 106 107 108 /** 109 * Construct a new SerializedFormBuilder. 110 * @param context the build context. 111 */ 112 private SerializedFormBuilder(Context context) { 113 super(context); 114 } 115 116 /** 117 * Construct a new SerializedFormBuilder. 118 * @param context the build context. 119 */ 120 public static SerializedFormBuilder getInstance(Context context) { 121 return new SerializedFormBuilder(context); 122 } 123 124 /** 125 * Build the serialized form. 126 */ 127 public void build() throws IOException { 128 SortedSet<TypeElement> rootclasses = new TreeSet<>(utils.makeGeneralPurposeComparator()); 129 rootclasses.addAll(configuration.root.getIncludedClasses()); 130 if (!serialClassFoundToDocument(rootclasses)) { 131 //Nothing to document. 132 return; 133 } 134 try { 135 writer = configuration.getWriterFactory().getSerializedFormWriter(); 136 if (writer == null) { 137 //Doclet does not support this output. 138 return; 139 } 140 } catch (Exception e) { 141 throw new DocletAbortException(e); 142 } 143 build(layoutParser.parseXML(NAME), contentTree); 144 writer.close(); 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 public String getName() { 157 * @param node the XML element that specifies which components to document 158 * @param serializedTree content tree to which the documentation will be added 159 */ 160 public void buildSerializedForm(XMLNode node, Content serializedTree) throws Exception { 161 serializedTree = writer.getHeader(configuration.getText( 162 "doclet.Serialized_Form")); 163 buildChildren(node, serializedTree); 164 writer.addFooter(serializedTree); 165 writer.printDocument(serializedTree); 166 writer.close(); 167 } 168 169 /** 170 * Build the serialized form summaries. 171 * 172 * @param node the XML element that specifies which components to document 173 * @param serializedTree content tree to which the documentation will be added 174 */ 175 public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) { 176 Content serializedSummariesTree = writer.getSerializedSummariesHeader(); 177 for (PackageElement pkg : configuration.packages) { 178 currentPackage = pkg; 179 buildChildren(node, serializedSummariesTree); 180 } 181 serializedTree.addContent(writer.getSerializedContent( 182 serializedSummariesTree)); 183 } 184 185 /** 186 * Build the package serialized form for the current package being processed. 187 * 188 * @param node the XML element that specifies which components to document 189 * @param serializedSummariesTree content tree to which the documentation will be added 190 */ 191 public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) { 192 Content packageSerializedTree = writer.getPackageSerializedHeader(); 193 SortedSet<TypeElement> classes = utils.getAllClassesUnfiltered(currentPackage); 194 if (classes.isEmpty()) { 195 return; 196 } 197 if (!serialInclude(utils, currentPackage)) { 198 return; 199 } 200 if (!serialClassFoundToDocument(classes)) { 201 return; 202 } 203 buildChildren(node, packageSerializedTree); 204 writer.addPackageSerializedTree(serializedSummariesTree, packageSerializedTree); 205 } 206 207 /** 208 * Build the package header. 209 * 210 * @param node the XML element that specifies which components to document 211 * @param packageSerializedTree content tree to which the documentation will be added 212 */ 213 public void buildPackageHeader(XMLNode node, Content packageSerializedTree) { 214 packageSerializedTree.addContent(writer.getPackageHeader( 215 utils.getPackageName(currentPackage))); 216 } 217 218 /** 219 * Build the class serialized form. 220 * 221 * @param node the XML element that specifies which components to document 222 * @param packageSerializedTree content tree to which the documentation will be added 223 */ 224 public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) { 225 Content classSerializedTree = writer.getClassSerializedHeader(); 226 SortedSet<TypeElement> typeElements = utils.getAllClassesUnfiltered(currentPackage); 227 for (TypeElement typeElement : typeElements) { 228 currentTypeElement = typeElement; 229 fieldWriter = writer.getSerialFieldWriter(currentTypeElement); 230 methodWriter = writer.getSerialMethodWriter(currentTypeElement); 231 if (utils.isClass(currentTypeElement) && utils.isSerializable(currentTypeElement)) { 232 if (!serialClassInclude(utils, currentTypeElement)) { 233 continue; 234 } 235 Content classTree = writer.getClassHeader(currentTypeElement); 236 buildChildren(node, classTree); 237 classSerializedTree.addContent(classTree); 238 } 239 } 240 packageSerializedTree.addContent(classSerializedTree); 241 } 242 243 /** 244 * Build the serial UID information for the given class. 245 * 246 * @param node the XML element that specifies which components to document 247 * @param classTree content tree to which the serial UID information will be added 248 */ 249 public void buildSerialUIDInfo(XMLNode node, Content classTree) { 250 Content serialUidTree = writer.getSerialUIDInfoHeader(); 251 for (Element e : utils.getFieldsUnfiltered(currentTypeElement)) { 252 VariableElement field = (VariableElement)e; 253 if (field.getSimpleName().toString().compareTo(SERIAL_VERSION_UID) == 0 && 254 field.getConstantValue() != null) { 255 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER, 256 utils.constantValueExpresion(field), serialUidTree); 257 break; 258 } 259 } 260 classTree.addContent(serialUidTree); 261 } 262 263 /** 264 * Build the summaries for the methods and fields. 265 * 266 * @param node the XML element that specifies which components to document 267 * @param classTree content tree to which the documentation will be added 268 */ 269 public void buildClassContent(XMLNode node, Content classTree) { 270 Content classContentTree = writer.getClassContentHeader(); 271 buildChildren(node, classContentTree); 272 classTree.addContent(classContentTree); 273 } 274 275 /** 276 * Build the summaries for the methods that belong to the given 277 * class. 278 * 279 * @param node the XML element that specifies which components to document 280 * @param classContentTree content tree to which the documentation will be added 281 */ 282 public void buildSerializableMethods(XMLNode node, Content classContentTree) { 283 Content serializableMethodTree = methodWriter.getSerializableMethodsHeader(); 284 SortedSet<ExecutableElement> members = utils.serializationMethods(currentTypeElement); 285 if (!members.isEmpty()) { 286 for (ExecutableElement member : members) { 287 currentMember = member; 288 Content methodsContentTree = methodWriter.getMethodsContentHeader( 289 currentMember == members.last()); 290 buildChildren(node, methodsContentTree); 291 serializableMethodTree.addContent(methodsContentTree); 292 } 293 } 294 if (!utils.serializationMethods(currentTypeElement).isEmpty()) { 295 classContentTree.addContent(methodWriter.getSerializableMethods( 296 configuration.getText("doclet.Serialized_Form_methods"), 297 serializableMethodTree)); 298 if (utils.isSerializable(currentTypeElement) && !utils.isExternalizable(currentTypeElement)) { 299 if (utils.serializationMethods(currentTypeElement).isEmpty()) { 300 Content noCustomizationMsg = methodWriter.getNoCustomizationMsg( 301 configuration.getText("doclet.Serializable_no_customization")); 302 classContentTree.addContent(methodWriter.getSerializableMethods( 303 configuration.getText("doclet.Serialized_Form_methods"), 304 noCustomizationMsg)); 305 } 306 } 307 } 308 } 309 310 /** 311 * Build the method sub header. 312 * 313 * @param node the XML element that specifies which components to document 314 * @param methodsContentTree content tree to which the documentation will be added 315 */ 316 public void buildMethodSubHeader(XMLNode node, Content methodsContentTree) { 317 methodWriter.addMemberHeader((ExecutableElement)currentMember, methodsContentTree); 318 } 319 320 /** 321 * Build the deprecated method description. 322 * 323 * @param node the XML element that specifies which components to document 324 * @param methodsContentTree content tree to which the documentation will be added 325 */ 326 public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) { 327 methodWriter.addDeprecatedMemberInfo((ExecutableElement)currentMember, methodsContentTree); 328 } 329 330 /** 331 * Build the information for the method. 332 * 333 * @param node the XML element that specifies which components to document 334 * @param methodsContentTree content tree to which the documentation will be added 335 */ 336 public void buildMethodInfo(XMLNode node, Content methodsContentTree) { 337 if(configuration.nocomment){ 338 return; 339 } 340 buildChildren(node, methodsContentTree); 341 } 342 343 /** 344 * Build method description. 345 * 346 * @param node the XML element that specifies which components to document 347 * @param methodsContentTree content tree to which the documentation will be added 348 */ 349 public void buildMethodDescription(XMLNode node, Content methodsContentTree) { 350 methodWriter.addMemberDescription((ExecutableElement)currentMember, methodsContentTree); 351 } 352 353 /** 354 * Build the method tags. 355 * 356 * @param node the XML element that specifies which components to document 357 * @param methodsContentTree content tree to which the documentation will be added 358 */ 359 public void buildMethodTags(XMLNode node, Content methodsContentTree) { 360 methodWriter.addMemberTags((ExecutableElement)currentMember, methodsContentTree); 361 ExecutableElement method = (ExecutableElement)currentMember; 362 if (method.getSimpleName().toString().compareTo("writeExternal") == 0 363 && utils.getSerialDataTrees(method).isEmpty()) { 364 if (configuration.serialwarn) { 365 TypeElement encl = (TypeElement) method.getEnclosingElement(); 366 configuration.getDocletSpecificMsg().warning(currentMember, 367 "doclet.MissingSerialDataTag", encl.getQualifiedName().toString(), 368 method.getSimpleName().toString()); 369 } 370 } 371 } 372 373 /** 374 * Build the field header. 375 * 376 * @param node the XML element that specifies which components to document 377 * @param classContentTree content tree to which the documentation will be added 378 */ 379 public void buildFieldHeader(XMLNode node, Content classContentTree) { 380 if (!utils.serializableFields(currentTypeElement).isEmpty()) { 381 buildFieldSerializationOverview(currentTypeElement, classContentTree); 382 } 383 } 384 385 /** 386 * Build the serialization overview for the given class. 387 * 388 * @param typeElement the class to print the overview for. 389 * @param classContentTree content tree to which the documentation will be added 390 */ 391 public void buildFieldSerializationOverview(TypeElement typeElement, Content classContentTree) { 392 if (utils.definesSerializableFields(typeElement)) { 393 VariableElement ve = utils.serializableFields(typeElement).first(); 394 // Check to see if there are inline comments, tags or deprecation 395 // information to be printed. 396 if (fieldWriter.shouldPrintOverview(ve)) { 397 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); 398 Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true); 399 fieldWriter.addMemberDeprecatedInfo(ve, fieldsOverviewContentTree); 400 if (!configuration.nocomment) { 401 fieldWriter.addMemberDescription(ve, fieldsOverviewContentTree); 402 fieldWriter.addMemberTags(ve, fieldsOverviewContentTree); 403 } 404 serializableFieldsTree.addContent(fieldsOverviewContentTree); 405 classContentTree.addContent(fieldWriter.getSerializableFields( 406 configuration.getText("doclet.Serialized_Form_class"), 407 serializableFieldsTree)); 408 } 409 } 410 } 411 412 /** 413 * Build the summaries for the fields that belong to the given class. 414 * 415 * @param node the XML element that specifies which components to document 416 * @param classContentTree content tree to which the documentation will be added 417 */ 418 public void buildSerializableFields(XMLNode node, Content classContentTree) { 419 SortedSet<VariableElement> members = utils.serializableFields(currentTypeElement); 420 if (!members.isEmpty()) { 421 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); 422 for (VariableElement ve : members) { 423 currentMember = ve; 424 if (!utils.definesSerializableFields(currentTypeElement)) { 425 Content fieldsContentTree = fieldWriter.getFieldsContentHeader( 426 currentMember == members.last()); 427 buildChildren(node, fieldsContentTree); 428 serializableFieldsTree.addContent(fieldsContentTree); 429 } else { 430 buildSerialFieldTagsInfo(serializableFieldsTree); 431 } 432 } 433 classContentTree.addContent(fieldWriter.getSerializableFields( 434 configuration.getText("doclet.Serialized_Form_fields"), 435 serializableFieldsTree)); 436 } 437 } 438 439 /** 440 * Build the field sub header. 441 * 442 * @param node the XML element that specifies which components to document 443 * @param fieldsContentTree content tree to which the documentation will be added 444 */ 445 public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) { 446 if (!utils.definesSerializableFields(currentTypeElement)) { 447 VariableElement field = (VariableElement) currentMember; 448 fieldWriter.addMemberHeader(utils.asTypeElement(field.asType()), 449 utils.getTypeName(field.asType(), false), utils.getDimension(field.asType()), 450 utils.getSimpleName(field), 451 fieldsContentTree); 452 } 453 } 454 455 /** 456 * Build the field deprecation information. 457 * 458 * @param node the XML element that specifies which components to document 459 * @param fieldsContentTree content tree to which the documentation will be added 460 */ 461 public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) { 462 if (!utils.definesSerializableFields(currentTypeElement)) { 463 fieldWriter.addMemberDeprecatedInfo((VariableElement)currentMember, 464 fieldsContentTree); 465 } 466 } 467 468 /** 469 * Build the serial field tags information. 470 * 471 * @param serializableFieldsTree content tree to which the documentation will be added 472 */ 473 public void buildSerialFieldTagsInfo(Content serializableFieldsTree) { 474 if(configuration.nocomment){ 475 return; 476 } 477 VariableElement field = (VariableElement)currentMember; 478 // Process Serializable Fields specified as array of 479 // ObjectStreamFields. Print a member for each serialField tag. 480 // (There should be one serialField tag per ObjectStreamField 481 // element.) 482 SortedSet<SerialFieldTree> tags = new TreeSet<>(utils.makeSerialFieldTreeComparator()); 483 // sort the elements 484 for (DocTree dt : utils.getSerialFieldTrees(field)) { 485 SerialFieldTree st = (SerialFieldTree) dt; 486 tags.add(st); 487 } 488 489 CommentHelper ch = utils.getCommentHelper(field); 490 for (SerialFieldTree tag : tags) { 491 if (tag.getName() == null || tag.getType() == null) // ignore malformed @serialField tags 492 continue; 493 Content fieldsContentTree = fieldWriter.getFieldsContentHeader(tag.equals(tags.last())); 494 TypeElement te = ch.getReferencedClass(configuration, tag); 495 String fieldType = ch.getReferencedMemberName(tag); 496 if (te != null && utils.isPrimitive(te.asType())) { 497 fieldType = utils.getTypeName(te.asType(), false); 498 te = null; 499 } 500 String refSignature = ch.getReferencedSignature(tag); 501 // TODO: Print the signature directly, if it is an array, the 502 // current DocTree APIs makes it very hard to distinguish 503 // an as these are returned back as "Array" a DeclaredType. 504 if (refSignature.endsWith("[]")) { 505 te = null; 506 fieldType = refSignature; 507 } 508 fieldWriter.addMemberHeader(te, fieldType, "", 509 tag.getName().getName().toString(), fieldsContentTree); 510 fieldWriter.addMemberDescription(field, tag, fieldsContentTree); 511 serializableFieldsTree.addContent(fieldsContentTree); 512 } 513 } 514 515 /** 516 * Build the field information. 517 * 518 * @param node the XML element that specifies which components to document 519 * @param fieldsContentTree content tree to which the documentation will be added 520 */ 521 public void buildFieldInfo(XMLNode node, Content fieldsContentTree) { 522 if(configuration.nocomment){ 523 return; 524 } 525 VariableElement field = (VariableElement)currentMember; 526 TypeElement te = utils.getEnclosingTypeElement(currentMember); 527 // Process default Serializable field. 528 if ((utils.getSerialTrees(field).isEmpty()) /*&& ! field.isSynthetic()*/ 529 && configuration.serialwarn) { 530 configuration.message.warning(field, 531 "doclet.MissingSerialTag", utils.getFullyQualifiedName(te), 532 utils.getSimpleName(field)); 533 } 534 fieldWriter.addMemberDescription(field, fieldsContentTree); 535 fieldWriter.addMemberTags(field, fieldsContentTree); 536 } 537 538 /** 539 * Return true if the given Element should be included 540 * in the serialized form. 541 * 542 * @param element the Element object to check for serializability. 543 */ 544 public static boolean serialInclude(Utils utils, Element element) { 545 if (element == null) { 546 return false; 547 } 548 return utils.isClass(element) 549 ? serialClassInclude(utils, (TypeElement)element) 550 : serialDocInclude(utils, element); 551 } 552 553 /** 554 * Return true if the given TypeElement should be included 555 * in the serialized form. 556 * 557 * @param te the TypeElement object to check for serializability. 558 */ 559 private static boolean serialClassInclude(Utils utils, TypeElement te) { 560 if (utils.isEnum(te)) { 561 return false; 562 } 563 if (utils.isSerializable(te)) { 564 if (!utils.getSerialTrees(te).isEmpty()) { 565 return serialDocInclude(utils, te); 566 } else if (utils.isPublic(te) || utils.isProtected(te)) { 567 return true; 568 } else { 569 return false; 570 } 571 } 572 return false; 573 } 574 575 /** 576 * Return true if the given Element should be included 577 * in the serialized form. 578 * 579 * @param element the Element to check for serializability. 580 */ 581 private static boolean serialDocInclude(Utils utils, Element element) { 582 if (utils.isEnum(element)) { 583 return false; 584 } 585 List<? extends DocTree> serial = utils.getSerialTrees(element); 586 if (!serial.isEmpty()) { 587 CommentHelper ch = utils.getCommentHelper(element); 588 String serialtext = Utils.toLowerCase(ch.getText(serial.get(0))); 589 if (serialtext.contains("exclude")) { 590 return false; 591 } else if (serialtext.contains("include")) { 592 return true; 593 } 594 } 595 return true; 596 } 597 598 /** 599 * Return true if any of the given typeElements have a @serialinclude tag. 600 * 601 * @param classes the typeElements to check. 602 * @return true if any of the given typeElements have a @serialinclude tag. 603 */ 604 private boolean serialClassFoundToDocument(SortedSet<TypeElement> classes) { 605 for (TypeElement aClass : classes) { 606 if (serialClassInclude(utils, aClass)) { 607 return true; 608 } 609 } 610 return false; 611 } 612 } |