001
014
015 package com.liferay.portal.tools;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
019 import com.liferay.portal.kernel.util.CharPool;
020 import com.liferay.portal.kernel.util.GetterUtil;
021 import com.liferay.portal.kernel.util.StringBundler;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Tuple;
025 import com.liferay.portal.kernel.util.Validator;
026 import com.liferay.portal.kernel.xml.Document;
027 import com.liferay.portal.kernel.xml.Element;
028 import com.liferay.portal.tools.javadocformatter.SinceJava;
029 import com.liferay.portal.tools.servicebuilder.ServiceBuilder;
030 import com.liferay.portal.util.FileImpl;
031 import com.liferay.portal.xml.SAXReaderImpl;
032 import com.liferay.util.xml.DocUtil;
033
034 import com.thoughtworks.qdox.JavaDocBuilder;
035 import com.thoughtworks.qdox.model.AbstractBaseJavaEntity;
036 import com.thoughtworks.qdox.model.AbstractJavaEntity;
037 import com.thoughtworks.qdox.model.Annotation;
038 import com.thoughtworks.qdox.model.DocletTag;
039 import com.thoughtworks.qdox.model.JavaClass;
040 import com.thoughtworks.qdox.model.JavaField;
041 import com.thoughtworks.qdox.model.JavaMethod;
042 import com.thoughtworks.qdox.model.JavaPackage;
043 import com.thoughtworks.qdox.model.JavaParameter;
044 import com.thoughtworks.qdox.model.Type;
045 import com.thoughtworks.qdox.model.annotation.AnnotationValue;
046
047 import java.io.File;
048 import java.io.FileInputStream;
049 import java.io.FileOutputStream;
050 import java.io.FileReader;
051 import java.io.IOException;
052 import java.io.InputStream;
053 import java.io.OutputStreamWriter;
054 import java.io.Reader;
055 import java.io.Writer;
056
057 import java.util.ArrayList;
058 import java.util.Collection;
059 import java.util.HashMap;
060 import java.util.HashSet;
061 import java.util.List;
062 import java.util.Map;
063 import java.util.Properties;
064 import java.util.Set;
065 import java.util.TreeMap;
066 import java.util.regex.Matcher;
067 import java.util.regex.Pattern;
068
069 import org.apache.tools.ant.DirectoryScanner;
070
071
077 public class JavadocFormatter {
078
079 public static void main(String[] args) {
080 try {
081 new JavadocFormatter(args);
082 }
083 catch (Exception e) {
084 e.printStackTrace();
085 }
086 }
087
088 public JavadocFormatter(String[] args) throws Exception {
089 Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
090
091 String init = arguments.get("javadoc.init");
092
093 if (Validator.isNotNull(init) && !init.startsWith("$")) {
094 _initializeMissingJavadocs = GetterUtil.getBoolean(init);
095 }
096
097 _inputDir = GetterUtil.getString(arguments.get("javadoc.input.dir"));
098
099 if (_inputDir.startsWith("$")) {
100 _inputDir = "./";
101 }
102
103 if (!_inputDir.endsWith("/")) {
104 _inputDir += "/";
105 }
106
107 System.out.println("Input directory is " + _inputDir);
108
109 String limit = arguments.get("javadoc.limit");
110
111 _outputFilePrefix = GetterUtil.getString(
112 arguments.get("javadoc.output.file.prefix"));
113
114 if (_outputFilePrefix.startsWith("$")) {
115 _outputFilePrefix = "javadocs";
116 }
117
118 String update = arguments.get("javadoc.update");
119
120 if (Validator.isNotNull(update) && !update.startsWith("$")) {
121 _updateJavadocs = GetterUtil.getBoolean(update);
122 }
123
124 DirectoryScanner directoryScanner = new DirectoryScanner();
125
126 directoryScanner.setBasedir(_inputDir);
127 directoryScanner.setExcludes(
128 new String[] {"**\\classes\\**", "**\\portal-client\\**"});
129
130 List<String> includes = new ArrayList<String>();
131
132 if (Validator.isNotNull(limit) && !limit.startsWith("$")) {
133 System.out.println("Limit on " + limit);
134
135 String[] limitArray = StringUtil.split(limit, '/');
136
137 for (String curLimit : limitArray) {
138 includes.add(
139 "**\\" + StringUtil.replace(curLimit, ".", "\\") +
140 "\\**\\*.java");
141 includes.add("**\\" + curLimit + ".java");
142 }
143 }
144 else {
145 includes.add("**\\*.java");
146 }
147
148 directoryScanner.setIncludes(
149 includes.toArray(new String[includes.size()]));
150
151 directoryScanner.scan();
152
153 String[] fileNames = directoryScanner.getIncludedFiles();
154
155 if ((fileNames.length == 0) && Validator.isNotNull(limit) &&
156 !limit.startsWith("$")) {
157
158 StringBundler sb = new StringBundler("Limit file not found: ");
159
160 sb.append(limit);
161
162 if (limit.contains(".")) {
163 sb.append(" Specify limit filename without package path or ");
164 sb.append("file type suffix.");
165 }
166
167 System.out.println(sb.toString());
168 }
169
170 _languagePropertiesFile = new File("src/content/Language.properties");
171
172 if (_languagePropertiesFile.exists()) {
173 _languageProperties = new Properties();
174
175 _languageProperties.load(
176 new FileInputStream(_languagePropertiesFile.getAbsolutePath()));
177 }
178
179 for (String fileName : fileNames) {
180 fileName = StringUtil.replace(fileName, "\\", "/");
181
182 _format(fileName);
183 }
184
185 for (Map.Entry<String, Tuple> entry : _javadocxXmlTuples.entrySet()) {
186 Tuple tuple = entry.getValue();
187
188 File javadocsXmlFile = (File)tuple.getObject(1);
189 String oldJavadocsXmlContent = (String)tuple.getObject(2);
190 Document javadocsXmlDocument = (Document)tuple.getObject(3);
191
192 Element javadocsXmlRootElement =
193 javadocsXmlDocument.getRootElement();
194
195 javadocsXmlRootElement.sortElementsByChildElement(
196 "javadoc", "type");
197
198 String newJavadocsXmlContent =
199 javadocsXmlDocument.formattedString();
200
201 if (!oldJavadocsXmlContent.equals(newJavadocsXmlContent)) {
202 _fileUtil.write(javadocsXmlFile, newJavadocsXmlContent);
203 }
204
205 _detachUnnecessaryTypes(javadocsXmlRootElement);
206
207 File javadocsRuntimeXmlFile = new File(
208 StringUtil.replaceLast(
209 javadocsXmlFile.toString(), "-all.xml", "-rt.xml"));
210
211 String oldJavadocsRuntimeXmlContent = StringPool.BLANK;
212
213 if (javadocsRuntimeXmlFile.exists()) {
214 oldJavadocsRuntimeXmlContent = _fileUtil.read(
215 javadocsRuntimeXmlFile);
216 }
217
218 String newJavadocsRuntimeXmlContent =
219 javadocsXmlDocument.compactString();
220
221 if (!oldJavadocsRuntimeXmlContent.equals(
222 newJavadocsRuntimeXmlContent)) {
223
224 _fileUtil.write(
225 javadocsRuntimeXmlFile, newJavadocsRuntimeXmlContent);
226 }
227 }
228 }
229
230 private List<Tuple> _addAncestorJavaClassTuples(
231 JavaClass javaClass, List<Tuple> ancestorJavaClassTuples) {
232
233 JavaClass superJavaClass = javaClass.getSuperJavaClass();
234
235 if (superJavaClass != null) {
236 ancestorJavaClassTuples.add(new Tuple(superJavaClass));
237
238 ancestorJavaClassTuples = _addAncestorJavaClassTuples(
239 superJavaClass, ancestorJavaClassTuples);
240 }
241
242 Type[] implementz = javaClass.getImplements();
243
244 for (Type implement : implementz) {
245 Type[] actualTypeArguments = implement.getActualTypeArguments();
246 JavaClass implementedInterface = implement.getJavaClass();
247
248 if (actualTypeArguments == null) {
249 ancestorJavaClassTuples.add(new Tuple(implementedInterface));
250 }
251 else {
252 ancestorJavaClassTuples.add(
253 new Tuple(implementedInterface, actualTypeArguments));
254 }
255
256 ancestorJavaClassTuples = _addAncestorJavaClassTuples(
257 implementedInterface, ancestorJavaClassTuples);
258 }
259
260 return ancestorJavaClassTuples;
261 }
262
263 private void _addClassCommentElement(
264 Element rootElement, JavaClass javaClass) {
265
266 String comment = _getCDATA(javaClass);
267
268 if (comment.startsWith("Copyright (c)")) {
269 comment = StringPool.BLANK;
270 }
271
272 if (Validator.isNull(comment)) {
273 return;
274 }
275
276 Element commentElement = rootElement.addElement("comment");
277
278 commentElement.addCDATA(comment);
279 }
280
281 private void _addDocletElements(
282 Element parentElement, AbstractJavaEntity abstractJavaEntity,
283 String name)
284 throws Exception {
285
286 DocletTag[] docletTags = abstractJavaEntity.getTagsByName(name);
287
288 for (DocletTag docletTag : docletTags) {
289 String value = docletTag.getValue();
290
291 value = _trimMultilineText(value);
292
293 value = StringUtil.replace(value, " </", "</");
294
295 Element element = parentElement.addElement(name);
296
297 element.addCDATA(value);
298 }
299
300 if ((docletTags.length == 0) && name.equals("author")) {
301 Element element = parentElement.addElement(name);
302
303 element.addCDATA(ServiceBuilder.AUTHOR);
304 }
305 }
306
307 private String _addDocletTags(
308 Element parentElement, String[] tagNames, String indent,
309 boolean publicAccess) {
310
311 List<String> allTagNames = new ArrayList<String>();
312 List<String> customTagNames = new ArrayList<String>();
313 List<String> requiredTagNames = new ArrayList<String>();
314
315 for (String tagName : tagNames) {
316 List<Element> elements = parentElement.elements(tagName);
317
318 for (Element element : elements) {
319 Element commentElement = element.element("comment");
320
321 String comment = null;
322
323
324
325 if (commentElement != null) {
326 comment = commentElement.getText();
327 }
328 else {
329 comment = element.getText();
330 }
331
332 if (tagName.equals("param") || tagName.equals("return") ||
333 tagName.equals("throws")) {
334
335 if (Validator.isNotNull(comment)) {
336 requiredTagNames.add(tagName);
337 }
338 else if (tagName.equals("param")) {
339 if (GetterUtil.getBoolean(
340 element.elementText("required"))) {
341
342 requiredTagNames.add(tagName);
343 }
344 }
345 else if (tagName.equals("throws")) {
346 if (GetterUtil.getBoolean(
347 element.elementText("required"))) {
348
349 requiredTagNames.add(tagName);
350 }
351 }
352 }
353 else {
354 customTagNames.add(tagName);
355 }
356
357 allTagNames.add(tagName);
358 }
359 }
360
361 int maxTagNameLength = 0;
362
363 List<String> maxTagNameLengthTags = new ArrayList<String>();
364
365 if (_initializeMissingJavadocs) {
366 maxTagNameLengthTags.addAll(allTagNames);
367 }
368 else if (_updateJavadocs) {
369 if (!requiredTagNames.isEmpty()) {
370 maxTagNameLengthTags.addAll(allTagNames);
371 }
372 else {
373 maxTagNameLengthTags.addAll(customTagNames);
374 maxTagNameLengthTags.addAll(requiredTagNames);
375 }
376 }
377 else {
378 maxTagNameLengthTags.addAll(customTagNames);
379 maxTagNameLengthTags.addAll(requiredTagNames);
380 }
381
382 for (String name : maxTagNameLengthTags) {
383 if (name.length() > maxTagNameLength) {
384 maxTagNameLength = name.length();
385 }
386 }
387
388
389
390 maxTagNameLength += 2;
391
392 String tagNameIndent = _getSpacesIndent(maxTagNameLength);
393
394 StringBundler sb = new StringBundler();
395
396 for (String tagName : tagNames) {
397 List<Element> elements = parentElement.elements(tagName);
398
399 for (Element element : elements) {
400 Element commentElement = element.element("comment");
401
402 String comment = null;
403
404 if (commentElement != null) {
405 comment = commentElement.getText();
406 }
407 else {
408 comment = element.getText();
409 }
410
411 String elementName = element.elementText("name");
412
413 if (Validator.isNotNull(comment)) {
414 comment = _assembleTagComment(
415 tagName, elementName, comment, indent, tagNameIndent);
416
417 sb.append(comment);
418 }
419 else {
420 if (_initializeMissingJavadocs && publicAccess) {
421
422
423
424 comment = _assembleTagComment(
425 tagName, elementName, comment, indent,
426 tagNameIndent);
427
428 sb.append(comment);
429 }
430 else if (_updateJavadocs && publicAccess) {
431 if (!tagName.equals("param") &&
432 !tagName.equals("return") &&
433 !tagName.equals("throws")) {
434
435
436
437 comment = _assembleTagComment(
438 tagName, elementName, comment, indent,
439 tagNameIndent);
440
441 sb.append(comment);
442 }
443 else if (!requiredTagNames.isEmpty()) {
444
445
446
447 comment = _assembleTagComment(
448 tagName, elementName, comment, indent,
449 tagNameIndent);
450
451 sb.append(comment);
452 }
453 else {
454
455
456
457 }
458 }
459 else {
460 if (!tagName.equals("param") &&
461 !tagName.equals("return") &&
462 !tagName.equals("throws")) {
463
464
465
466 comment = _assembleTagComment(
467 tagName, elementName, comment, indent,
468 tagNameIndent);
469
470 sb.append(comment);
471 }
472 else if (tagName.equals("param") ||
473 tagName.equals("return") ||
474 tagName.equals("throws")) {
475
476 if (GetterUtil.getBoolean(
477 element.elementText("required"))) {
478
479 elementName = element.elementText("name");
480
481 comment = _assembleTagComment(
482 tagName, elementName, comment, indent,
483 tagNameIndent);
484
485 sb.append(comment);
486 }
487 }
488 else {
489
490
491
492 }
493 }
494 }
495 }
496 }
497
498 return sb.toString();
499 }
500
501 private void _addFieldElement(Element rootElement, JavaField javaField)
502 throws Exception {
503
504 Element fieldElement = rootElement.addElement("field");
505
506 DocUtil.add(fieldElement, "name", javaField.getName());
507
508 String comment = _getCDATA(javaField);
509
510 if (Validator.isNotNull(comment)) {
511 Element commentElement = fieldElement.addElement("comment");
512
513 commentElement.addCDATA(comment);
514 }
515
516 _addDocletElements(fieldElement, javaField, "version");
517 _addDocletElements(fieldElement, javaField, "see");
518 _addDocletElements(fieldElement, javaField, "since");
519 _addDocletElements(fieldElement, javaField, "deprecated");
520 }
521
522 private void _addMethodElement(Element rootElement, JavaMethod javaMethod)
523 throws Exception {
524
525 Element methodElement = rootElement.addElement("method");
526
527 DocUtil.add(methodElement, "name", javaMethod.getName());
528
529 String comment = _getCDATA(javaMethod);
530
531 if (Validator.isNotNull(comment)) {
532 Element commentElement = methodElement.addElement("comment");
533
534 commentElement.addCDATA(_getCDATA(javaMethod));
535 }
536
537 _addDocletElements(methodElement, javaMethod, "version");
538 _addParamElements(methodElement, javaMethod);
539 _addReturnElement(methodElement, javaMethod);
540 _addThrowsElements(methodElement, javaMethod);
541 _addDocletElements(methodElement, javaMethod, "see");
542 _addDocletElements(methodElement, javaMethod, "since");
543 _addDocletElements(methodElement, javaMethod, "deprecated");
544 }
545
546 private void _addParamElement(
547 Element methodElement, JavaParameter javaParameter,
548 DocletTag[] paramDocletTags) {
549
550 String name = javaParameter.getName();
551
552 String value = null;
553
554 for (DocletTag paramDocletTag : paramDocletTags) {
555 String curValue = paramDocletTag.getValue();
556
557 if (!curValue.startsWith(name)) {
558 continue;
559 }
560 else {
561 value = curValue;
562
563 break;
564 }
565 }
566
567 Element paramElement = methodElement.addElement("param");
568
569 DocUtil.add(paramElement, "name", name);
570 DocUtil.add(paramElement, "type", _getTypeValue(javaParameter));
571
572 if (value != null) {
573 value = value.substring(name.length());
574
575 DocUtil.add(paramElement, "required", true);
576 }
577
578 value = _trimMultilineText(value);
579
580 Element commentElement = paramElement.addElement("comment");
581
582 commentElement.addCDATA(value);
583 }
584
585 private void _addParamElements(
586 Element methodElement, JavaMethod javaMethod) {
587
588 JavaParameter[] javaParameters = javaMethod.getParameters();
589
590 DocletTag[] paramDocletTags = javaMethod.getTagsByName("param");
591
592 for (JavaParameter javaParameter : javaParameters) {
593 _addParamElement(methodElement, javaParameter, paramDocletTags);
594 }
595 }
596
597 private void _addReturnElement(Element methodElement, JavaMethod javaMethod)
598 throws Exception {
599
600 Type returns = javaMethod.getReturns();
601
602 if (returns == null) {
603 return;
604 }
605
606 String returnsValue = returns.getValue();
607
608 if (returnsValue.equals("void")) {
609 return;
610 }
611
612 Element returnElement = methodElement.addElement("return");
613
614 DocletTag[] returnDocletTags = javaMethod.getTagsByName("return");
615
616 String comment = StringPool.BLANK;
617
618 if (returnDocletTags.length > 0) {
619 DocletTag returnDocletTag = returnDocletTags[0];
620
621 comment = GetterUtil.getString(returnDocletTag.getValue());
622
623 DocUtil.add(returnElement, "required", true);
624 }
625
626 comment = _trimMultilineText(comment);
627
628 Element commentElement = returnElement.addElement("comment");
629
630 commentElement.addCDATA(comment);
631 }
632
633 private void _addThrowsElement(
634 Element methodElement, Type exceptionType,
635 DocletTag[] throwsDocletTags) {
636
637 JavaClass javaClass = exceptionType.getJavaClass();
638
639 String name = javaClass.getName();
640
641 String value = null;
642
643 for (DocletTag throwsDocletTag : throwsDocletTags) {
644 String curValue = throwsDocletTag.getValue();
645
646 if (!curValue.startsWith(name)) {
647 continue;
648 }
649 else {
650 value = curValue;
651
652 break;
653 }
654 }
655
656 Element throwsElement = methodElement.addElement("throws");
657
658 DocUtil.add(throwsElement, "name", name);
659 DocUtil.add(throwsElement, "type", exceptionType.getValue());
660
661 if (value != null) {
662 value = value.substring(name.length());
663
664 DocUtil.add(throwsElement, "required", true);
665 }
666
667 value = _trimMultilineText(value);
668
669 Element commentElement = throwsElement.addElement("comment");
670
671 commentElement.addCDATA(_getCDATA(value));
672 }
673
674 private void _addThrowsElements(
675 Element methodElement, JavaMethod javaMethod) {
676
677 Type[] exceptionTypes = javaMethod.getExceptions();
678
679 DocletTag[] throwsDocletTags = javaMethod.getTagsByName("throws");
680
681 for (Type exceptionType : exceptionTypes) {
682 _addThrowsElement(methodElement, exceptionType, throwsDocletTags);
683 }
684 }
685
686 private String _assembleTagComment(
687 String tagName, String elementName, String comment, String indent,
688 String tagNameIndent) {
689
690 String indentAndTagName = indent + StringPool.AT + tagName;
691
692 if (Validator.isNotNull(elementName)) {
693 if (Validator.isNotNull(comment)) {
694 comment = elementName + StringPool.SPACE + comment;
695 }
696 else {
697 comment = elementName;
698 }
699
700
701
702 comment = _wrapText(comment, indent + tagNameIndent);
703
704
705
706 comment =
707 indentAndTagName + comment.substring(indentAndTagName.length());
708 }
709 else {
710 if (Validator.isNotNull(comment)) {
711
712
713
714 comment = _wrapText(comment, indent + tagNameIndent);
715
716
717
718 comment =
719 indentAndTagName +
720 comment.substring(indentAndTagName.length());
721 }
722 else {
723
724
725
726 comment = indentAndTagName + "\n";
727 }
728 }
729
730 return comment;
731 }
732
733 private void _detachUnnecessaryTypes(Element rootElement) {
734 List<Element> elements = rootElement.elements();
735
736 for (Element element : elements) {
737 String type = element.elementText("type");
738
739 if (!type.contains(".service.") || !type.endsWith("ServiceImpl")) {
740 element.detach();
741 }
742 }
743 }
744
745 private void _format(String fileName) throws Exception {
746 InputStream inputStream = new FileInputStream(_inputDir + fileName);
747
748 byte[] bytes = new byte[inputStream.available()];
749
750 inputStream.read(bytes);
751
752 inputStream.close();
753
754 String originalContent = new String(bytes, StringPool.UTF8);
755
756 if (fileName.endsWith("JavadocFormatter.java") ||
757 fileName.endsWith("SourceFormatter.java") ||
758 _hasGeneratedTag(originalContent)) {
759
760 return;
761 }
762
763 JavaClass javaClass = _getJavaClass(
764 fileName, new UnsyncStringReader(originalContent));
765
766 String javadocLessContent = _removeJavadocFromJava(
767 javaClass, originalContent);
768
769 Document document = _getJavadocDocument(javaClass);
770
771 _updateJavadocsXmlFile(fileName, javaClass, document);
772
773 _updateJavaFromDocument(
774 fileName, originalContent, javadocLessContent, document);
775 }
776
777 private String _formatCDATA(String cdata, String exclude) {
778 StringBundler sb = new StringBundler();
779
780 String startTag = "<" + exclude + ">";
781 String endTag = "</" + exclude + ">";
782
783 String[] cdataParts = cdata.split(startTag);
784
785 for (String cdataPart : cdataParts) {
786 if (!cdataPart.contains(endTag)) {
787 cdataPart = _getCDATA(cdataPart);
788 }
789
790 if (cdataPart.contains("</" + exclude + ">")) {
791 sb.append(startTag);
792 }
793
794 sb.append(cdataPart);
795 }
796
797 return sb.toString();
798 }
799
800 private String _formatInlines(String text) {
801
802
803
804 text = text.replaceAll("[?@param id](?i)\\bid(s)?\\b", " ID$1");
805
806
807
808 text = text.replaceAll(
809 "(?i)(?<!<code>|\\w)(null|false|true)(?!\\w)", "<code>$1</code>");
810
811 return text;
812 }
813
814 private String _getCDATA(AbstractJavaEntity abstractJavaEntity) {
815 return _getCDATA(abstractJavaEntity.getComment());
816 }
817
818 private String _getCDATA(String cdata) {
819 if (cdata == null) {
820 return StringPool.BLANK;
821 }
822 else if (cdata.contains("<pre>")) {
823 cdata = _formatCDATA(cdata, "pre");
824 }
825 else if (cdata.contains("<table>")) {
826 cdata = _formatCDATA(cdata, "table");
827 }
828 else {
829 cdata = cdata.replaceAll(
830 "(?s)\\s*<(p|[ou]l)>\\s*(.*?)\\s*</\\1>\\s*",
831 "\n\n<$1>\n$2\n</$1>\n\n");
832 cdata = cdata.replaceAll(
833 "(?s)\\s*<li>\\s*(.*?)\\s*</li>\\s*", "\n<li>\n$1\n</li>\n");
834 cdata = StringUtil.replace(cdata, "</li>\n\n<li>", "</li>\n<li>");
835 cdata = cdata.replaceAll("\n\\s+\n", "\n\n");
836 cdata.replaceAll(" +", " ");
837
838
839
840 Pattern pattern = Pattern.compile(
841 "(^.*?(?=\n\n|$)+|(?<=<p>\n).*?(?=\n</p>))", Pattern.DOTALL);
842
843 Matcher matcher = pattern.matcher(cdata);
844
845 StringBuffer sb = new StringBuffer();
846
847 while (matcher.find()) {
848 String trimmed = _trimMultilineText(matcher.group());
849
850
851
852 trimmed = trimmed.replaceAll("\\$", "\\\\\\$");
853
854 matcher.appendReplacement(sb, trimmed);
855 }
856
857 matcher.appendTail(sb);
858
859 cdata = sb.toString();
860 }
861
862 return cdata.trim();
863 }
864
865 private String _getClassName(String fileName) {
866 int pos = fileName.indexOf("src/");
867
868 if (pos == -1) {
869 pos = fileName.indexOf("test/integration/");
870
871 if (pos != -1) {
872 pos = fileName.indexOf("integration/", pos);
873 }
874 }
875
876 if (pos == -1) {
877 pos = fileName.indexOf("test/unit/");
878
879 if (pos != -1) {
880 pos = fileName.indexOf("unit/", pos);
881 }
882 }
883
884 if (pos == -1) {
885 pos = fileName.indexOf("test/");
886 }
887
888 if (pos == -1) {
889 pos = fileName.indexOf("service/");
890 }
891
892 if (pos == -1) {
893 throw new RuntimeException(fileName);
894 }
895
896 pos = fileName.indexOf("/", pos);
897
898 String srcFile = fileName.substring(pos + 1, fileName.length());
899
900 return StringUtil.replace(
901 srcFile.substring(0, srcFile.length() - 5), "/", ".");
902 }
903
904 private String _getFieldKey(Element fieldElement) {
905 return fieldElement.elementText("name");
906 }
907
908 private String _getFieldKey(JavaField javaField) {
909 return javaField.getName();
910 }
911
912 private String _getIndent(
913 String[] lines, AbstractBaseJavaEntity abstractBaseJavaEntity) {
914
915 String line = lines[abstractBaseJavaEntity.getLineNumber() - 1];
916
917 String indent = StringPool.BLANK;
918
919 for (char c : line.toCharArray()) {
920 if (Character.isWhitespace(c)) {
921 indent += c;
922 }
923 else {
924 break;
925 }
926 }
927
928 return indent;
929 }
930
931 private int _getIndentLength(String indent) {
932 int indentLength = 0;
933
934 for (char c : indent.toCharArray()) {
935 if (c == '\t') {
936 indentLength = indentLength + 4;
937 }
938 else {
939 indentLength++;
940 }
941 }
942
943 return indentLength;
944 }
945
946 private JavaClass _getJavaClass(String fileName, Reader reader)
947 throws Exception {
948
949 String className = _getClassName(fileName);
950
951 JavaDocBuilder javadocBuilder = new JavaDocBuilder();
952
953 if (reader == null) {
954 File file = new File(fileName);
955
956 if (!file.exists()) {
957 return null;
958 }
959
960 javadocBuilder.addSource(file);
961 }
962 else {
963 javadocBuilder.addSource(reader);
964 }
965
966 return javadocBuilder.getClassByName(className);
967 }
968
969 private String _getJavaClassComment(
970 Element rootElement, JavaClass javaClass) {
971
972 StringBundler sb = new StringBundler();
973
974 String indent = StringPool.BLANK;
975
976 sb.append("\n");
1000
1001 return sb.toString();
1002 }
1003
1004 private int _getJavaClassLineNumber(JavaClass javaClass) {
1005 int lineNumber = javaClass.getLineNumber();
1006
1007 Annotation[] annotations = javaClass.getAnnotations();
1008
1009 if (annotations.length == 0) {
1010 return lineNumber;
1011 }
1012
1013 for (Annotation annotation : annotations) {
1014 int annotationLineNumber = annotation.getLineNumber();
1015
1016 Map<String, String> propertyMap = annotation.getPropertyMap();
1017
1018 if (propertyMap.isEmpty()) {
1019 annotationLineNumber--;
1020 }
1021
1022 if (annotationLineNumber < lineNumber) {
1023 lineNumber = annotationLineNumber;
1024 }
1025 }
1026
1027 return lineNumber;
1028 }
1029
1030 private Document _getJavadocDocument(JavaClass javaClass) throws Exception {
1031 Element rootElement = _saxReaderUtil.createElement("javadoc");
1032
1033 Document document = _saxReaderUtil.createDocument(rootElement);
1034
1035 DocUtil.add(rootElement, "name", javaClass.getName());
1036 DocUtil.add(rootElement, "type", javaClass.getFullyQualifiedName());
1037
1038 _addClassCommentElement(rootElement, javaClass);
1039 _addDocletElements(rootElement, javaClass, "author");
1040 _addDocletElements(rootElement, javaClass, "version");
1041 _addDocletElements(rootElement, javaClass, "see");
1042 _addDocletElements(rootElement, javaClass, "since");
1043 _addDocletElements(rootElement, javaClass, "serial");
1044 _addDocletElements(rootElement, javaClass, "deprecated");
1045
1046 JavaMethod[] javaMethods = javaClass.getMethods();
1047
1048 for (JavaMethod javaMethod : javaMethods) {
1049 _addMethodElement(rootElement, javaMethod);
1050 }
1051
1052 JavaField[] javaFields = javaClass.getFields();
1053
1054 for (JavaField javaField : javaFields) {
1055 _addFieldElement(rootElement, javaField);
1056 }
1057
1058 return document;
1059 }
1060
1061 private Tuple _getJavadocsXmlTuple(String fileName) throws Exception {
1062 File file = new File(_inputDir + fileName);
1063
1064 String absolutePath = file.getAbsolutePath();
1065
1066 absolutePath = StringUtil.replace(absolutePath, "\\", "/");
1067 absolutePath = StringUtil.replace(absolutePath, "/./", "/");
1068
1069 int pos = absolutePath.indexOf("/portal-impl/src/");
1070
1071 String srcDirName = null;
1072
1073 if (pos != -1) {
1074 srcDirName = absolutePath.substring(0, pos + 17);
1075 }
1076
1077 if (srcDirName == null) {
1078 pos = absolutePath.indexOf("/portal-kernel/src/");
1079
1080 if (pos == -1) {
1081 pos = absolutePath.indexOf("/portal-service/src/");
1082 }
1083
1084 if (pos == -1) {
1085 pos = absolutePath.indexOf("/util-bridges/src/");
1086 }
1087
1088 if (pos == -1) {
1089 pos = absolutePath.indexOf("/util-java/src/");
1090 }
1091
1092 if (pos == -1) {
1093 pos = absolutePath.indexOf("/util-taglib/src/");
1094 }
1095
1096 if (pos != -1) {
1097 srcDirName =
1098 absolutePath.substring(0, pos) + "/portal-impl/src/";
1099 }
1100 }
1101
1102 if (srcDirName == null) {
1103 pos = absolutePath.indexOf("/WEB-INF/src/");
1104
1105 if (pos != -1) {
1106 srcDirName = absolutePath.substring(0, pos + 13);
1107 }
1108 }
1109
1110 if (srcDirName == null) {
1111 return null;
1112 }
1113
1114 Tuple tuple = _javadocxXmlTuples.get(srcDirName);
1115
1116 if (tuple != null) {
1117 return tuple;
1118 }
1119
1120 File javadocsXmlFile = new File(
1121 srcDirName, "META-INF/" + _outputFilePrefix + "-all.xml");
1122
1123 if (!javadocsXmlFile.exists()) {
1124 _fileUtil.write(
1125 javadocsXmlFile,
1126 "<?xml version=\"1.0\"?>\n\n<javadocs>\n</javadocs>");
1127 }
1128
1129 String javadocsXmlContent = _fileUtil.read(javadocsXmlFile);
1130
1131 Document javadocsXmlDocument = _saxReaderUtil.read(javadocsXmlContent);
1132
1133 tuple = new Tuple(
1134 srcDirName, javadocsXmlFile, javadocsXmlContent,
1135 javadocsXmlDocument);
1136
1137 _javadocxXmlTuples.put(srcDirName, tuple);
1138
1139 return tuple;
1140 }
1141
1142 private String _getJavaFieldComment(
1143 String[] lines, Map<String, Element> fieldElementsMap,
1144 JavaField javaField) {
1145
1146 String fieldKey = _getFieldKey(javaField);
1147
1148 Element fieldElement = fieldElementsMap.get(fieldKey);
1149
1150 if (fieldElement == null) {
1151 return null;
1152 }
1153
1154 String indent = _getIndent(lines, javaField);
1155
1156 StringBundler sb = new StringBundler();
1157
1158 sb.append(indent);
1159 sb.append("\n");
1183
1184 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1185 Validator.isNull(docletTags)) {
1186
1187 return null;
1188 }
1189
1190 if (!_hasPublicModifier(javaField) && Validator.isNull(comment) &&
1191 Validator.isNull(docletTags)) {
1192
1193 return null;
1194 }
1195
1196 return sb.toString();
1197 }
1198
1199 private String _getJavaMethodComment(
1200 String[] lines, Map<String, Element> methodElementsMap,
1201 JavaMethod javaMethod) {
1202
1203 String methodKey = _getMethodKey(javaMethod);
1204
1205 Element methodElement = methodElementsMap.get(methodKey);
1206
1207 if (methodElement == null) {
1208 return null;
1209 }
1210
1211 String indent = _getIndent(lines, javaMethod);
1212
1213 StringBundler sb = new StringBundler();
1214
1215 sb.append(indent);
1216 sb.append("\n");
1243
1244 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1245 Validator.isNull(docletTags)) {
1246
1247 return null;
1248 }
1249
1250 if (!_hasPublicModifier(javaMethod) && Validator.isNull(comment) &&
1251 Validator.isNull(docletTags)) {
1252
1253 return null;
1254 }
1255
1256 return sb.toString();
1257 }
1258
1259 private String _getMethodKey(Element methodElement) {
1260 StringBundler sb = new StringBundler();
1261
1262 sb.append(methodElement.elementText("name"));
1263 sb.append(StringPool.OPEN_PARENTHESIS);
1264
1265 List<Element> paramElements = methodElement.elements("param");
1266
1267 for (Element paramElement : paramElements) {
1268 sb.append(paramElement.elementText("name"));
1269 sb.append("|");
1270 sb.append(paramElement.elementText("type"));
1271 sb.append(",");
1272 }
1273
1274 sb.append(StringPool.CLOSE_PARENTHESIS);
1275
1276 return sb.toString();
1277 }
1278
1279 private String _getMethodKey(JavaMethod javaMethod) {
1280 StringBundler sb = new StringBundler();
1281
1282 sb.append(javaMethod.getName());
1283 sb.append(StringPool.OPEN_PARENTHESIS);
1284
1285 JavaParameter[] javaParameters = javaMethod.getParameters();
1286
1287 for (JavaParameter javaParameter : javaParameters) {
1288 sb.append(javaParameter.getName());
1289 sb.append("|");
1290 sb.append(_getTypeValue(javaParameter));
1291 sb.append(",");
1292 }
1293
1294 sb.append(StringPool.CLOSE_PARENTHESIS);
1295
1296 return sb.toString();
1297 }
1298
1299 private String _getSpacesIndent(int length) {
1300 String indent = StringPool.BLANK;
1301
1302 for (int i = 0; i < length; i++) {
1303 indent += StringPool.SPACE;
1304 }
1305
1306 return indent;
1307 }
1308
1309 private String _getTypeValue(JavaParameter javaParameter) {
1310 Type type = javaParameter.getType();
1311
1312 String typeValue = type.getValue();
1313
1314 if (type.isArray()) {
1315 typeValue += "[]";
1316 }
1317
1318 return typeValue;
1319 }
1320
1321 private boolean _hasAnnotation(
1322 AbstractBaseJavaEntity abstractBaseJavaEntity, String annotationName) {
1323
1324 Annotation[] annotations = abstractBaseJavaEntity.getAnnotations();
1325
1326 if (annotations == null) {
1327 return false;
1328 }
1329
1330 for (int i = 0; i < annotations.length; i++) {
1331 Type type = annotations[i].getType();
1332
1333 JavaClass javaClass = type.getJavaClass();
1334
1335 if (annotationName.equals(javaClass.getName())) {
1336 return true;
1337 }
1338 }
1339
1340 return false;
1341 }
1342
1343 private boolean _hasGeneratedTag(String content) {
1344 if (content.contains("* @generated") || content.contains("$ANTLR")) {
1345 return true;
1346 }
1347 else {
1348 return false;
1349 }
1350 }
1351
1352 private boolean _hasPublicModifier(AbstractJavaEntity abstractJavaEntity) {
1353 String[] modifiers = abstractJavaEntity.getModifiers();
1354
1355 if (modifiers == null) {
1356 return false;
1357 }
1358
1359 for (String modifier : modifiers) {
1360 if (modifier.equals("public")) {
1361 return true;
1362 }
1363 }
1364
1365 return false;
1366 }
1367
1368 private boolean _isOverrideMethod(
1369 JavaClass javaClass, JavaMethod javaMethod,
1370 Collection<Tuple> ancestorJavaClassTuples) {
1371
1372 if (javaMethod.isConstructor() || javaMethod.isPrivate() ||
1373 javaMethod.isStatic() ||
1374 _overridesHigherJavaAPIVersion(javaMethod)) {
1375
1376 return false;
1377 }
1378
1379 String methodName = javaMethod.getName();
1380
1381 JavaParameter[] javaParameters = javaMethod.getParameters();
1382
1383 Type[] types = new Type[javaParameters.length];
1384
1385 for (int i = 0; i < javaParameters.length; i++) {
1386 types[i] = javaParameters[i].getType();
1387 }
1388
1389
1390
1391 for (Tuple ancestorJavaClassTuple : ancestorJavaClassTuples) {
1392 JavaClass ancestorJavaClass =
1393 (JavaClass)ancestorJavaClassTuple.getObject(0);
1394
1395 JavaMethod ancestorJavaMethod = null;
1396
1397 if (ancestorJavaClassTuple.getSize() > 1) {
1398
1399
1400
1401 Type[] ancestorActualTypeArguments =
1402 (Type[])ancestorJavaClassTuple.getObject(1);
1403
1404 Type[] genericTypes = new Type[types.length];
1405
1406 for (int i = 0; i < types.length; i++) {
1407 Type type = types[i];
1408
1409 String typeValue = type.getValue();
1410
1411 boolean useGenericType = false;
1412
1413 for (int j = 0; j < ancestorActualTypeArguments.length;
1414 j++) {
1415
1416 if (typeValue.equals(
1417 ancestorActualTypeArguments[j].getValue())) {
1418
1419 useGenericType = true;
1420
1421 break;
1422 }
1423 }
1424
1425 if (useGenericType) {
1426 genericTypes[i] = new Type("java.lang.Object");
1427 }
1428 else {
1429 genericTypes[i] = type;
1430 }
1431 }
1432
1433 ancestorJavaMethod = ancestorJavaClass.getMethodBySignature(
1434 methodName, genericTypes);
1435 }
1436 else {
1437 ancestorJavaMethod = ancestorJavaClass.getMethodBySignature(
1438 methodName, types);
1439 }
1440
1441 if (ancestorJavaMethod == null) {
1442 continue;
1443 }
1444
1445 boolean samePackage = false;
1446
1447 JavaPackage ancestorJavaPackage = ancestorJavaClass.getPackage();
1448
1449 if (ancestorJavaPackage != null) {
1450 samePackage = ancestorJavaPackage.equals(
1451 javaClass.getPackage());
1452 }
1453
1454
1455
1456 if (samePackage) {
1457 return !ancestorJavaMethod.isPrivate();
1458 }
1459 else {
1460 if (ancestorJavaMethod.isProtected() ||
1461 ancestorJavaMethod.isPublic()) {
1462
1463 return true;
1464 }
1465 else {
1466 return false;
1467 }
1468 }
1469 }
1470
1471 return false;
1472 }
1473
1474 private boolean _overridesHigherJavaAPIVersion(JavaMethod javaMethod) {
1475 Annotation[] annotations = javaMethod.getAnnotations();
1476
1477 if (annotations == null) {
1478 return false;
1479 }
1480
1481 for (Annotation annotation : annotations) {
1482 Type type = annotation.getType();
1483
1484 JavaClass javaClass = type.getJavaClass();
1485
1486 String javaClassName = javaClass.getFullyQualifiedName();
1487
1488 if (javaClassName.equals(SinceJava.class.getName())) {
1489 AnnotationValue value = annotation.getProperty("value");
1490
1491 double sinceJava = GetterUtil.getDouble(
1492 value.getParameterValue());
1493
1494 if (sinceJava > _LOWEST_SUPPORTED_JAVA_VERSION) {
1495 return true;
1496 }
1497 }
1498 }
1499
1500 return false;
1501 }
1502
1503 private String _removeJavadocFromJava(JavaClass javaClass, String content) {
1504 Set<Integer> lineNumbers = new HashSet<Integer>();
1505
1506 lineNumbers.add(_getJavaClassLineNumber(javaClass));
1507
1508 JavaMethod[] javaMethods = javaClass.getMethods();
1509
1510 for (JavaMethod javaMethod : javaMethods) {
1511 lineNumbers.add(javaMethod.getLineNumber());
1512 }
1513
1514 JavaField[] javaFields = javaClass.getFields();
1515
1516 for (JavaField javaField : javaFields) {
1517 lineNumbers.add(javaField.getLineNumber());
1518 }
1519
1520 String[] lines = StringUtil.splitLines(content);
1521
1522 for (int lineNumber : lineNumbers) {
1523 if (lineNumber == 0) {
1524 continue;
1525 }
1526
1527 int pos = lineNumber - 2;
1528
1529 String line = lines[pos];
1530
1531 if (line == null) {
1532 continue;
1533 }
1534
1535 line = line.trim();
1536
1537 if (line.endsWith("*/")) {
1538 while (true) {
1539 lines[pos] = null;
1540
1541 if (line.startsWith("