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

Mon, 09 Mar 2009 23:53:41 -0700

author
tbell
date
Mon, 09 Mar 2009 23:53:41 -0700
changeset 240
8c55d5b0ed71
parent 229
03bcd66bd8e7
parent 233
5240b1120530
child 554
9d9f26857129
permissions
-rw-r--r--

Merge

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

mercurial