Wed, 27 Apr 2016 01:34:52 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17
1 /*
2 * Copyright (c) 2003, 2013, 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 */
26 package com.sun.tools.doclets.internal.toolkit.builders;
28 import java.io.*;
29 import java.util.*;
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;
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 {
50 /**
51 * The root element of the serialized form XML is {@value}.
52 */
53 public static final String NAME = "SerializedForm";
55 /**
56 * The writer for this builder.
57 */
58 private SerializedFormWriter writer;
60 /**
61 * The writer for serializable fields.
62 */
63 private SerializedFormWriter.SerialFieldWriter fieldWriter;
65 /**
66 * The writer for serializable method documentation.
67 */
68 private SerializedFormWriter.SerialMethodWriter methodWriter;
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:";
77 /**
78 * The current package being documented.
79 */
80 private PackageDoc currentPackage;
82 /**
83 * The current class being documented.
84 */
85 private ClassDoc currentClass;
87 /**
88 * The current member being documented.
89 */
90 protected MemberDoc currentMember;
92 /**
93 * The content that will be added to the serialized form documentation tree.
94 */
95 private Content contentTree;
98 /**
99 * Construct a new SerializedFormBuilder.
100 * @param context the build context.
101 */
102 private SerializedFormBuilder(Context context) {
103 super(context);
104 }
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 }
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 }
135 /**
136 * {@inheritDoc}
137 */
138 public String getName() {
139 return NAME;
140 }
142 /**
143 * Build the serialized form.
144 *
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 }
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 PackageDoc[] packages = configuration.packages;
166 for (int i = 0; i < packages.length; i++) {
167 currentPackage = packages[i];
168 buildChildren(node, serializedSummariesTree);
169 }
170 serializedTree.addContent(writer.getSerializedContent(
171 serializedSummariesTree));
172 }
174 /**
175 * Build the package serialized form for the current package being processed.
176 *
177 * @param node the XML element that specifies which components to document
178 * @param serializedSummariesTree content tree to which the documentation will be added
179 */
180 public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) {
181 Content packageSerializedTree = writer.getPackageSerializedHeader();
182 String foo = currentPackage.name();
183 ClassDoc[] classes = currentPackage.allClasses(false);
184 if (classes == null || classes.length == 0) {
185 return;
186 }
187 if (!serialInclude(currentPackage)) {
188 return;
189 }
190 if (!serialClassFoundToDocument(classes)) {
191 return;
192 }
193 buildChildren(node, packageSerializedTree);
194 serializedSummariesTree.addContent(packageSerializedTree);
195 }
197 /**
198 * Build the package header.
199 *
200 * @param node the XML element that specifies which components to document
201 * @param packageSerializedTree content tree to which the documentation will be added
202 */
203 public void buildPackageHeader(XMLNode node, Content packageSerializedTree) {
204 packageSerializedTree.addContent(writer.getPackageHeader(
205 Util.getPackageName(currentPackage)));
206 }
208 /**
209 * Build the class serialized form.
210 *
211 * @param node the XML element that specifies which components to document
212 * @param packageSerializedTree content tree to which the documentation will be added
213 */
214 public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) {
215 Content classSerializedTree = writer.getClassSerializedHeader();
216 ClassDoc[] classes = currentPackage.allClasses(false);
217 Arrays.sort(classes);
218 for (int j = 0; j < classes.length; j++) {
219 currentClass = classes[j];
220 fieldWriter = writer.getSerialFieldWriter(currentClass);
221 methodWriter = writer.getSerialMethodWriter(currentClass);
222 if(currentClass.isClass() && currentClass.isSerializable()) {
223 if(!serialClassInclude(currentClass)) {
224 continue;
225 }
226 Content classTree = writer.getClassHeader(currentClass);
227 buildChildren(node, classTree);
228 classSerializedTree.addContent(classTree);
229 }
230 }
231 packageSerializedTree.addContent(classSerializedTree);
232 }
234 /**
235 * Build the serial UID information for the given class.
236 *
237 * @param node the XML element that specifies which components to document
238 * @param classTree content tree to which the serial UID information will be added
239 */
240 public void buildSerialUIDInfo(XMLNode node, Content classTree) {
241 Content serialUidTree = writer.getSerialUIDInfoHeader();
242 FieldDoc[] fields = currentClass.fields(false);
243 for (int i = 0; i < fields.length; i++) {
244 if (fields[i].name().equals("serialVersionUID") &&
245 fields[i].constantValueExpression() != null) {
246 writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER,
247 fields[i].constantValueExpression(), serialUidTree);
248 break;
249 }
250 }
251 classTree.addContent(serialUidTree);
252 }
254 /**
255 * Build the summaries for the methods and fields.
256 *
257 * @param node the XML element that specifies which components to document
258 * @param classTree content tree to which the documentation will be added
259 */
260 public void buildClassContent(XMLNode node, Content classTree) {
261 Content classContentTree = writer.getClassContentHeader();
262 buildChildren(node, classContentTree);
263 classTree.addContent(classContentTree);
264 }
266 /**
267 * Build the summaries for the methods that belong to the given
268 * class.
269 *
270 * @param node the XML element that specifies which components to document
271 * @param classContentTree content tree to which the documentation will be added
272 */
273 public void buildSerializableMethods(XMLNode node, Content classContentTree) {
274 Content serializableMethodTree = methodWriter.getSerializableMethodsHeader();
275 MemberDoc[] members = currentClass.serializationMethods();
276 int membersLength = members.length;
277 if (membersLength > 0) {
278 for (int i = 0; i < membersLength; i++) {
279 currentMember = members[i];
280 Content methodsContentTree = methodWriter.getMethodsContentHeader(
281 (i == membersLength - 1));
282 buildChildren(node, methodsContentTree);
283 serializableMethodTree.addContent(methodsContentTree);
284 }
285 }
286 if (currentClass.serializationMethods().length > 0) {
287 classContentTree.addContent(methodWriter.getSerializableMethods(
288 configuration.getText("doclet.Serialized_Form_methods"),
289 serializableMethodTree));
290 if (currentClass.isSerializable() && !currentClass.isExternalizable()) {
291 if (currentClass.serializationMethods().length == 0) {
292 Content noCustomizationMsg = methodWriter.getNoCustomizationMsg(
293 configuration.getText(
294 "doclet.Serializable_no_customization"));
295 classContentTree.addContent(methodWriter.getSerializableMethods(
296 configuration.getText("doclet.Serialized_Form_methods"),
297 noCustomizationMsg));
298 }
299 }
300 }
301 }
303 /**
304 * Build the method sub header.
305 *
306 * @param node the XML element that specifies which components to document
307 * @param methodsContentTree content tree to which the documentation will be added
308 */
309 public void buildMethodSubHeader(XMLNode node, Content methodsContentTree) {
310 methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree);
311 }
313 /**
314 * Build the deprecated method description.
315 *
316 * @param node the XML element that specifies which components to document
317 * @param methodsContentTree content tree to which the documentation will be added
318 */
319 public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) {
320 methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree);
321 }
323 /**
324 * Build the information for the method.
325 *
326 * @param node the XML element that specifies which components to document
327 * @param methodsContentTree content tree to which the documentation will be added
328 */
329 public void buildMethodInfo(XMLNode node, Content methodsContentTree) {
330 if(configuration.nocomment){
331 return;
332 }
333 buildChildren(node, methodsContentTree);
334 }
336 /**
337 * Build method description.
338 *
339 * @param node the XML element that specifies which components to document
340 * @param methodsContentTree content tree to which the documentation will be added
341 */
342 public void buildMethodDescription(XMLNode node, Content methodsContentTree) {
343 methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree);
344 }
346 /**
347 * Build the method tags.
348 *
349 * @param node the XML element that specifies which components to document
350 * @param methodsContentTree content tree to which the documentation will be added
351 */
352 public void buildMethodTags(XMLNode node, Content methodsContentTree) {
353 methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree);
354 MethodDoc method = (MethodDoc)currentMember;
355 if (method.name().compareTo("writeExternal") == 0
356 && method.tags("serialData").length == 0) {
357 if (configuration.serialwarn) {
358 configuration.getDocletSpecificMsg().warning(
359 currentMember.position(), "doclet.MissingSerialDataTag",
360 method.containingClass().qualifiedName(), method.name());
361 }
362 }
363 }
365 /**
366 * Build the field header.
367 *
368 * @param node the XML element that specifies which components to document
369 * @param classContentTree content tree to which the documentation will be added
370 */
371 public void buildFieldHeader(XMLNode node, Content classContentTree) {
372 if (currentClass.serializableFields().length > 0) {
373 buildFieldSerializationOverview(currentClass, classContentTree);
374 }
375 }
377 /**
378 * Build the serialization overview for the given class.
379 *
380 * @param classDoc the class to print the overview for.
381 * @param classContentTree content tree to which the documentation will be added
382 */
383 public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) {
384 if (classDoc.definesSerializableFields()) {
385 FieldDoc serialPersistentField = classDoc.serializableFields()[0];
386 // Check to see if there are inline comments, tags or deprecation
387 // information to be printed.
388 if (fieldWriter.shouldPrintOverview(serialPersistentField)) {
389 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
390 Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true);
391 fieldWriter.addMemberDeprecatedInfo(serialPersistentField,
392 fieldsOverviewContentTree);
393 if (!configuration.nocomment) {
394 fieldWriter.addMemberDescription(serialPersistentField,
395 fieldsOverviewContentTree);
396 fieldWriter.addMemberTags(serialPersistentField,
397 fieldsOverviewContentTree);
398 }
399 serializableFieldsTree.addContent(fieldsOverviewContentTree);
400 classContentTree.addContent(fieldWriter.getSerializableFields(
401 configuration.getText("doclet.Serialized_Form_class"),
402 serializableFieldsTree));
403 }
404 }
405 }
407 /**
408 * Build the summaries for the fields that belong to the given class.
409 *
410 * @param node the XML element that specifies which components to document
411 * @param classContentTree content tree to which the documentation will be added
412 */
413 public void buildSerializableFields(XMLNode node, Content classContentTree) {
414 MemberDoc[] members = currentClass.serializableFields();
415 int membersLength = members.length;
416 if (membersLength > 0) {
417 Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader();
418 for (int i = 0; i < membersLength; i++) {
419 currentMember = members[i];
420 if (!currentClass.definesSerializableFields()) {
421 Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
422 (i == membersLength - 1));
423 buildChildren(node, fieldsContentTree);
424 serializableFieldsTree.addContent(fieldsContentTree);
425 }
426 else {
427 buildSerialFieldTagsInfo(serializableFieldsTree);
428 }
429 }
430 classContentTree.addContent(fieldWriter.getSerializableFields(
431 configuration.getText("doclet.Serialized_Form_fields"),
432 serializableFieldsTree));
433 }
434 }
436 /**
437 * Build the field sub header.
438 *
439 * @param node the XML element that specifies which components to document
440 * @param fieldsContentTree content tree to which the documentation will be added
441 */
442 public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) {
443 if (!currentClass.definesSerializableFields()) {
444 FieldDoc field = (FieldDoc) currentMember;
445 fieldWriter.addMemberHeader(field.type().asClassDoc(),
446 field.type().typeName(), field.type().dimension(), field.name(),
447 fieldsContentTree);
448 }
449 }
451 /**
452 * Build the field deprecation information.
453 *
454 * @param node the XML element that specifies which components to document
455 * @param fieldsContentTree content tree to which the documentation will be added
456 */
457 public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) {
458 if (!currentClass.definesSerializableFields()) {
459 FieldDoc field = (FieldDoc)currentMember;
460 fieldWriter.addMemberDeprecatedInfo(field, fieldsContentTree);
461 }
462 }
464 /**
465 * Build the serial field tags information.
466 *
467 * @param serializableFieldsTree content tree to which the documentation will be added
468 */
469 public void buildSerialFieldTagsInfo(Content serializableFieldsTree) {
470 if(configuration.nocomment){
471 return;
472 }
473 FieldDoc field = (FieldDoc)currentMember;
474 // Process Serializable Fields specified as array of
475 // ObjectStreamFields. Print a member for each serialField tag.
476 // (There should be one serialField tag per ObjectStreamField
477 // element.)
478 SerialFieldTag[] tags = field.serialFieldTags();
479 Arrays.sort(tags);
480 int tagsLength = tags.length;
481 for (int i = 0; i < tagsLength; i++) {
482 if (tags[i].fieldName() == null || tags[i].fieldType() == null) // ignore malformed @serialField tags
483 continue;
484 Content fieldsContentTree = fieldWriter.getFieldsContentHeader(
485 (i == tagsLength - 1));
486 fieldWriter.addMemberHeader(tags[i].fieldTypeDoc(),
487 tags[i].fieldType(), "", tags[i].fieldName(), fieldsContentTree);
488 fieldWriter.addMemberDescription(tags[i], fieldsContentTree);
489 serializableFieldsTree.addContent(fieldsContentTree);
490 }
491 }
493 /**
494 * Build the field information.
495 *
496 * @param node the XML element that specifies which components to document
497 * @param fieldsContentTree content tree to which the documentation will be added
498 */
499 public void buildFieldInfo(XMLNode node, Content fieldsContentTree) {
500 if(configuration.nocomment){
501 return;
502 }
503 FieldDoc field = (FieldDoc)currentMember;
504 ClassDoc cd = field.containingClass();
505 // Process default Serializable field.
506 if ((field.tags("serial").length == 0) && ! field.isSynthetic()
507 && configuration.serialwarn) {
508 configuration.message.warning(field.position(),
509 "doclet.MissingSerialTag", cd.qualifiedName(),
510 field.name());
511 }
512 fieldWriter.addMemberDescription(field, fieldsContentTree);
513 fieldWriter.addMemberTags(field, fieldsContentTree);
514 }
516 /**
517 * Return true if the given Doc should be included
518 * in the serialized form.
519 *
520 * @param doc the Doc object to check for serializability.
521 */
522 public static boolean serialInclude(Doc doc) {
523 if (doc == null) {
524 return false;
525 }
526 return doc.isClass() ?
527 serialClassInclude((ClassDoc)doc) :
528 serialDocInclude(doc);
529 }
531 /**
532 * Return true if the given ClassDoc should be included
533 * in the serialized form.
534 *
535 * @param cd the ClassDoc object to check for serializability.
536 */
537 private static boolean serialClassInclude(ClassDoc cd) {
538 if (cd.isEnum()) {
539 return false;
540 }
541 try {
542 cd.superclassType();
543 } catch (NullPointerException e) {
544 //Workaround for null pointer bug in ClassDoc.superclassType().
545 return false;
546 }
547 if (cd.isSerializable()) {
548 if (cd.tags("serial").length > 0) {
549 return serialDocInclude(cd);
550 } else if (cd.isPublic() || cd.isProtected()) {
551 return true;
552 } else {
553 return false;
554 }
555 }
556 return false;
557 }
559 /**
560 * Return true if the given Doc should be included
561 * in the serialized form.
562 *
563 * @param doc the Doc object to check for serializability.
564 */
565 private static boolean serialDocInclude(Doc doc) {
566 if (doc.isEnum()) {
567 return false;
568 }
569 Tag[] serial = doc.tags("serial");
570 if (serial.length > 0) {
571 String serialtext = StringUtils.toLowerCase(serial[0].text());
572 if (serialtext.indexOf("exclude") >= 0) {
573 return false;
574 } else if (serialtext.indexOf("include") >= 0) {
575 return true;
576 }
577 }
578 return true;
579 }
581 /**
582 * Return true if any of the given classes have a @serialinclude tag.
583 *
584 * @param classes the classes to check.
585 * @return true if any of the given classes have a @serialinclude tag.
586 */
587 private boolean serialClassFoundToDocument(ClassDoc[] classes) {
588 for (int i = 0; i < classes.length; i++) {
589 if (serialClassInclude(classes[i])) {
590 return true;
591 }
592 }
593 return false;
594 }
595 }