1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,504 @@ 1.4 +/* 1.5 + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.doclets.internal.toolkit.builders; 1.30 + 1.31 +import com.sun.tools.doclets.internal.toolkit.util.*; 1.32 +import com.sun.tools.doclets.internal.toolkit.*; 1.33 +import com.sun.javadoc.*; 1.34 +import java.io.*; 1.35 +import java.lang.reflect.*; 1.36 +import java.util.*; 1.37 + 1.38 +/** 1.39 + * Builds the serialized form. 1.40 + * 1.41 + * This code is not part of an API. 1.42 + * It is implementation that is subject to change. 1.43 + * Do not use it as an API 1.44 + * 1.45 + * @author Jamie Ho 1.46 + * @since 1.5 1.47 + */ 1.48 +public class SerializedFormBuilder extends AbstractBuilder { 1.49 + 1.50 + /** 1.51 + * The root element of the serialized form XML is {@value}. 1.52 + */ 1.53 + public static final String NAME = "SerializedForm"; 1.54 + 1.55 + /** 1.56 + * The writer for this builder. 1.57 + */ 1.58 + private SerializedFormWriter writer; 1.59 + 1.60 + /** 1.61 + * The writer for serializable fields. 1.62 + */ 1.63 + private SerializedFormWriter.SerialFieldWriter fieldWriter; 1.64 + 1.65 + /** 1.66 + * The writer for serializable method documentation. 1.67 + */ 1.68 + private SerializedFormWriter.SerialMethodWriter methodWriter; 1.69 + 1.70 + /** 1.71 + * The header for the serial version UID. Save the string 1.72 + * here instead of the properties file because we do not want 1.73 + * this string to be localized. 1.74 + */ 1.75 + private static final String SERIAL_VERSION_UID_HEADER = "serialVersionUID:"; 1.76 + 1.77 + /** 1.78 + * The current package being documented. 1.79 + */ 1.80 + private PackageDoc currentPackage; 1.81 + 1.82 + /** 1.83 + * The current class being documented. 1.84 + */ 1.85 + private ClassDoc currentClass; 1.86 + 1.87 + /** 1.88 + * The current member being documented. 1.89 + */ 1.90 + protected MemberDoc currentMember; 1.91 + 1.92 + private SerializedFormBuilder(Configuration configuration) { 1.93 + super(configuration); 1.94 + } 1.95 + 1.96 + /** 1.97 + * Construct a new SerializedFormBuilder. 1.98 + * @param configuration the current configuration of the doclet. 1.99 + */ 1.100 + public static SerializedFormBuilder getInstance(Configuration configuration) { 1.101 + SerializedFormBuilder builder = new SerializedFormBuilder(configuration); 1.102 + return builder; 1.103 + } 1.104 + 1.105 + /** 1.106 + * Build the serialized form. 1.107 + */ 1.108 + public void build() throws IOException { 1.109 + if (! serialClassFoundToDocument(configuration.root.classes())) { 1.110 + //Nothing to document. 1.111 + return; 1.112 + } 1.113 + try { 1.114 + writer = configuration.getWriterFactory().getSerializedFormWriter(); 1.115 + if (writer == null) { 1.116 + //Doclet does not support this output. 1.117 + return; 1.118 + } 1.119 + } catch (Exception e) { 1.120 + throw new DocletAbortException(); 1.121 + } 1.122 + build(LayoutParser.getInstance(configuration).parseXML(NAME)); 1.123 + writer.close(); 1.124 + } 1.125 + 1.126 + /** 1.127 + * {@inheritDoc} 1.128 + */ 1.129 + public String getName() { 1.130 + return NAME; 1.131 + } 1.132 + 1.133 + /** 1.134 + * Build the serialized form. 1.135 + */ 1.136 + public void buildSerializedForm(List elements) throws Exception { 1.137 + build(elements); 1.138 + writer.close(); 1.139 + } 1.140 + 1.141 + /** 1.142 + * {@inheritDoc} 1.143 + */ 1.144 + public void invokeMethod(String methodName, Class[] paramClasses, 1.145 + Object[] params) 1.146 + throws Exception { 1.147 + if (DEBUG) { 1.148 + configuration.root.printError("DEBUG: " + this.getClass().getName() 1.149 + + "." + methodName); 1.150 + } 1.151 + Method method = this.getClass().getMethod(methodName, paramClasses); 1.152 + method.invoke(this, params); 1.153 + } 1.154 + 1.155 + /** 1.156 + * Build the header. 1.157 + */ 1.158 + public void buildHeader() { 1.159 + writer.writeHeader(configuration.getText("doclet.Serialized_Form")); 1.160 + } 1.161 + 1.162 + /** 1.163 + * Build the contents. 1.164 + */ 1.165 + public void buildSerializedFormSummaries(List elements) { 1.166 + PackageDoc[] packages = configuration.packages; 1.167 + for (int i = 0; i < packages.length; i++) { 1.168 + currentPackage = packages[i]; 1.169 + build(elements); 1.170 + } 1.171 + } 1.172 + 1.173 + /** 1.174 + * Build the package serialized for for the current package being processed. 1.175 + */ 1.176 + public void buildPackageSerializedForm(List elements) { 1.177 + String foo = currentPackage.name(); 1.178 + ClassDoc[] classes = currentPackage.allClasses(false); 1.179 + if (classes == null || classes.length == 0) { 1.180 + return; 1.181 + } 1.182 + if (!serialInclude(currentPackage)) { 1.183 + return; 1.184 + } 1.185 + if (!serialClassFoundToDocument(classes)) { 1.186 + return; 1.187 + } 1.188 + build(elements); 1.189 + } 1.190 + 1.191 + public void buildPackageHeader() { 1.192 + writer.writePackageHeader(Util.getPackageName(currentPackage)); 1.193 + } 1.194 + 1.195 + public void buildClassSerializedForm(List elements) { 1.196 + ClassDoc[] classes = currentPackage.allClasses(false); 1.197 + Arrays.sort(classes); 1.198 + for (int j = 0; j < classes.length; j++) { 1.199 + currentClass = classes[j]; 1.200 + fieldWriter = writer.getSerialFieldWriter(currentClass); 1.201 + methodWriter = writer.getSerialMethodWriter(currentClass); 1.202 + if(currentClass.isClass() && currentClass.isSerializable()) { 1.203 + if(!serialClassInclude(currentClass)) { 1.204 + continue; 1.205 + } 1.206 + build(elements); 1.207 + } 1.208 + } 1.209 + } 1.210 + 1.211 + public void buildClassHeader() { 1.212 + writer.writeClassHeader(currentClass); 1.213 + } 1.214 + 1.215 + /** 1.216 + * Build the serial UID information for the given class. 1.217 + */ 1.218 + public void buildSerialUIDInfo() { 1.219 + FieldDoc[] fields = currentClass.fields(false); 1.220 + for (int i = 0; i < fields.length; i++) { 1.221 + if (fields[i].name().equals("serialVersionUID") && 1.222 + fields[i].constantValueExpression() != null) { 1.223 + writer.writeSerialUIDInfo(SERIAL_VERSION_UID_HEADER, 1.224 + fields[i].constantValueExpression()); 1.225 + return; 1.226 + } 1.227 + } 1.228 + } 1.229 + 1.230 + /** 1.231 + * Build the footer. 1.232 + */ 1.233 + public void buildFooter() { 1.234 + writer.writeFooter(); 1.235 + } 1.236 + 1.237 + /** 1.238 + * Return true if the given Doc should be included 1.239 + * in the serialized form. 1.240 + * 1.241 + * @param doc the Doc object to check for serializability. 1.242 + */ 1.243 + public static boolean serialInclude(Doc doc) { 1.244 + if (doc == null) { 1.245 + return false; 1.246 + } 1.247 + return doc.isClass() ? 1.248 + serialClassInclude((ClassDoc)doc) : 1.249 + serialDocInclude(doc); 1.250 + } 1.251 + 1.252 + /** 1.253 + * Return true if the given ClassDoc should be included 1.254 + * in the serialized form. 1.255 + * 1.256 + * @param cd the ClassDoc object to check for serializability. 1.257 + */ 1.258 + private static boolean serialClassInclude(ClassDoc cd) { 1.259 + if (cd.isEnum()) { 1.260 + return false; 1.261 + } 1.262 + try { 1.263 + cd.superclassType(); 1.264 + } catch (NullPointerException e) { 1.265 + //Workaround for null pointer bug in ClassDoc.superclassType(). 1.266 + return false; 1.267 + } 1.268 + if (cd.isSerializable()) { 1.269 + if (cd.tags("serial").length > 0) { 1.270 + return serialDocInclude(cd); 1.271 + } else if (cd.isPublic() || cd.isProtected()) { 1.272 + return true; 1.273 + } else { 1.274 + return false; 1.275 + } 1.276 + } 1.277 + return false; 1.278 + } 1.279 + 1.280 + /** 1.281 + * Return true if the given Doc should be included 1.282 + * in the serialized form. 1.283 + * 1.284 + * @param doc the Doc object to check for serializability. 1.285 + */ 1.286 + private static boolean serialDocInclude(Doc doc) { 1.287 + if (doc.isEnum()) { 1.288 + return false; 1.289 + } 1.290 + Tag[] serial = doc.tags("serial"); 1.291 + if (serial.length > 0) { 1.292 + String serialtext = serial[0].text().toLowerCase(); 1.293 + if (serialtext.indexOf("exclude") >= 0) { 1.294 + return false; 1.295 + } else if (serialtext.indexOf("include") >= 0) { 1.296 + return true; 1.297 + } 1.298 + } 1.299 + return true; 1.300 + } 1.301 + 1.302 + /** 1.303 + * Return true if any of the given classes have a @serialinclude tag. 1.304 + * 1.305 + * @param classes the classes to check. 1.306 + * @return true if any of the given classes have a @serialinclude tag. 1.307 + */ 1.308 + private boolean serialClassFoundToDocument(ClassDoc[] classes) { 1.309 + for (int i = 0; i < classes.length; i++) { 1.310 + if (serialClassInclude(classes[i])) { 1.311 + return true; 1.312 + } 1.313 + } 1.314 + return false; 1.315 + } 1.316 + 1.317 + /** 1.318 + * Build the method header. 1.319 + */ 1.320 + public void buildMethodHeader() { 1.321 + if (currentClass.serializationMethods().length > 0) { 1.322 + methodWriter.writeHeader( 1.323 + configuration.getText("doclet.Serialized_Form_methods")); 1.324 + if (currentClass.isSerializable() && !currentClass.isExternalizable()) { 1.325 + if (currentClass.serializationMethods().length == 0) { 1.326 + methodWriter.writeNoCustomizationMsg( 1.327 + configuration.getText( 1.328 + "doclet.Serializable_no_customization")); 1.329 + } 1.330 + } 1.331 + } 1.332 + } 1.333 + 1.334 + /** 1.335 + * Build the method sub header. 1.336 + */ 1.337 + public void buildMethodSubHeader() { 1.338 + methodWriter.writeMemberHeader((MethodDoc) currentMember); 1.339 + } 1.340 + 1.341 + /** 1.342 + * Build the deprecated method description. 1.343 + */ 1.344 + public void buildDeprecatedMethodInfo() { 1.345 + methodWriter.writeDeprecatedMemberInfo((MethodDoc) currentMember); 1.346 + } 1.347 + 1.348 + /** 1.349 + * Build method tags. 1.350 + */ 1.351 + public void buildMethodDescription() { 1.352 + methodWriter.writeMemberDescription((MethodDoc) currentMember); 1.353 + } 1.354 + 1.355 + /** 1.356 + * Build the method tags. 1.357 + */ 1.358 + public void buildMethodTags() { 1.359 + methodWriter.writeMemberTags((MethodDoc) currentMember); 1.360 + MethodDoc method = (MethodDoc)currentMember; 1.361 + if (method.name().compareTo("writeExternal") == 0 1.362 + && method.tags("serialData").length == 0) { 1.363 + if (configuration.serialwarn) { 1.364 + configuration.getDocletSpecificMsg().warning( 1.365 + currentMember.position(), "doclet.MissingSerialDataTag", 1.366 + method.containingClass().qualifiedName(), method.name()); 1.367 + } 1.368 + } 1.369 + } 1.370 + 1.371 + /** 1.372 + * build the information for the method. 1.373 + */ 1.374 + public void buildMethodInfo(List elements) { 1.375 + if(configuration.nocomment){ 1.376 + return; 1.377 + } 1.378 + build(elements); 1.379 + } 1.380 + 1.381 + /** 1.382 + * Build the method footer. 1.383 + */ 1.384 + public void buildMethodFooter() { 1.385 + methodWriter.writeMemberFooter((MethodDoc) currentMember); 1.386 + } 1.387 + 1.388 + /** 1.389 + * Build the field header. 1.390 + */ 1.391 + public void buildFieldHeader() { 1.392 + if (currentClass.serializableFields().length > 0) { 1.393 + buildFieldSerializationOverview(currentClass); 1.394 + fieldWriter.writeHeader(configuration.getText( 1.395 + "doclet.Serialized_Form_fields")); 1.396 + } 1.397 + } 1.398 + 1.399 + /** 1.400 + * If possible, build the serialization overview for the given 1.401 + * class. 1.402 + * 1.403 + * @param classDoc the class to print the overview for. 1.404 + */ 1.405 + public void buildFieldSerializationOverview(ClassDoc classDoc) { 1.406 + if (classDoc.definesSerializableFields()) { 1.407 + FieldDoc serialPersistentField = 1.408 + (FieldDoc)((Util.asList(classDoc.serializableFields()).get(0))); 1.409 + String comment = serialPersistentField.commentText(); 1.410 + if (comment.length() > 0) { 1.411 + fieldWriter.writeHeader( 1.412 + configuration.getText("doclet.Serialized_Form_class")); 1.413 + if (!configuration.nocomment) { 1.414 + fieldWriter.writeMemberDeprecatedInfo(serialPersistentField); 1.415 + fieldWriter.writeMemberDescription(serialPersistentField); 1.416 + fieldWriter.writeMemberTags(serialPersistentField); 1.417 + fieldWriter.writeMemberFooter(serialPersistentField); 1.418 + } 1.419 + } 1.420 + } 1.421 + } 1.422 + 1.423 + /** 1.424 + * Build the field sub header. 1.425 + */ 1.426 + public void buildFieldSubHeader() { 1.427 + if (! currentClass.definesSerializableFields() ){ 1.428 + FieldDoc field = (FieldDoc) currentMember; 1.429 + fieldWriter.writeMemberHeader(field.type().asClassDoc(), 1.430 + field.type().typeName(), field.type().dimension(), field.name()); 1.431 + } 1.432 + } 1.433 + 1.434 + /** 1.435 + * Build the field information. 1.436 + */ 1.437 + public void buildFieldInfo() { 1.438 + if(configuration.nocomment){ 1.439 + return; 1.440 + } 1.441 + FieldDoc field = (FieldDoc)currentMember; 1.442 + ClassDoc cd = field.containingClass(); 1.443 + if (cd.definesSerializableFields()) { 1.444 + // Process Serializable Fields specified as array of 1.445 + // ObjectStreamFields. Print a member for each serialField tag. 1.446 + // (There should be one serialField tag per ObjectStreamField 1.447 + // element.) 1.448 + SerialFieldTag[] tags = field.serialFieldTags(); 1.449 + Arrays.sort(tags); 1.450 + for (int i = 0; i < tags.length; i++) { 1.451 + fieldWriter.writeMemberHeader(tags[i].fieldTypeDoc(), 1.452 + tags[i].fieldType(), "", tags[i].fieldName()); 1.453 + fieldWriter.writeMemberDescription(tags[i]); 1.454 + 1.455 + } 1.456 + } else { 1.457 + 1.458 + // Process default Serializable field. 1.459 + if ((field.tags("serial").length == 0) && ! field.isSynthetic() 1.460 + && configuration.serialwarn) { 1.461 + configuration.message.warning(field.position(), 1.462 + "doclet.MissingSerialTag", cd.qualifiedName(), 1.463 + field.name()); 1.464 + } 1.465 + fieldWriter.writeMemberDeprecatedInfo(field); 1.466 + fieldWriter.writeMemberDescription(field); 1.467 + fieldWriter.writeMemberTags(field); 1.468 + } 1.469 + } 1.470 + 1.471 + /** 1.472 + * Build the field footer. 1.473 + */ 1.474 + public void buildFieldFooter() { 1.475 + if (! currentClass.definesSerializableFields()) { 1.476 + fieldWriter.writeMemberFooter((FieldDoc) currentMember); 1.477 + } 1.478 + } 1.479 + 1.480 + /** 1.481 + * Build the summaries for the methods that belong to the given 1.482 + * class. 1.483 + */ 1.484 + public void buildSerializableMethods(List elements) { 1.485 + MemberDoc[] members = currentClass.serializationMethods(); 1.486 + if (members.length > 0) { 1.487 + for (int i = 0; i < members.length; i++) { 1.488 + currentMember = members[i]; 1.489 + build(elements); 1.490 + } 1.491 + } 1.492 + } 1.493 + 1.494 + /** 1.495 + * Build the summaries for the fields that belong to the given 1.496 + * class. 1.497 + */ 1.498 + public void buildSerializableFields(List elements) { 1.499 + MemberDoc[] members = currentClass.serializableFields(); 1.500 + if (members.length > 0) { 1.501 + for (int i = 0; i < members.length; i++) { 1.502 + currentMember = members[i]; 1.503 + build(elements); 1.504 + } 1.505 + } 1.506 + } 1.507 +}