src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java

Wed, 18 Feb 2009 13:47:27 -0800

author
bpatel
date
Wed, 18 Feb 2009 13:47:27 -0800
changeset 222
d424ed561993
parent 198
b4b1f7732289
child 229
03bcd66bd8e7
child 233
5240b1120530
permissions
-rw-r--r--

6802694: Javadoc doclet does not display deprecated information with -nocomment option for serialized form
Reviewed-by: jjg

duke@1 1 /*
duke@1 2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
duke@1 7 * published by the Free Software Foundation. Sun designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
duke@1 9 * by Sun in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
duke@1 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@1 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@1 23 * have any questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.doclets.internal.toolkit.builders;
duke@1 27
duke@1 28 import com.sun.tools.doclets.internal.toolkit.util.*;
duke@1 29 import com.sun.tools.doclets.internal.toolkit.*;
duke@1 30 import com.sun.javadoc.*;
duke@1 31 import java.io.*;
duke@1 32 import java.lang.reflect.*;
duke@1 33 import java.util.*;
duke@1 34
duke@1 35 /**
duke@1 36 * Builds the serialized form.
duke@1 37 *
duke@1 38 * This code is not part of an API.
duke@1 39 * It is implementation that is subject to change.
duke@1 40 * Do not use it as an API
duke@1 41 *
duke@1 42 * @author Jamie Ho
duke@1 43 * @since 1.5
duke@1 44 */
duke@1 45 public class SerializedFormBuilder extends AbstractBuilder {
duke@1 46
duke@1 47 /**
duke@1 48 * The root element of the serialized form XML is {@value}.
duke@1 49 */
duke@1 50 public static final String NAME = "SerializedForm";
duke@1 51
duke@1 52 /**
duke@1 53 * The writer for this builder.
duke@1 54 */
duke@1 55 private SerializedFormWriter writer;
duke@1 56
duke@1 57 /**
duke@1 58 * The writer for serializable fields.
duke@1 59 */
duke@1 60 private SerializedFormWriter.SerialFieldWriter fieldWriter;
duke@1 61
duke@1 62 /**
duke@1 63 * The writer for serializable method documentation.
duke@1 64 */
duke@1 65 private SerializedFormWriter.SerialMethodWriter methodWriter;
duke@1 66
duke@1 67 /**
duke@1 68 * The header for the serial version UID. Save the string
duke@1 69 * here instead of the properties file because we do not want
duke@1 70 * this string to be localized.
duke@1 71 */
duke@1 72 private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:";
duke@1 73
duke@1 74 /**
duke@1 75 * The current package being documented.
duke@1 76 */
duke@1 77 private PackageDoc currentPackage;
duke@1 78
duke@1 79 /**
duke@1 80 * The current class being documented.
duke@1 81 */
duke@1 82 private ClassDoc currentClass;
duke@1 83
duke@1 84 /**
duke@1 85 * The current member being documented.
duke@1 86 */
duke@1 87 protected MemberDoc currentMember;
duke@1 88
duke@1 89 private SerializedFormBuilder(Configuration configuration) {
duke@1 90 super(configuration);
duke@1 91 }
duke@1 92
duke@1 93 /**
duke@1 94 * Construct a new SerializedFormBuilder.
duke@1 95 * @param configuration the current configuration of the doclet.
duke@1 96 */
duke@1 97 public static SerializedFormBuilder getInstance(Configuration configuration) {
duke@1 98 SerializedFormBuilder builder = new SerializedFormBuilder(configuration);
duke@1 99 return builder;
duke@1 100 }
duke@1 101
duke@1 102 /**
duke@1 103 * Build the serialized form.
duke@1 104 */
duke@1 105 public void build() throws IOException {
duke@1 106 if (! serialClassFoundToDocument(configuration.root.classes())) {
duke@1 107 //Nothing to document.
duke@1 108 return;
duke@1 109 }
duke@1 110 try {
duke@1 111 writer = configuration.getWriterFactory().getSerializedFormWriter();
duke@1 112 if (writer == null) {
duke@1 113 //Doclet does not support this output.
duke@1 114 return;
duke@1 115 }
duke@1 116 } catch (Exception e) {
duke@1 117 throw new DocletAbortException();
duke@1 118 }
duke@1 119 build(LayoutParser.getInstance(configuration).parseXML(NAME));
duke@1 120 writer.close();
duke@1 121 }
duke@1 122
duke@1 123 /**
duke@1 124 * {@inheritDoc}
duke@1 125 */
duke@1 126 public String getName() {
duke@1 127 return NAME;
duke@1 128 }
duke@1 129
duke@1 130 /**
duke@1 131 * Build the serialized form.
duke@1 132 */
mcimadamore@184 133 public void buildSerializedForm(List<?> elements) throws Exception {
duke@1 134 build(elements);
duke@1 135 writer.close();
duke@1 136 }
duke@1 137
duke@1 138 /**
duke@1 139 * {@inheritDoc}
duke@1 140 */
mcimadamore@184 141 public void invokeMethod(String methodName, Class<?>[] paramClasses,
duke@1 142 Object[] params)
duke@1 143 throws Exception {
duke@1 144 if (DEBUG) {
duke@1 145 configuration.root.printError("DEBUG: " + this.getClass().getName()
duke@1 146 + "." + methodName);
duke@1 147 }
duke@1 148 Method method = this.getClass().getMethod(methodName, paramClasses);
duke@1 149 method.invoke(this, params);
duke@1 150 }
duke@1 151
duke@1 152 /**
duke@1 153 * Build the header.
duke@1 154 */
duke@1 155 public void buildHeader() {
duke@1 156 writer.writeHeader(configuration.getText("doclet.Serialized_Form"));
duke@1 157 }
duke@1 158
duke@1 159 /**
duke@1 160 * Build the contents.
duke@1 161 */
mcimadamore@184 162 public void buildSerializedFormSummaries(List<?> elements) {
duke@1 163 PackageDoc[] packages = configuration.packages;
duke@1 164 for (int i = 0; i < packages.length; i++) {
duke@1 165 currentPackage = packages[i];
duke@1 166 build(elements);
duke@1 167 }
duke@1 168 }
duke@1 169
duke@1 170 /**
duke@1 171 * Build the package serialized for for the current package being processed.
duke@1 172 */
mcimadamore@184 173 public void buildPackageSerializedForm(List<?> elements) {
duke@1 174 String foo = currentPackage.name();
duke@1 175 ClassDoc[] classes = currentPackage.allClasses(false);
duke@1 176 if (classes == null || classes.length == 0) {
duke@1 177 return;
duke@1 178 }
duke@1 179 if (!serialInclude(currentPackage)) {
duke@1 180 return;
duke@1 181 }
duke@1 182 if (!serialClassFoundToDocument(classes)) {
duke@1 183 return;
duke@1 184 }
duke@1 185 build(elements);
duke@1 186 }
duke@1 187
duke@1 188 public void buildPackageHeader() {
duke@1 189 writer.writePackageHeader(Util.getPackageName(currentPackage));
duke@1 190 }
duke@1 191
mcimadamore@184 192 public void buildClassSerializedForm(List<?> elements) {
duke@1 193 ClassDoc[] classes = currentPackage.allClasses(false);
duke@1 194 Arrays.sort(classes);
duke@1 195 for (int j = 0; j < classes.length; j++) {
duke@1 196 currentClass = classes[j];
duke@1 197 fieldWriter = writer.getSerialFieldWriter(currentClass);
duke@1 198 methodWriter = writer.getSerialMethodWriter(currentClass);
duke@1 199 if(currentClass.isClass() && currentClass.isSerializable()) {
duke@1 200 if(!serialClassInclude(currentClass)) {
duke@1 201 continue;
duke@1 202 }
duke@1 203 build(elements);
duke@1 204 }
duke@1 205 }
duke@1 206 }
duke@1 207
duke@1 208 public void buildClassHeader() {
duke@1 209 writer.writeClassHeader(currentClass);
duke@1 210 }
duke@1 211
duke@1 212 /**
duke@1 213 * Build the serial UID information for the given class.
duke@1 214 */
duke@1 215 public void buildSerialUIDInfo() {
duke@1 216 FieldDoc[] fields = currentClass.fields(false);
duke@1 217 for (int i = 0; i < fields.length; i++) {
duke@1 218 if (fields[i].name().equals("serialVersionUID") &&
duke@1 219 fields[i].constantValueExpression() != null) {
duke@1 220 writer.writeSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
duke@1 221 fields[i].constantValueExpression());
duke@1 222 return;
duke@1 223 }
duke@1 224 }
duke@1 225 }
duke@1 226
duke@1 227 /**
duke@1 228 * Build the footer.
duke@1 229 */
duke@1 230 public void buildFooter() {
duke@1 231 writer.writeFooter();
duke@1 232 }
duke@1 233
duke@1 234 /**
duke@1 235 * Return true if the given Doc should be included
duke@1 236 * in the serialized form.
duke@1 237 *
duke@1 238 * @param doc the Doc object to check for serializability.
duke@1 239 */
duke@1 240 public static boolean serialInclude(Doc doc) {
duke@1 241 if (doc == null) {
duke@1 242 return false;
duke@1 243 }
duke@1 244 return doc.isClass() ?
duke@1 245 serialClassInclude((ClassDoc)doc) :
duke@1 246 serialDocInclude(doc);
duke@1 247 }
duke@1 248
duke@1 249 /**
duke@1 250 * Return true if the given ClassDoc should be included
duke@1 251 * in the serialized form.
duke@1 252 *
duke@1 253 * @param cd the ClassDoc object to check for serializability.
duke@1 254 */
duke@1 255 private static boolean serialClassInclude(ClassDoc cd) {
duke@1 256 if (cd.isEnum()) {
duke@1 257 return false;
duke@1 258 }
duke@1 259 try {
duke@1 260 cd.superclassType();
duke@1 261 } catch (NullPointerException e) {
duke@1 262 //Workaround for null pointer bug in ClassDoc.superclassType().
duke@1 263 return false;
duke@1 264 }
duke@1 265 if (cd.isSerializable()) {
duke@1 266 if (cd.tags("serial").length > 0) {
duke@1 267 return serialDocInclude(cd);
duke@1 268 } else if (cd.isPublic() || cd.isProtected()) {
duke@1 269 return true;
duke@1 270 } else {
duke@1 271 return false;
duke@1 272 }
duke@1 273 }
duke@1 274 return false;
duke@1 275 }
duke@1 276
duke@1 277 /**
duke@1 278 * Return true if the given Doc should be included
duke@1 279 * in the serialized form.
duke@1 280 *
duke@1 281 * @param doc the Doc object to check for serializability.
duke@1 282 */
duke@1 283 private static boolean serialDocInclude(Doc doc) {
duke@1 284 if (doc.isEnum()) {
duke@1 285 return false;
duke@1 286 }
duke@1 287 Tag[] serial = doc.tags("serial");
duke@1 288 if (serial.length > 0) {
duke@1 289 String serialtext = serial[0].text().toLowerCase();
duke@1 290 if (serialtext.indexOf("exclude") >= 0) {
duke@1 291 return false;
duke@1 292 } else if (serialtext.indexOf("include") >= 0) {
duke@1 293 return true;
duke@1 294 }
duke@1 295 }
duke@1 296 return true;
duke@1 297 }
duke@1 298
duke@1 299 /**
duke@1 300 * Return true if any of the given classes have a @serialinclude tag.
duke@1 301 *
duke@1 302 * @param classes the classes to check.
duke@1 303 * @return true if any of the given classes have a @serialinclude tag.
duke@1 304 */
duke@1 305 private boolean serialClassFoundToDocument(ClassDoc[] classes) {
duke@1 306 for (int i = 0; i < classes.length; i++) {
duke@1 307 if (serialClassInclude(classes[i])) {
duke@1 308 return true;
duke@1 309 }
duke@1 310 }
duke@1 311 return false;
duke@1 312 }
duke@1 313
duke@1 314 /**
duke@1 315 * Build the method header.
duke@1 316 */
duke@1 317 public void buildMethodHeader() {
duke@1 318 if (currentClass.serializationMethods().length > 0) {
duke@1 319 methodWriter.writeHeader(
duke@1 320 configuration.getText("doclet.Serialized_Form_methods"));
duke@1 321 if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
duke@1 322 if (currentClass.serializationMethods().length == 0) {
duke@1 323 methodWriter.writeNoCustomizationMsg(
duke@1 324 configuration.getText(
duke@1 325 "doclet.Serializable_no_customization"));
duke@1 326 }
duke@1 327 }
duke@1 328 }
duke@1 329 }
duke@1 330
duke@1 331 /**
duke@1 332 * Build the method sub header.
duke@1 333 */
duke@1 334 public void buildMethodSubHeader() {
duke@1 335 methodWriter.writeMemberHeader((MethodDoc) currentMember);
duke@1 336 }
duke@1 337
duke@1 338 /**
duke@1 339 * Build the deprecated method description.
duke@1 340 */
duke@1 341 public void buildDeprecatedMethodInfo() {
duke@1 342 methodWriter.writeDeprecatedMemberInfo((MethodDoc) currentMember);
duke@1 343 }
duke@1 344
duke@1 345 /**
duke@1 346 * Build method tags.
duke@1 347 */
duke@1 348 public void buildMethodDescription() {
duke@1 349 methodWriter.writeMemberDescription((MethodDoc) currentMember);
duke@1 350 }
duke@1 351
duke@1 352 /**
duke@1 353 * Build the method tags.
duke@1 354 */
duke@1 355 public void buildMethodTags() {
duke@1 356 methodWriter.writeMemberTags((MethodDoc) currentMember);
duke@1 357 MethodDoc method = (MethodDoc)currentMember;
duke@1 358 if (method.name().compareTo("writeExternal") == 0
duke@1 359 && method.tags("serialData").length == 0) {
duke@1 360 if (configuration.serialwarn) {
duke@1 361 configuration.getDocletSpecificMsg().warning(
duke@1 362 currentMember.position(), "doclet.MissingSerialDataTag",
duke@1 363 method.containingClass().qualifiedName(), method.name());
duke@1 364 }
duke@1 365 }
duke@1 366 }
duke@1 367
duke@1 368 /**
duke@1 369 * build the information for the method.
duke@1 370 */
mcimadamore@184 371 public void buildMethodInfo(List<?> elements) {
duke@1 372 if(configuration.nocomment){
duke@1 373 return;
duke@1 374 }
duke@1 375 build(elements);
duke@1 376 }
duke@1 377
duke@1 378 /**
duke@1 379 * Build the method footer.
duke@1 380 */
duke@1 381 public void buildMethodFooter() {
duke@1 382 methodWriter.writeMemberFooter((MethodDoc) currentMember);
duke@1 383 }
duke@1 384
duke@1 385 /**
duke@1 386 * Build the field header.
duke@1 387 */
duke@1 388 public void buildFieldHeader() {
duke@1 389 if (currentClass.serializableFields().length > 0) {
duke@1 390 buildFieldSerializationOverview(currentClass);
duke@1 391 fieldWriter.writeHeader(configuration.getText(
duke@1 392 "doclet.Serialized_Form_fields"));
duke@1 393 }
duke@1 394 }
duke@1 395
duke@1 396 /**
duke@1 397 * If possible, build the serialization overview for the given
duke@1 398 * class.
duke@1 399 *
duke@1 400 * @param classDoc the class to print the overview for.
duke@1 401 */
duke@1 402 public void buildFieldSerializationOverview(ClassDoc classDoc) {
duke@1 403 if (classDoc.definesSerializableFields()) {
duke@1 404 FieldDoc serialPersistentField =
jjg@198 405 Util.asList(classDoc.serializableFields()).get(0);
bpatel@222 406 // Check to see if there are inline comments, tags or deprecation
bpatel@222 407 // information to be printed.
bpatel@222 408 if (fieldWriter.shouldPrintMemberDetails(serialPersistentField)) {
duke@1 409 fieldWriter.writeHeader(
duke@1 410 configuration.getText("doclet.Serialized_Form_class"));
bpatel@222 411 fieldWriter.writeMemberDeprecatedInfo(serialPersistentField);
duke@1 412 if (!configuration.nocomment) {
duke@1 413 fieldWriter.writeMemberDescription(serialPersistentField);
duke@1 414 fieldWriter.writeMemberTags(serialPersistentField);
duke@1 415 }
bpatel@222 416 fieldWriter.writeMemberFooter(serialPersistentField);
duke@1 417 }
duke@1 418 }
duke@1 419 }
duke@1 420
duke@1 421 /**
duke@1 422 * Build the field sub header.
duke@1 423 */
duke@1 424 public void buildFieldSubHeader() {
duke@1 425 if (! currentClass.definesSerializableFields() ){
duke@1 426 FieldDoc field = (FieldDoc) currentMember;
duke@1 427 fieldWriter.writeMemberHeader(field.type().asClassDoc(),
duke@1 428 field.type().typeName(), field.type().dimension(), field.name());
duke@1 429 }
duke@1 430 }
duke@1 431
duke@1 432 /**
bpatel@222 433 * Build the field deprecation information.
bpatel@222 434 */
bpatel@222 435 public void buildFieldDeprecationInfo() {
bpatel@222 436 if (!currentClass.definesSerializableFields()) {
bpatel@222 437 FieldDoc field = (FieldDoc)currentMember;
bpatel@222 438 fieldWriter.writeMemberDeprecatedInfo(field);
bpatel@222 439 }
bpatel@222 440 }
bpatel@222 441
bpatel@222 442 /**
duke@1 443 * Build the field information.
duke@1 444 */
duke@1 445 public void buildFieldInfo() {
duke@1 446 if(configuration.nocomment){
duke@1 447 return;
duke@1 448 }
duke@1 449 FieldDoc field = (FieldDoc)currentMember;
duke@1 450 ClassDoc cd = field.containingClass();
duke@1 451 if (cd.definesSerializableFields()) {
duke@1 452 // Process Serializable Fields specified as array of
duke@1 453 // ObjectStreamFields. Print a member for each serialField tag.
duke@1 454 // (There should be one serialField tag per ObjectStreamField
duke@1 455 // element.)
duke@1 456 SerialFieldTag[] tags = field.serialFieldTags();
duke@1 457 Arrays.sort(tags);
duke@1 458 for (int i = 0; i < tags.length; i++) {
duke@1 459 fieldWriter.writeMemberHeader(tags[i].fieldTypeDoc(),
duke@1 460 tags[i].fieldType(), "", tags[i].fieldName());
duke@1 461 fieldWriter.writeMemberDescription(tags[i]);
duke@1 462
duke@1 463 }
duke@1 464 } else {
duke@1 465
duke@1 466 // Process default Serializable field.
duke@1 467 if ((field.tags("serial").length == 0) && ! field.isSynthetic()
duke@1 468 && configuration.serialwarn) {
duke@1 469 configuration.message.warning(field.position(),
duke@1 470 "doclet.MissingSerialTag", cd.qualifiedName(),
duke@1 471 field.name());
duke@1 472 }
duke@1 473 fieldWriter.writeMemberDescription(field);
duke@1 474 fieldWriter.writeMemberTags(field);
duke@1 475 }
duke@1 476 }
duke@1 477
duke@1 478 /**
duke@1 479 * Build the field footer.
duke@1 480 */
duke@1 481 public void buildFieldFooter() {
duke@1 482 if (! currentClass.definesSerializableFields()) {
duke@1 483 fieldWriter.writeMemberFooter((FieldDoc) currentMember);
duke@1 484 }
duke@1 485 }
duke@1 486
duke@1 487 /**
duke@1 488 * Build the summaries for the methods that belong to the given
duke@1 489 * class.
duke@1 490 */
mcimadamore@184 491 public void buildSerializableMethods(List<?> elements) {
duke@1 492 MemberDoc[] members = currentClass.serializationMethods();
duke@1 493 if (members.length > 0) {
duke@1 494 for (int i = 0; i < members.length; i++) {
duke@1 495 currentMember = members[i];
duke@1 496 build(elements);
duke@1 497 }
duke@1 498 }
duke@1 499 }
duke@1 500
duke@1 501 /**
duke@1 502 * Build the summaries for the fields that belong to the given
duke@1 503 * class.
duke@1 504 */
mcimadamore@184 505 public void buildSerializableFields(List<?> elements) {
duke@1 506 MemberDoc[] members = currentClass.serializableFields();
duke@1 507 if (members.length > 0) {
duke@1 508 for (int i = 0; i < members.length; i++) {
duke@1 509 currentMember = members[i];
duke@1 510 build(elements);
duke@1 511 }
duke@1 512 }
duke@1 513 }
duke@1 514 }

mercurial