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

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 1
9a66ca7c79fa
child 184
905e151a185a
permissions
-rw-r--r--

Initial load

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

mercurial