1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugins.javadoc;
20  
21  import java.io.File;
22  import java.io.FileNotFoundException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.Writer;
26  import java.net.MalformedURLException;
27  import java.net.URI;
28  import java.net.URISyntaxException;
29  import java.net.URL;
30  import java.net.URLClassLoader;
31  import java.nio.charset.Charset;
32  import java.nio.charset.StandardCharsets;
33  import java.nio.file.Files;
34  import java.nio.file.Path;
35  import java.nio.file.StandardCopyOption;
36  import java.time.LocalDate;
37  import java.time.ZoneOffset;
38  import java.util.ArrayList;
39  import java.util.Arrays;
40  import java.util.Collection;
41  import java.util.Collections;
42  import java.util.HashMap;
43  import java.util.HashSet;
44  import java.util.LinkedHashMap;
45  import java.util.LinkedHashSet;
46  import java.util.LinkedList;
47  import java.util.List;
48  import java.util.Locale;
49  import java.util.Map;
50  import java.util.Map.Entry;
51  import java.util.Optional;
52  import java.util.Properties;
53  import java.util.Set;
54  import java.util.StringTokenizer;
55  import java.util.regex.Pattern;
56  import java.util.stream.Collectors;
57  
58  import org.apache.commons.lang3.BooleanUtils;
59  import org.apache.commons.lang3.StringUtils;
60  import org.apache.maven.RepositoryUtils;
61  import org.apache.maven.archiver.MavenArchiver;
62  import org.apache.maven.artifact.Artifact;
63  import org.apache.maven.artifact.ArtifactUtils;
64  import org.apache.maven.artifact.handler.ArtifactHandler;
65  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
66  import org.apache.maven.artifact.versioning.ArtifactVersion;
67  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
68  import org.apache.maven.doxia.tools.SiteTool;
69  import org.apache.maven.execution.MavenSession;
70  import org.apache.maven.model.Dependency;
71  import org.apache.maven.model.Plugin;
72  import org.apache.maven.model.Resource;
73  import org.apache.maven.plugin.AbstractMojo;
74  import org.apache.maven.plugin.MojoExecution;
75  import org.apache.maven.plugin.MojoExecutionException;
76  import org.apache.maven.plugin.MojoFailureException;
77  import org.apache.maven.plugins.annotations.Parameter;
78  import org.apache.maven.plugins.javadoc.options.BootclasspathArtifact;
79  import org.apache.maven.plugins.javadoc.options.DocletArtifact;
80  import org.apache.maven.plugins.javadoc.options.Group;
81  import org.apache.maven.plugins.javadoc.options.JavadocOptions;
82  import org.apache.maven.plugins.javadoc.options.JavadocPathArtifact;
83  import org.apache.maven.plugins.javadoc.options.OfflineLink;
84  import org.apache.maven.plugins.javadoc.options.ResourcesArtifact;
85  import org.apache.maven.plugins.javadoc.options.Tag;
86  import org.apache.maven.plugins.javadoc.options.Taglet;
87  import org.apache.maven.plugins.javadoc.options.TagletArtifact;
88  import org.apache.maven.plugins.javadoc.options.io.xpp3.JavadocOptionsXpp3Writer;
89  import org.apache.maven.plugins.javadoc.resolver.JavadocBundle;
90  import org.apache.maven.plugins.javadoc.resolver.ResourceResolver;
91  import org.apache.maven.plugins.javadoc.resolver.SourceResolverConfig;
92  import org.apache.maven.project.DefaultProjectBuildingRequest;
93  import org.apache.maven.project.MavenProject;
94  import org.apache.maven.project.ProjectBuilder;
95  import org.apache.maven.project.ProjectBuildingException;
96  import org.apache.maven.project.ProjectBuildingRequest;
97  import org.apache.maven.reporting.MavenReportException;
98  import org.apache.maven.settings.Proxy;
99  import org.apache.maven.settings.Settings;
100 import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
101 import org.apache.maven.shared.artifact.filter.resolve.PatternExclusionsFilter;
102 import org.apache.maven.shared.artifact.filter.resolve.PatternInclusionsFilter;
103 import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
104 import org.apache.maven.shared.invoker.MavenInvocationException;
105 import org.apache.maven.toolchain.Toolchain;
106 import org.apache.maven.toolchain.ToolchainManager;
107 import org.apache.maven.wagon.PathUtils;
108 import org.codehaus.plexus.archiver.ArchiverException;
109 import org.codehaus.plexus.archiver.UnArchiver;
110 import org.codehaus.plexus.archiver.manager.ArchiverManager;
111 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
112 import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
113 import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
114 import org.codehaus.plexus.languages.java.jpms.LocationManager;
115 import org.codehaus.plexus.languages.java.jpms.ModuleNameSource;
116 import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
117 import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
118 import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
119 import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
120 import org.codehaus.plexus.languages.java.version.JavaVersion;
121 import org.codehaus.plexus.util.DirectoryScanner;
122 import org.codehaus.plexus.util.FileUtils;
123 import org.codehaus.plexus.util.IOUtil;
124 import org.codehaus.plexus.util.WriterFactory;
125 import org.codehaus.plexus.util.cli.CommandLineException;
126 import org.codehaus.plexus.util.cli.CommandLineUtils;
127 import org.codehaus.plexus.util.cli.Commandline;
128 import org.codehaus.plexus.util.xml.Xpp3Dom;
129 import org.eclipse.aether.RepositorySystem;
130 import org.eclipse.aether.RepositorySystemSession;
131 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
132 import org.eclipse.aether.artifact.DefaultArtifact;
133 import org.eclipse.aether.collection.CollectRequest;
134 import org.eclipse.aether.graph.DependencyFilter;
135 import org.eclipse.aether.resolution.ArtifactRequest;
136 import org.eclipse.aether.resolution.ArtifactResolutionException;
137 import org.eclipse.aether.resolution.ArtifactResult;
138 import org.eclipse.aether.resolution.DependencyRequest;
139 import org.eclipse.aether.resolution.DependencyResolutionException;
140 import org.eclipse.aether.util.filter.AndDependencyFilter;
141 import org.eclipse.aether.util.filter.PatternExclusionsDependencyFilter;
142 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
143 
144 import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast;
145 import static org.apache.maven.plugins.javadoc.JavadocUtil.isEmpty;
146 import static org.apache.maven.plugins.javadoc.JavadocUtil.isNotEmpty;
147 import static org.apache.maven.plugins.javadoc.JavadocUtil.toList;
148 import static org.apache.maven.plugins.javadoc.JavadocUtil.toRelative;
149 
150 
151 
152 
153 
154 
155 
156 
157 
158 public abstract class AbstractJavadocMojo extends AbstractMojo {
159     
160 
161 
162 
163 
164 
165 
166     public static final String JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER = "javadoc-resources";
167 
168     
169 
170 
171 
172 
173 
174 
175     public static final String TEST_JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER = "test-javadoc-resources";
176 
177     
178 
179 
180     protected static final String DEBUG_JAVADOC_SCRIPT_NAME = "javadoc." + (SystemUtils.IS_OS_WINDOWS ? "bat" : "sh");
181 
182     
183 
184 
185 
186     protected static final String OPTIONS_FILE_NAME = "options";
187 
188     
189 
190 
191 
192     protected static final String PACKAGES_FILE_NAME = "packages";
193 
194     
195 
196 
197 
198     protected static final String ARGFILE_FILE_NAME = "argfile";
199 
200     
201 
202 
203 
204     protected static final String FILES_FILE_NAME = "files";
205 
206     
207 
208 
209 
210     private static final String DEFAULT_CSS_NAME = "stylesheet.css";
211 
212     private static final String PACKAGE_LIST = "package-list";
213     private static final String ELEMENT_LIST = "element-list";
214 
215     
216 
217 
218 
219 
220 
221 
222     private static final JavaVersion SINCE_JAVADOC_1_4 = JavaVersion.parse("1.4");
223 
224     
225 
226 
227 
228 
229 
230 
231 
232     private static final JavaVersion SINCE_JAVADOC_1_4_2 = JavaVersion.parse("1.4.2");
233 
234     
235 
236 
237 
238 
239 
240 
241 
242     private static final JavaVersion SINCE_JAVADOC_1_5 = JavaVersion.parse("1.5");
243 
244     
245 
246 
247 
248 
249 
250 
251     private static final JavaVersion SINCE_JAVADOC_1_6 = JavaVersion.parse("1.6");
252 
253     
254 
255 
256 
257 
258 
259 
260     private static final JavaVersion SINCE_JAVADOC_1_8 = JavaVersion.parse("1.8");
261 
262     private static final JavaVersion JAVA_VERSION = JavaVersion.JAVA_SPECIFICATION_VERSION;
263 
264     
265     
266     
267 
268     
269 
270 
271     protected SiteTool siteTool;
272 
273     
274 
275 
276 
277 
278     private ArchiverManager archiverManager;
279 
280     private ResourceResolver resourceResolver;
281 
282     private RepositorySystem repoSystem;
283 
284     @Parameter(defaultValue = "${repositorySystemSession}", readonly = true, required = true)
285     private RepositorySystemSession repoSession;
286 
287     private ArtifactHandlerManager artifactHandlerManager;
288 
289     
290 
291 
292 
293 
294     private ProjectBuilder mavenProjectBuilder;
295 
296     private ToolchainManager toolchainManager;
297 
298     public AbstractJavadocMojo(
299             SiteTool siteTool,
300             ArchiverManager archiverManager,
301             ResourceResolver resourceResolver,
302             RepositorySystem repoSystem,
303             ArtifactHandlerManager artifactHandlerManager,
304             ProjectBuilder mavenProjectBuilder,
305             ToolchainManager toolchainManager) {
306         this.siteTool = siteTool;
307         this.archiverManager = archiverManager;
308         this.resourceResolver = resourceResolver;
309         this.repoSystem = repoSystem;
310         this.artifactHandlerManager = artifactHandlerManager;
311         this.mavenProjectBuilder = mavenProjectBuilder;
312         this.toolchainManager = toolchainManager;
313     }
314 
315     final LocationManager locationManager = new LocationManager();
316 
317     
318     
319     
320 
321     
322 
323 
324 
325     @Parameter(defaultValue = "${session}", readonly = true, required = true)
326     protected MavenSession session;
327 
328     
329 
330 
331 
332 
333     @Parameter(defaultValue = "${settings}", readonly = true, required = true)
334     private Settings settings;
335 
336     
337 
338 
339     @Parameter(defaultValue = "${project}", readonly = true, required = true)
340     protected MavenProject project;
341 
342     @Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
343     protected MojoExecution mojoExecution;
344 
345     
346 
347 
348 
349 
350 
351 
352     @Parameter(property = "maven.javadoc.offline", defaultValue = "false")
353     private boolean offline;
354 
355     
356 
357 
358 
359 
360 
361 
362 
363 
364 
365     @Parameter(defaultValue = "${basedir}/src/main/javadoc")
366     private File javadocDirectory;
367 
368     
369 
370 
371 
372 
373 
374     @Parameter
375     private String[] additionalOptions;
376 
377     
378 
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 
389 
390 
391 
392     @Parameter(property = "additionalJOption")
393     private String additionalJOption;
394 
395     
396 
397 
398 
399 
400 
401 
402 
403 
404 
405 
406     @Parameter
407     private String[] additionalJOptions;
408 
409     
410 
411 
412 
413 
414 
415 
416 
417 
418 
419 
420 
421 
422 
423 
424 
425 
426 
427 
428 
429     @Parameter(property = "resourcesArtifacts")
430     private ResourcesArtifact[] resourcesArtifacts;
431 
432     
433 
434 
435     @Parameter(defaultValue = "${reactorProjects}", required = true, readonly = true)
436     protected List<MavenProject> reactorProjects;
437 
438     
439 
440 
441 
442 
443 
444 
445     @Parameter(property = "debug", defaultValue = "false")
446     private boolean debug;
447 
448     
449 
450 
451 
452 
453 
454     @Parameter(property = "javadocExecutable")
455     private String javadocExecutable;
456 
457     
458 
459 
460 
461 
462     @Parameter(property = "javadocVersion")
463     private String javadocVersion;
464 
465     
466 
467 
468     private JavaVersion javadocRuntimeVersion;
469 
470     
471 
472 
473 
474 
475     @Parameter(property = "maven.javadoc.skip", defaultValue = "false")
476     protected boolean skip;
477 
478     
479 
480 
481 
482 
483     @Parameter(property = "maven.javadoc.failOnError", defaultValue = "true")
484     protected boolean failOnError;
485 
486     
487 
488 
489 
490 
491     @Parameter(property = "maven.javadoc.failOnWarnings", defaultValue = "false")
492     protected boolean failOnWarnings;
493 
494     
495 
496 
497 
498 
499 
500 
501 
502 
503 
504 
505 
506 
507 
508 
509 
510 
511 
512 
513     @Parameter(property = "useStandardDocletOptions", defaultValue = "true")
514     protected boolean useStandardDocletOptions;
515 
516     
517 
518 
519 
520 
521 
522 
523 
524 
525 
526 
527 
528 
529 
530 
531 
532 
533 
534     @Parameter(property = "detectLinks", defaultValue = "false")
535     private boolean detectLinks;
536 
537     
538 
539 
540 
541 
542 
543 
544 
545 
546 
547 
548 
549 
550 
551 
552 
553     @Parameter(property = "detectOfflineLinks", defaultValue = "true")
554     private boolean detectOfflineLinks;
555 
556     
557 
558 
559 
560 
561 
562 
563 
564 
565 
566 
567 
568 
569     @Parameter(property = "detectJavaApiLink", defaultValue = "true")
570     private boolean detectJavaApiLink;
571 
572     
573 
574 
575 
576 
577 
578 
579 
580 
581 
582 
583 
584 
585 
586 
587 
588     @Parameter(property = "javaApiLinks")
589     private Properties javaApiLinks;
590 
591     
592 
593 
594 
595 
596 
597     @Parameter(property = "validateLinks", defaultValue = "false")
598     private boolean validateLinks;
599 
600     
601     
602     
603 
604     
605 
606 
607 
608 
609 
610 
611 
612     @Parameter(property = "bootclasspath")
613     private String bootclasspath;
614 
615     
616 
617 
618 
619 
620 
621 
622 
623 
624 
625 
626 
627 
628 
629 
630 
631 
632 
633 
634 
635 
636     @Parameter(property = "bootclasspathArtifacts")
637     private BootclasspathArtifact[] bootclasspathArtifacts;
638 
639     
640 
641 
642 
643 
644 
645     @Parameter(property = "breakiterator", defaultValue = "false")
646     private boolean breakiterator;
647 
648     
649 
650 
651 
652     @Parameter(property = "doclet")
653     private String doclet;
654 
655     
656 
657 
658 
659 
660 
661 
662 
663 
664 
665 
666 
667 
668 
669 
670 
671 
672     @Parameter(property = "docletArtifact")
673     private DocletArtifact docletArtifact;
674 
675     
676 
677 
678 
679 
680 
681 
682 
683 
684 
685 
686 
687 
688 
689 
690 
691 
692 
693 
694 
695     @Parameter(property = "docletArtifacts")
696     private DocletArtifact[] docletArtifacts;
697 
698     
699 
700 
701 
702 
703 
704     @Parameter(property = "docletPath")
705     private String docletPath;
706 
707     
708 
709 
710 
711 
712 
713 
714 
715     @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
716     private String encoding;
717 
718     
719 
720 
721 
722 
723 
724 
725 
726 
727 
728 
729 
730 
731 
732 
733 
734 
735     @Parameter(property = "excludePackageNames")
736     private String excludePackageNames;
737 
738     
739 
740 
741 
742 
743     @Parameter(property = "extdirs")
744     private String extdirs;
745 
746     
747 
748 
749 
750     @Parameter(property = "locale")
751     private String locale;
752 
753     
754 
755 
756 
757 
758 
759 
760     @Parameter(property = "maxmemory")
761     private String maxmemory;
762 
763     
764 
765 
766 
767 
768 
769 
770     @Parameter(property = "minmemory")
771     private String minmemory;
772 
773     
774 
775 
776 
777 
778     @Parameter(property = "old", defaultValue = "false")
779     @Deprecated
780     private boolean old;
781 
782     
783 
784 
785 
786 
787 
788 
789 
790     @Parameter(property = "overview", defaultValue = "${basedir}/src/main/javadoc/overview.html")
791     private File overview;
792 
793     
794 
795 
796 
797 
798 
799 
800 
801 
802 
803     @Parameter(property = "quiet", defaultValue = "false")
804     private boolean quiet;
805 
806     
807 
808 
809 
810 
811 
812 
813 
814 
815 
816 
817     @Parameter(property = "show", defaultValue = "protected")
818     private String show;
819 
820     
821 
822 
823 
824     @Parameter(property = "source", defaultValue = "${maven.compiler.source}")
825     private String source;
826 
827     
828 
829 
830 
831 
832 
833     @Parameter(defaultValue = "${maven.compiler.release}")
834     private String release;
835 
836     
837 
838 
839 
840 
841     @Parameter(property = "sourcepath")
842     private String sourcepath;
843 
844     
845 
846 
847 
848 
849 
850 
851 
852 
853 
854 
855 
856 
857     @Parameter(property = "maven.javadoc.disableSourcepathUsage")
858     private boolean disableSourcepathUsage;
859 
860     
861 
862 
863 
864 
865     @Parameter(property = "subpackages")
866     private String subpackages;
867 
868     
869 
870 
871 
872     @Parameter(property = "verbose", defaultValue = "false")
873     private boolean verbose;
874 
875     
876 
877 
878 
879 
880 
881 
882     @Parameter(property = "legacyMode", defaultValue = "false")
883     private boolean legacyMode;
884 
885     
886     
887     
888 
889     
890 
891 
892 
893     @Parameter(property = "author", defaultValue = "true")
894     private boolean author;
895 
896     
897 
898 
899 
900 
901 
902 
903 
904 
905     @Parameter(
906             property = "bottom",
907             defaultValue = "Copyright © {inceptionYear}–{currentYear} {organizationName}. "
908                     + "All rights reserved.")
909     private String bottom;
910 
911     
912 
913 
914 
915 
916     @Parameter(property = "charset")
917     private String charset;
918 
919     
920 
921 
922 
923 
924     @Parameter(property = "docencoding", defaultValue = "${project.reporting.outputEncoding}")
925     private String docencoding;
926 
927     
928 
929 
930 
931 
932 
933 
934 
935     @Parameter(property = "docfilessubdirs", defaultValue = "false")
936     private boolean docfilessubdirs;
937 
938     
939 
940 
941 
942 
943 
944     @Parameter(property = "doclint")
945     private String doclint;
946 
947     
948 
949 
950 
951     @Parameter(property = "doctitle", defaultValue = "${project.name} ${project.version} API")
952     private String doctitle;
953 
954     
955 
956 
957 
958 
959 
960     @Parameter(property = "excludedocfilessubdir")
961     private String excludedocfilessubdir;
962 
963     
964 
965 
966 
967     @Parameter(property = "footer")
968     private String footer;
969 
970     
971 
972 
973 
974 
975 
976 
977 
978 
979 
980 
981 
982 
983 
984 
985 
986 
987 
988 
989 
990 
991 
992 
993 
994 
995 
996 
997 
998 
999     @Parameter
1000     private Group[] groups;
1001 
1002     
1003 
1004 
1005 
1006     @Parameter(property = "header")
1007     private String header;
1008 
1009     
1010 
1011 
1012 
1013 
1014 
1015 
1016 
1017 
1018 
1019 
1020 
1021 
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 
1030 
1031 
1032 
1033 
1034 
1035 
1036 
1037 
1038 
1039 
1040 
1041 
1042 
1043 
1044 
1045 
1046 
1047 
1048 
1049 
1050     @Parameter(property = "helpfile")
1051     private String helpfile;
1052 
1053     
1054 
1055 
1056 
1057 
1058 
1059     @Parameter(property = "keywords", defaultValue = "false")
1060     private boolean keywords;
1061 
1062     
1063 
1064 
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 
1076 
1077 
1078 
1079 
1080 
1081 
1082 
1083 
1084 
1085     @Parameter(property = "links")
1086     protected ArrayList<String> links;
1087 
1088     
1089 
1090 
1091 
1092 
1093 
1094 
1095 
1096 
1097 
1098 
1099 
1100 
1101 
1102 
1103 
1104 
1105     @Parameter
1106     private List<DependencyLink> dependencyLinks = new ArrayList<>();
1107 
1108     
1109 
1110 
1111 
1112 
1113 
1114     @Parameter(property = "linksource", defaultValue = "false")
1115     private boolean linksource;
1116 
1117     
1118 
1119 
1120 
1121     @Parameter(property = "nocomment", defaultValue = "false")
1122     private boolean nocomment;
1123 
1124     
1125 
1126 
1127 
1128 
1129     @Parameter(property = "nodeprecated", defaultValue = "false")
1130     private boolean nodeprecated;
1131 
1132     
1133 
1134 
1135 
1136 
1137 
1138     @Parameter(property = "nodeprecatedlist", defaultValue = "false")
1139     private boolean nodeprecatedlist;
1140 
1141     
1142 
1143 
1144 
1145 
1146 
1147     @Parameter(property = "nohelp", defaultValue = "false")
1148     private boolean nohelp;
1149 
1150     
1151 
1152 
1153 
1154 
1155 
1156     @Parameter(property = "noindex", defaultValue = "false")
1157     private boolean noindex;
1158 
1159     
1160 
1161 
1162 
1163     @Parameter(property = "nonavbar", defaultValue = "false")
1164     private boolean nonavbar;
1165 
1166     
1167 
1168 
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1176     @Parameter(property = "nooverview", defaultValue = "false")
1177     private boolean nooverview;
1178 
1179     
1180 
1181 
1182 
1183 
1184 
1185 
1186 
1187 
1188 
1189     @Parameter(property = "noqualifier")
1190     private String noqualifier;
1191 
1192     
1193 
1194 
1195 
1196     @Parameter(property = "nosince", defaultValue = "false")
1197     private boolean nosince;
1198 
1199     
1200 
1201 
1202 
1203 
1204 
1205 
1206 
1207 
1208     @Parameter(property = "notimestamp", defaultValue = "false")
1209     private boolean notimestamp;
1210 
1211     
1212 
1213 
1214 
1215     @Parameter(property = "notree", defaultValue = "false")
1216     private boolean notree;
1217 
1218     
1219 
1220 
1221 
1222 
1223 
1224 
1225 
1226 
1227 
1228 
1229 
1230 
1231 
1232 
1233 
1234 
1235 
1236 
1237     @Parameter(property = "offlineLinks")
1238     private OfflineLink[] offlineLinks;
1239 
1240     
1241 
1242 
1243 
1244 
1245 
1246 
1247 
1248 
1249     @Parameter(defaultValue = "${project.build.directory}/reports", required = true)
1250     protected File outputDirectory;
1251 
1252     
1253 
1254 
1255 
1256 
1257     @Parameter(property = "packagesheader")
1258     private String packagesheader;
1259 
1260     
1261 
1262 
1263 
1264     @Parameter(property = "serialwarn", defaultValue = "false")
1265     private boolean serialwarn;
1266 
1267     
1268 
1269 
1270 
1271 
1272 
1273 
1274     @Parameter(property = "sourcetab", alias = "linksourcetab")
1275     private int sourcetab;
1276 
1277     
1278 
1279 
1280 
1281 
1282 
1283 
1284     @Parameter(property = "splitindex", defaultValue = "false")
1285     private boolean splitindex;
1286 
1287     
1288 
1289 
1290 
1291 
1292 
1293 
1294     @Parameter(property = "stylesheet", defaultValue = "java")
1295     @Deprecated
1296     private String stylesheet;
1297 
1298     
1299 
1300 
1301 
1302 
1303 
1304 
1305 
1306 
1307 
1308 
1309 
1310 
1311 
1312 
1313 
1314 
1315 
1316 
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 
1333 
1334 
1335 
1336 
1337     @Parameter(property = "stylesheetfile")
1338     private String stylesheetfile;
1339 
1340     
1341 
1342 
1343 
1344 
1345 
1346 
1347 
1348 
1349 
1350     @Parameter
1351     private String[] addStylesheets;
1352 
1353     
1354 
1355 
1356 
1357     @Parameter(property = "taglet")
1358     private String taglet;
1359 
1360     
1361 
1362 
1363 
1364 
1365 
1366 
1367 
1368 
1369 
1370 
1371 
1372 
1373 
1374 
1375 
1376 
1377 
1378 
1379 
1380 
1381 
1382 
1383 
1384 
1385     @Parameter(property = "tagletArtifact")
1386     private TagletArtifact tagletArtifact;
1387 
1388     
1389 
1390 
1391 
1392 
1393 
1394 
1395 
1396 
1397 
1398 
1399 
1400 
1401 
1402 
1403 
1404 
1405 
1406 
1407 
1408     @Parameter(property = "tagletArtifacts")
1409     private TagletArtifact[] tagletArtifacts;
1410 
1411     
1412 
1413 
1414 
1415 
1416     @Parameter(property = "tagletpath")
1417     private String tagletpath;
1418 
1419     
1420 
1421 
1422 
1423 
1424 
1425 
1426 
1427 
1428 
1429 
1430 
1431 
1432 
1433 
1434 
1435 
1436 
1437 
1438 
1439 
1440 
1441 
1442     @Parameter(property = "taglets")
1443     private Taglet[] taglets;
1444 
1445     
1446 
1447 
1448 
1449 
1450 
1451 
1452 
1453 
1454 
1455 
1456 
1457 
1458 
1459 
1460 
1461 
1462 
1463 
1464 
1465 
1466 
1467 
1468 
1469 
1470 
1471 
1472     @Parameter(property = "tags")
1473     private Tag[] tags;
1474 
1475     
1476 
1477 
1478 
1479 
1480 
1481     @Parameter(property = "top")
1482     private String top;
1483 
1484     
1485 
1486 
1487 
1488     @Parameter(property = "use", defaultValue = "true")
1489     private boolean use;
1490 
1491     
1492 
1493 
1494 
1495     @Parameter(property = "version", defaultValue = "true")
1496     private boolean version;
1497 
1498     
1499 
1500 
1501 
1502     @Parameter(property = "windowtitle", defaultValue = "${project.name} ${project.version} API")
1503     private String windowtitle;
1504 
1505     
1506 
1507 
1508 
1509 
1510 
1511     @Parameter(defaultValue = "false")
1512     private boolean includeDependencySources;
1513 
1514     
1515 
1516 
1517 
1518 
1519 
1520     @Parameter(defaultValue = "${project.build.directory}/distro-javadoc-sources")
1521     private File sourceDependencyCacheDir;
1522 
1523     
1524 
1525 
1526 
1527 
1528 
1529 
1530 
1531 
1532     @Parameter(defaultValue = "false")
1533     @Deprecated
1534     private boolean includeTransitiveDependencySources;
1535 
1536     
1537 
1538 
1539 
1540 
1541 
1542     @Parameter
1543     private List<String> dependencySourceIncludes;
1544 
1545     
1546 
1547 
1548 
1549 
1550 
1551     @Parameter
1552     private List<String> dependencySourceExcludes;
1553 
1554     
1555 
1556 
1557 
1558 
1559 
1560     @Parameter(defaultValue = "${project.build.directory}/javadoc-bundle-options", readonly = true)
1561     private File javadocOptionsDir;
1562 
1563     
1564 
1565 
1566 
1567 
1568 
1569     private transient List<JavadocBundle> dependencyJavadocBundles;
1570 
1571     
1572 
1573 
1574 
1575 
1576 
1577 
1578 
1579 
1580 
1581 
1582 
1583 
1584 
1585 
1586     @Parameter
1587     private List<AdditionalDependency> additionalDependencies;
1588 
1589     
1590 
1591 
1592 
1593 
1594 
1595     @Parameter
1596     private List<String> sourceFileIncludes;
1597 
1598     
1599 
1600 
1601 
1602 
1603 
1604     @Parameter
1605     private List<String> sourceFileExcludes;
1606 
1607     
1608 
1609 
1610 
1611 
1612     @Parameter(defaultValue = "true", property = "maven.javadoc.applyJavadocSecurityFix")
1613     private boolean applyJavadocSecurityFix = true;
1614 
1615     
1616 
1617 
1618 
1619 
1620 
1621 
1622 
1623 
1624 
1625 
1626 
1627 
1628 
1629 
1630 
1631 
1632 
1633 
1634 
1635 
1636 
1637 
1638 
1639 
1640 
1641 
1642 
1643 
1644 
1645 
1646 
1647 
1648     @Parameter
1649     private Map<String, String> jdkToolchain;
1650 
1651     
1652 
1653 
1654 
1655 
1656 
1657 
1658 
1659     @Parameter(
1660             property = "staleDataPath",
1661             defaultValue = "${project.build.directory}/maven-javadoc-plugin-stale-data.txt")
1662     private File staleDataPath;
1663 
1664     
1665 
1666 
1667 
1668 
1669 
1670 
1671     @Parameter(property = "maven.javadoc.skippedModules")
1672     private String skippedModules;
1673 
1674     
1675 
1676 
1677     private List<Pattern> patternsToSkip;
1678 
1679     
1680 
1681 
1682 
1683 
1684 
1685 
1686     @Parameter(defaultValue = "${project.build.outputTimestamp}")
1687     protected String outputTimestamp;
1688 
1689     
1690 
1691 
1692 
1693 
1694 
1695 
1696 
1697     @Parameter(property = "forceRootLocale", defaultValue = "true")
1698     private boolean forceRootLocale;
1699 
1700     
1701     
1702     
1703 
1704     
1705 
1706 
1707 
1708 
1709 
1710 
1711     protected boolean isAggregator() {
1712         return false;
1713     }
1714 
1715     
1716 
1717 
1718 
1719 
1720     protected boolean isTest() {
1721         return false;
1722     }
1723 
1724     protected String getOutputDirectory() {
1725         return outputDirectory.getAbsolutePath();
1726     }
1727 
1728     
1729 
1730 
1731 
1732 
1733 
1734     protected String getPluginReportOutputDirectory() {
1735         return getOutputDirectory() + "/" + (isTest() ? "test" : "") + "apidocs";
1736     }
1737 
1738     protected MavenProject getProject() {
1739         return project;
1740     }
1741 
1742     
1743 
1744 
1745 
1746 
1747     protected List<File> getProjectBuildOutputDirs(MavenProject p) {
1748         if (StringUtils.isEmpty(p.getBuild().getOutputDirectory())) {
1749             return Collections.emptyList();
1750         }
1751 
1752         return Collections.singletonList(new File(p.getBuild().getOutputDirectory()));
1753     }
1754 
1755     
1756 
1757 
1758 
1759     protected File getClassesFile(MavenProject project) {
1760         if (!isAggregator() && isTest()) {
1761             return null;
1762         }
1763 
1764         if (project.getArtifact() != null && project.getArtifact().getFile() != null) {
1765             File artifactFile = project.getArtifact().getFile();
1766             if (artifactFile.isDirectory() || artifactFile.getName().endsWith(".jar")) {
1767                 return artifactFile;
1768             }
1769         } else if (project.getExecutionProject() != null
1770                 && project.getExecutionProject().getArtifact() != null
1771                 && project.getExecutionProject().getArtifact().getFile() != null) {
1772             File artifactFile = project.getExecutionProject().getArtifact().getFile();
1773             if (artifactFile.isDirectory() || artifactFile.getName().endsWith(".jar")) {
1774                 return artifactFile;
1775             }
1776         }
1777 
1778         if (project.getBuild().getOutputDirectory() != null) {
1779             return new File(project.getBuild().getOutputDirectory());
1780         } else {
1781             return null;
1782         }
1783     }
1784 
1785     
1786 
1787 
1788 
1789     protected List<String> getProjectSourceRoots(MavenProject p) {
1790         if ("pom".equals(p.getPackaging().toLowerCase())) {
1791             return Collections.emptyList();
1792         }
1793 
1794         return p.getCompileSourceRoots() == null
1795                 ? Collections.<String>emptyList()
1796                 : new LinkedList<>(p.getCompileSourceRoots());
1797     }
1798 
1799     
1800 
1801 
1802 
1803     protected List<String> getExecutionProjectSourceRoots(MavenProject p) {
1804         if ("pom".equals(p.getExecutionProject().getPackaging().toLowerCase())) {
1805             return Collections.emptyList();
1806         }
1807 
1808         return p.getExecutionProject().getCompileSourceRoots() == null
1809                 ? Collections.<String>emptyList()
1810                 : new LinkedList<>(p.getExecutionProject().getCompileSourceRoots());
1811     }
1812 
1813     
1814 
1815 
1816     protected File getJavadocDirectory() {
1817         return javadocDirectory;
1818     }
1819 
1820     
1821 
1822 
1823     protected String getDoclint() {
1824         return doclint;
1825     }
1826 
1827     
1828 
1829 
1830     protected String getDoctitle() {
1831         return doctitle;
1832     }
1833 
1834     
1835 
1836 
1837     protected File getOverview() {
1838         return overview;
1839     }
1840 
1841     
1842 
1843 
1844     protected String getWindowtitle() {
1845         return windowtitle;
1846     }
1847 
1848     
1849 
1850 
1851     private String getCharset() {
1852         return (charset == null || charset.isEmpty()) ? getDocencoding() : charset;
1853     }
1854 
1855     
1856 
1857 
1858     private String getDocencoding() {
1859         return (docencoding == null || docencoding.isEmpty()) ? StandardCharsets.UTF_8.name() : docencoding;
1860     }
1861 
1862     
1863 
1864 
1865     private String getEncoding() {
1866         return (encoding == null || encoding.isEmpty())
1867                 ? Charset.defaultCharset().name()
1868                 : encoding;
1869     }
1870 
1871     @Override
1872     public void execute() throws MojoExecutionException, MojoFailureException {
1873         verifyRemovedParameter("aggregator");
1874         verifyRemovedParameter("proxyHost");
1875         verifyRemovedParameter("proxyPort");
1876         verifyReplacedParameter("additionalparam", "additionalOptions");
1877 
1878         doExecute();
1879     }
1880 
1881     protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
1882 
1883     protected final void verifyRemovedParameter(String paramName) {
1884         Xpp3Dom configDom = mojoExecution.getConfiguration();
1885         if (configDom != null) {
1886             if (configDom.getChild(paramName) != null) {
1887                 throw new IllegalArgumentException(
1888                         "parameter '" + paramName + "' has been removed from the plugin, please verify documentation.");
1889             }
1890         }
1891     }
1892 
1893     private void verifyReplacedParameter(String oldParamName, String newParamNew) {
1894         Xpp3Dom configDom = mojoExecution.getConfiguration();
1895         if (configDom != null) {
1896             if (configDom.getChild(oldParamName) != null) {
1897                 throw new IllegalArgumentException("parameter '" + oldParamName + "' has been replaced with "
1898                         + newParamNew + ", please verify documentation.");
1899             }
1900         }
1901     }
1902 
1903     
1904 
1905 
1906 
1907 
1908 
1909 
1910     protected void executeReport(Locale unusedLocale) throws MavenReportException {
1911         if (getLog().isDebugEnabled()) {
1912             this.debug = true;
1913         }
1914 
1915         
1916         
1917         try {
1918             buildJavadocOptions();
1919         } catch (IOException e) {
1920             throw new MavenReportException("Failed to generate javadoc options file: " + e.getMessage(), e);
1921         }
1922 
1923         Collection<JavadocModule> sourcePaths = getSourcePaths();
1924 
1925         Collection<Path> collectedSourcePaths =
1926                 sourcePaths.stream().flatMap(e -> e.getSourcePaths().stream()).collect(Collectors.toList());
1927 
1928         Map<Path, Collection<String>> files = getFiles(collectedSourcePaths);
1929         if (!canGenerateReport(files)) {
1930             return;
1931         }
1932 
1933         
1934         
1935         
1936 
1937         String jExecutable;
1938         try {
1939             jExecutable = getJavadocExecutable();
1940         } catch (IOException e) {
1941             throw new MavenReportException("Unable to find javadoc command: " + e.getMessage(), e);
1942         }
1943         setFJavadocVersion(new File(jExecutable));
1944 
1945         Collection<String> packageNames;
1946         if (javadocRuntimeVersion.isAtLeast("9")) {
1947             packageNames = getPackageNamesRespectingJavaModules(sourcePaths);
1948         } else {
1949             packageNames = getPackageNames(files);
1950         }
1951 
1952         
1953         
1954         
1955 
1956         File javadocOutputDirectory = new File(getPluginReportOutputDirectory());
1957         if (javadocOutputDirectory.exists() && !javadocOutputDirectory.isDirectory()) {
1958             throw new MavenReportException("IOException: " + javadocOutputDirectory + " is not a directory.");
1959         }
1960         if (javadocOutputDirectory.exists() && !javadocOutputDirectory.canWrite()) {
1961             throw new MavenReportException("IOException: " + javadocOutputDirectory + " is not writable.");
1962         }
1963         javadocOutputDirectory.mkdirs();
1964 
1965         
1966         
1967         
1968 
1969         copyAllResources(javadocOutputDirectory);
1970 
1971         
1972         
1973         
1974 
1975         Commandline cmd = new Commandline();
1976         cmd.getShell().setQuotedArgumentsEnabled(false); 
1977         cmd.setWorkingDirectory(javadocOutputDirectory.getAbsolutePath());
1978         cmd.setExecutable(jExecutable);
1979 
1980         
1981         
1982         
1983 
1984         addMemoryArg(cmd, "-Xmx", this.maxmemory);
1985         addMemoryArg(cmd, "-Xms", this.minmemory);
1986         addProxyArg(cmd);
1987 
1988         if (forceRootLocale) {
1989             cmd.createArg().setValue("-J-Duser.language=");
1990             cmd.createArg().setValue("-J-Duser.country=");
1991         }
1992 
1993         if (additionalJOption != null && !additionalJOption.isEmpty()) {
1994             cmd.createArg().setValue(additionalJOption);
1995         }
1996 
1997         if (additionalJOptions != null && additionalJOptions.length != 0) {
1998             for (String jo : additionalJOptions) {
1999                 cmd.createArg().setValue(jo);
2000             }
2001         }
2002 
2003         
2004         
2005         
2006         List<String> standardDocletArguments = new ArrayList<>();
2007 
2008         Set<OfflineLink> offlineLinks;
2009         if ((doclet == null || doclet.isEmpty()) || useStandardDocletOptions) {
2010             offlineLinks = getOfflineLinks();
2011             addStandardDocletOptions(javadocOutputDirectory, standardDocletArguments, offlineLinks);
2012         } else {
2013             offlineLinks = Collections.emptySet();
2014         }
2015 
2016         
2017         
2018         
2019         List<String> javadocArguments = new ArrayList<>();
2020 
2021         addJavadocOptions(javadocOutputDirectory, javadocArguments, sourcePaths, offlineLinks);
2022 
2023         
2024         
2025         
2026 
2027         List<String> arguments = new ArrayList<>(javadocArguments.size() + standardDocletArguments.size());
2028         arguments.addAll(javadocArguments);
2029         arguments.addAll(standardDocletArguments);
2030 
2031         if (arguments.size() > 0) {
2032             addCommandLineOptions(cmd, arguments, javadocOutputDirectory);
2033         }
2034 
2035         
2036         
2037         
2038 
2039         
2040         
2041         
2042         
2043         boolean includesExcludesActive = (sourceFileIncludes != null && !sourceFileIncludes.isEmpty())
2044                 || (sourceFileExcludes != null && !sourceFileExcludes.isEmpty());
2045         if (includesExcludesActive && !(subpackages == null || subpackages.isEmpty())) {
2046             getLog().warn("sourceFileIncludes and sourceFileExcludes have no effect when subpackages are specified!");
2047             includesExcludesActive = false;
2048         }
2049         if (!packageNames.isEmpty() && !includesExcludesActive) {
2050             addCommandLinePackages(cmd, javadocOutputDirectory, packageNames);
2051 
2052             
2053             
2054             
2055 
2056             List<String> specialFiles = getSpecialFiles(files);
2057 
2058             if (!specialFiles.isEmpty()) {
2059                 addCommandLineArgFile(cmd, javadocOutputDirectory, specialFiles);
2060             }
2061         } else {
2062             
2063             
2064             
2065 
2066             List<String> allFiles = new ArrayList<>();
2067             for (Map.Entry<Path, Collection<String>> filesEntry : files.entrySet()) {
2068                 for (String file : filesEntry.getValue()) {
2069                     allFiles.add(filesEntry.getKey().resolve(file).toString());
2070                 }
2071             }
2072 
2073             if (!files.isEmpty()) {
2074                 addCommandLineArgFile(cmd, javadocOutputDirectory, allFiles);
2075             }
2076         }
2077 
2078         
2079         
2080         
2081 
2082         executeJavadocCommandLine(cmd, javadocOutputDirectory);
2083 
2084         
2085         
2086         
2087         if (!debug) {
2088             for (int i = 0; i < cmd.getArguments().length; i++) {
2089                 String arg = cmd.getArguments()[i].trim();
2090 
2091                 if (!arg.startsWith("@")) {
2092                     continue;
2093                 }
2094 
2095                 File argFile = new File(javadocOutputDirectory, arg.substring(1));
2096                 if (argFile.exists()) {
2097                     argFile.delete();
2098                 }
2099             }
2100 
2101             File scriptFile = new File(javadocOutputDirectory, DEBUG_JAVADOC_SCRIPT_NAME);
2102             if (scriptFile.exists()) {
2103                 scriptFile.delete();
2104             }
2105         }
2106         if (applyJavadocSecurityFix) {
2107             
2108             try {
2109                 final int patched = fixFrameInjectionBug(javadocOutputDirectory, getDocencoding());
2110                 if (patched > 0) {
2111                     getLog().info(String.format(
2112                             "Fixed Javadoc frame injection vulnerability (CVE-2013-1571) in %d files.", patched));
2113                 }
2114             } catch (IOException e) {
2115                 throw new MavenReportException("Failed to patch javadocs vulnerability: " + e.getMessage(), e);
2116             }
2117         } else {
2118             getLog().info("applying javadoc security fix has been disabled");
2119         }
2120     }
2121 
2122     
2123 
2124 
2125 
2126 
2127 
2128 
2129     protected Map<Path, Collection<String>> getFiles(Collection<Path> sourcePaths) throws MavenReportException {
2130         Map<Path, Collection<String>> mappedFiles = new LinkedHashMap<>(sourcePaths.size());
2131         if (subpackages == null || subpackages.isEmpty()) {
2132             Collection<String> excludedPackages = getExcludedPackages();
2133 
2134             final boolean autoExclude;
2135             if (release != null) {
2136                 autoExclude = JavaVersion.parse(release).isBefore("9");
2137             } else if (source != null) {
2138                 autoExclude = JavaVersion.parse(source).isBefore("9");
2139             } else {
2140                 
2141                 
2142                 autoExclude = legacyMode;
2143             }
2144 
2145             for (Path sourcePath : sourcePaths) {
2146                 File sourceDirectory = sourcePath.toFile();
2147                 List<String> files = new ArrayList<>(JavadocUtil.getFilesFromSource(
2148                         sourceDirectory, sourceFileIncludes, sourceFileExcludes, excludedPackages));
2149 
2150                 if (autoExclude && files.remove("module-info.java")) {
2151                     getLog().debug("Auto exclude module-info.java due to source value");
2152                 }
2153                 mappedFiles.put(sourcePath, files);
2154             }
2155         }
2156 
2157         return mappedFiles;
2158     }
2159 
2160     
2161 
2162 
2163 
2164 
2165 
2166 
2167 
2168     protected Collection<JavadocModule> getSourcePaths() throws MavenReportException {
2169         Collection<JavadocModule> mappedSourcePaths = new ArrayList<>();
2170 
2171         if (sourcepath == null || sourcepath.isEmpty()) {
2172             if (!"pom".equals(project.getPackaging())) {
2173                 Set<Path> sourcePaths =
2174                         new LinkedHashSet<>(JavadocUtil.pruneDirs(project, getProjectSourceRoots(project)));
2175 
2176                 if (project.getExecutionProject() != null) {
2177                     sourcePaths.addAll(JavadocUtil.pruneDirs(project, getExecutionProjectSourceRoots(project)));
2178                 }
2179 
2180                 
2181 
2182 
2183 
2184 
2185                 if (getJavadocDirectory() != null) {
2186                     File javadocDir = getJavadocDirectory();
2187                     if (javadocDir.exists() && javadocDir.isDirectory()) {
2188                         Collection<Path> l = JavadocUtil.pruneDirs(
2189                                 project,
2190                                 Collections.singletonList(getJavadocDirectory().getAbsolutePath()));
2191                         sourcePaths.addAll(l);
2192                     }
2193                 }
2194                 if (!sourcePaths.isEmpty()) {
2195                     mappedSourcePaths.add(buildJavadocModule(project, sourcePaths));
2196                 }
2197             }
2198 
2199             if (isAggregator()) {
2200                 for (MavenProject subProject : getAggregatedProjects()) {
2201                     if (subProject != project) {
2202                         Collection<Path> additionalSourcePaths = new ArrayList<>();
2203 
2204                         List<String> sourceRoots = getProjectSourceRoots(subProject);
2205 
2206                         if (subProject.getExecutionProject() != null) {
2207                             sourceRoots.addAll(getExecutionProjectSourceRoots(subProject));
2208                         }
2209 
2210                         ArtifactHandler artifactHandler =
2211                                 subProject.getArtifact().getArtifactHandler();
2212                         if ("java".equals(artifactHandler.getLanguage())) {
2213                             additionalSourcePaths.addAll(JavadocUtil.pruneDirs(subProject, sourceRoots));
2214                         }
2215 
2216                         if (getJavadocDirectory() != null) {
2217                             String javadocDirRelative = PathUtils.toRelative(
2218                                     project.getBasedir(), getJavadocDirectory().getAbsolutePath());
2219                             File javadocDir = new File(subProject.getBasedir(), javadocDirRelative);
2220                             if (javadocDir.exists() && javadocDir.isDirectory()) {
2221                                 Collection<Path> l = JavadocUtil.pruneDirs(
2222                                         subProject, Collections.singletonList(javadocDir.getAbsolutePath()));
2223                                 additionalSourcePaths.addAll(l);
2224                             }
2225                         }
2226 
2227                         if (!additionalSourcePaths.isEmpty()) {
2228                             mappedSourcePaths.add(buildJavadocModule(subProject, additionalSourcePaths));
2229                         }
2230                     }
2231                 }
2232             }
2233 
2234             if (includeDependencySources) {
2235                 mappedSourcePaths.addAll(getDependencySourcePaths());
2236             }
2237         } else {
2238             Collection<Path> sourcePaths =
2239                     JavadocUtil.pruneDirs(project, new ArrayList<>(Arrays.asList(JavadocUtil.splitPath(sourcepath))));
2240             if (getJavadocDirectory() != null) {
2241                 Collection<Path> l = JavadocUtil.pruneDirs(
2242                         project, Collections.singletonList(getJavadocDirectory().getAbsolutePath()));
2243                 sourcePaths.addAll(l);
2244             }
2245 
2246             if (!sourcePaths.isEmpty()) {
2247                 mappedSourcePaths.add(new JavadocModule(
2248                         ArtifactUtils.key(project.getGroupId(), project.getArtifactId(), project.getVersion()),
2249                         getClassesFile(project),
2250                         sourcePaths));
2251             }
2252         }
2253 
2254         return mappedSourcePaths;
2255     }
2256 
2257     private JavadocModule buildJavadocModule(MavenProject project, Collection<Path> sourcePaths) {
2258         File classessFile = getClassesFile(project);
2259         ResolvePathResult resolvePathResult = getResolvePathResult(classessFile);
2260         if (resolvePathResult == null) {
2261             return new JavadocModule(
2262                     ArtifactUtils.key(project.getGroupId(), project.getArtifactId(), project.getVersion()),
2263                     classessFile,
2264                     sourcePaths);
2265         } else {
2266             return new JavadocModule(
2267                     ArtifactUtils.key(project.getGroupId(), project.getArtifactId(), project.getVersion()),
2268                     classessFile,
2269                     sourcePaths,
2270                     resolvePathResult.getModuleDescriptor(),
2271                     resolvePathResult.getModuleNameSource());
2272         }
2273     }
2274 
2275     
2276 
2277 
2278 
2279 
2280 
2281     private Set<MavenProject> modulesForAggregatedProject(
2282             MavenProject aggregatedProject, Map<Path, MavenProject> reactorProjectsMap) {
2283         
2284         
2285         
2286         
2287 
2288         if (aggregatedProject.getModules().isEmpty()) {
2289             return Collections.singleton(aggregatedProject);
2290         }
2291 
2292         Path basePath = aggregatedProject.getBasedir().toPath();
2293         List<Path> modulePaths = new LinkedList<>();
2294         for (String module : aggregatedProject.getModules()) {
2295             modulePaths.add(basePath.resolve(module).normalize());
2296         }
2297 
2298         Set<MavenProject> aggregatedModules = new LinkedHashSet<>();
2299 
2300         for (Path modulePath : modulePaths) {
2301             MavenProject module = reactorProjectsMap.remove(modulePath);
2302             if (module != null) {
2303                 aggregatedModules.addAll(modulesForAggregatedProject(module, reactorProjectsMap));
2304             }
2305         }
2306 
2307         return aggregatedModules;
2308     }
2309 
2310     
2311 
2312 
2313 
2314 
2315 
2316     protected SourceResolverConfig configureDependencySourceResolution(final SourceResolverConfig config) {
2317         return config.withCompileSources();
2318     }
2319 
2320     
2321 
2322 
2323 
2324 
2325 
2326     protected final Collection<JavadocModule> getDependencySourcePaths() throws MavenReportException {
2327         try {
2328             if (sourceDependencyCacheDir.exists()) {
2329                 FileUtils.forceDelete(sourceDependencyCacheDir);
2330                 sourceDependencyCacheDir.mkdirs();
2331             }
2332         } catch (IOException e) {
2333             throw new MavenReportException(
2334                     "Failed to delete cache directory: " + sourceDependencyCacheDir + "\nReason: " + e.getMessage(), e);
2335         }
2336 
2337         final SourceResolverConfig config = getDependencySourceResolverConfig();
2338 
2339         try {
2340             return resourceResolver.resolveDependencySourcePaths(config);
2341         } catch (org.apache.maven.artifact.resolver.ArtifactResolutionException
2342                 | org.apache.maven.artifact.resolver.ArtifactNotFoundException e) {
2343             throw new MavenReportException(
2344                     "Failed to resolve one or more javadoc source/resource artifacts:\n\n" + e.getMessage(), e);
2345         }
2346     }
2347 
2348     
2349 
2350 
2351 
2352 
2353 
2354     private TransformableFilter createDependencyArtifactFilter() {
2355         Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts();
2356 
2357         List<String> artifactPatterns = new ArrayList<>(dependencyArtifacts.size());
2358         for (Artifact artifact : dependencyArtifacts) {
2359             artifactPatterns.add(artifact.getGroupId() + ":" + artifact.getArtifactId());
2360         }
2361 
2362         return new PatternInclusionsFilter(artifactPatterns);
2363     }
2364 
2365     
2366 
2367 
2368 
2369 
2370 
2371     private SourceResolverConfig getDependencySourceResolverConfig() {
2372         final List<TransformableFilter> andFilters = new ArrayList<>();
2373 
2374         final List<String> dependencyIncludes = dependencySourceIncludes;
2375         final List<String> dependencyExcludes = dependencySourceExcludes;
2376 
2377         if (!includeTransitiveDependencySources || isNotEmpty(dependencyIncludes) || isNotEmpty(dependencyExcludes)) {
2378             if (!includeTransitiveDependencySources) {
2379                 andFilters.add(createDependencyArtifactFilter());
2380             }
2381 
2382             if (isNotEmpty(dependencyIncludes)) {
2383                 andFilters.add(new PatternInclusionsFilter(dependencyIncludes));
2384             }
2385 
2386             if (isNotEmpty(dependencyExcludes)) {
2387                 andFilters.add(new PatternExclusionsFilter(dependencyExcludes));
2388             }
2389         }
2390 
2391         return configureDependencySourceResolution(
2392                         new SourceResolverConfig(project, getProjectBuildingRequest(project), sourceDependencyCacheDir)
2393                                 .withReactorProjects(this.reactorProjects))
2394                 .withFilter(new AndFilter(andFilters));
2395     }
2396 
2397     private ProjectBuildingRequest getProjectBuildingRequest(MavenProject currentProject) {
2398         return new DefaultProjectBuildingRequest(session.getProjectBuildingRequest())
2399                 .setRemoteRepositories(currentProject.getRemoteArtifactRepositories());
2400     }
2401 
2402     
2403 
2404 
2405 
2406 
2407 
2408 
2409     protected boolean canGenerateReport(Map<Path, Collection<String>> files) {
2410         for (Collection<String> filesValues : files.values()) {
2411             if (!filesValues.isEmpty()) {
2412                 return true;
2413             }
2414         }
2415 
2416         return !(subpackages == null || subpackages.isEmpty());
2417     }
2418 
2419     
2420     
2421     
2422 
2423     
2424 
2425 
2426 
2427 
2428 
2429 
2430 
2431     private String getExcludedPackages(Collection<Path> sourcePaths) throws MavenReportException {
2432         List<String> excludedNames = null;
2433 
2434         if ((sourcepath != null && !sourcepath.isEmpty()) && (subpackages != null && !subpackages.isEmpty())) {
2435             Collection<String> excludedPackages = getExcludedPackages();
2436 
2437             excludedNames = JavadocUtil.getExcludedPackages(sourcePaths, excludedPackages);
2438         }
2439 
2440         String excludeArg = "";
2441         if ((subpackages != null && !subpackages.isEmpty()) && excludedNames != null) {
2442             
2443             excludeArg = StringUtils.join(excludedNames.iterator(), ":");
2444         }
2445 
2446         return excludeArg;
2447     }
2448 
2449     
2450 
2451 
2452 
2453 
2454 
2455 
2456 
2457     private String getSourcePath(Collection<Path> sourcePaths) {
2458         String sourcePath = null;
2459 
2460         if ((subpackages == null || subpackages.isEmpty()) || (sourcepath != null && !sourcepath.isEmpty())) {
2461             sourcePath = StringUtils.join(sourcePaths.iterator(), File.pathSeparator);
2462         }
2463 
2464         return sourcePath;
2465     }
2466 
2467     
2468 
2469 
2470 
2471 
2472 
2473 
2474     private Collection<String> getExcludedPackages() throws MavenReportException {
2475         Set<String> excluded = new LinkedHashSet<>();
2476 
2477         if (includeDependencySources) {
2478             try {
2479                 resolveDependencyBundles();
2480             } catch (IOException e) {
2481                 throw new MavenReportException(
2482                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
2483             }
2484 
2485             if (isNotEmpty(dependencyJavadocBundles)) {
2486                 for (JavadocBundle bundle : dependencyJavadocBundles) {
2487                     JavadocOptions options = bundle.getOptions();
2488                     if (options != null && isNotEmpty(options.getExcludePackageNames())) {
2489                         excluded.addAll(options.getExcludePackageNames());
2490                     }
2491                 }
2492             }
2493         }
2494 
2495         
2496         if (excludePackageNames != null && !excludePackageNames.isEmpty()) {
2497             List<String> packageNames = Arrays.asList(excludePackageNames.split("[,:;]"));
2498             excluded.addAll(trimValues(packageNames));
2499         }
2500 
2501         return excluded;
2502     }
2503 
2504     private static List<String> trimValues(List<String> items) {
2505         List<String> result = new ArrayList<>(items.size());
2506         for (String item : items) {
2507             String trimmed = item.trim();
2508             if (trimmed == null || trimmed.isEmpty()) {
2509                 continue;
2510             }
2511             result.add(trimmed);
2512         }
2513         return result;
2514     }
2515 
2516     private List<org.eclipse.aether.graph.Dependency> toResolverDependencies(List<Dependency> dependencies) {
2517         if (dependencies == null) {
2518             return null;
2519         }
2520         ArtifactTypeRegistry registry = RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager);
2521         return dependencies.stream()
2522                 .map(d -> RepositoryUtils.toDependency(d, registry))
2523                 .collect(Collectors.toList());
2524     }
2525 
2526     
2527 
2528 
2529 
2530 
2531 
2532 
2533 
2534 
2535 
2536     private Collection<File> getPathElements() throws MavenReportException {
2537         Set<File> classpathElements = new LinkedHashSet<>();
2538         Map<String, Artifact> compileArtifactMap = new LinkedHashMap<>();
2539 
2540         if (isTest()) {
2541             classpathElements.addAll(getProjectBuildOutputDirs(project));
2542         }
2543 
2544         populateCompileArtifactMap(compileArtifactMap, project.getArtifacts());
2545 
2546         if (isAggregator()) {
2547             Collection<MavenProject> aggregatorProjects = getAggregatedProjects();
2548 
2549             List<String> reactorArtifacts = new ArrayList<>();
2550             for (MavenProject p : aggregatorProjects) {
2551                 reactorArtifacts.add(p.getGroupId() + ':' + p.getArtifactId());
2552             }
2553 
2554             DependencyFilter dependencyFilter = new AndDependencyFilter(
2555                     new PatternExclusionsDependencyFilter(reactorArtifacts), getDependencyScopeFilter());
2556 
2557             for (MavenProject subProject : aggregatorProjects) {
2558                 if (subProject != project) {
2559                     File projectArtifactFile = getClassesFile(subProject);
2560                     if (projectArtifactFile != null) {
2561                         classpathElements.add(projectArtifactFile);
2562                     } else {
2563                         classpathElements.addAll(getProjectBuildOutputDirs(subProject));
2564                     }
2565 
2566                     try {
2567                         StringBuilder sb = new StringBuilder();
2568 
2569                         sb.append("Compiled artifacts for ");
2570                         sb.append(subProject.getGroupId()).append(":");
2571                         sb.append(subProject.getArtifactId()).append(":");
2572                         sb.append(subProject.getVersion()).append('\n');
2573 
2574                         List<Dependency> managedDependencies = null;
2575                         if (subProject.getDependencyManagement() != null) {
2576                             managedDependencies =
2577                                     subProject.getDependencyManagement().getDependencies();
2578                         }
2579 
2580                         CollectRequest collRequest = new CollectRequest(
2581                                 toResolverDependencies(subProject.getDependencies()),
2582                                 toResolverDependencies(managedDependencies),
2583                                 subProject.getRemoteProjectRepositories());
2584                         DependencyRequest depRequest = new DependencyRequest(collRequest, dependencyFilter);
2585                         for (ArtifactResult artifactResult : repoSystem
2586                                 .resolveDependencies(repoSession, depRequest)
2587                                 .getArtifactResults()) {
2588                             List<Artifact> artifacts =
2589                                     Collections.singletonList(RepositoryUtils.toArtifact(artifactResult.getArtifact()));
2590                             populateCompileArtifactMap(compileArtifactMap, artifacts);
2591 
2592                             sb.append(artifactResult.getArtifact().getFile()).append('\n');
2593                         }
2594 
2595                         if (getLog().isDebugEnabled()) {
2596                             getLog().debug(sb.toString());
2597                         }
2598 
2599                     } catch (DependencyResolutionException e) {
2600                         throw new MavenReportException(e.getMessage(), e);
2601                     }
2602                 }
2603             }
2604         }
2605 
2606         for (Artifact a : compileArtifactMap.values()) {
2607             classpathElements.add(a.getFile());
2608         }
2609 
2610         if (additionalDependencies != null) {
2611             for (Dependency dependency : additionalDependencies) {
2612                 Artifact artifact = resolveDependency(dependency);
2613                 getLog().debug("add additional artifact with path " + artifact.getFile());
2614                 classpathElements.add(artifact.getFile());
2615             }
2616         }
2617 
2618         return classpathElements;
2619     }
2620 
2621     protected ScopeDependencyFilter getDependencyScopeFilter() {
2622         return new ScopeDependencyFilter(
2623                 Arrays.asList(Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM), null);
2624     }
2625 
2626     
2627 
2628 
2629 
2630 
2631     public Artifact resolveDependency(Dependency dependency) throws MavenReportException {
2632         ArtifactTypeRegistry registry = RepositoryUtils.newArtifactTypeRegistry(artifactHandlerManager);
2633         ArtifactRequest req = new ArtifactRequest(
2634                 RepositoryUtils.toDependency(dependency, registry).getArtifact(),
2635                 project.getRemoteProjectRepositories(),
2636                 null);
2637         try {
2638             ArtifactResult resolutionResult = repoSystem.resolveArtifact(repoSession, req);
2639             return RepositoryUtils.toArtifact(resolutionResult.getArtifact());
2640         } catch (ArtifactResolutionException e) {
2641             throw new MavenReportException("artifact resolver problem - " + e.getMessage(), e);
2642         }
2643     }
2644 
2645     protected final Toolchain getToolchain() {
2646         Toolchain tc = null;
2647 
2648         if (jdkToolchain != null) {
2649             List<Toolchain> tcs = toolchainManager.getToolchains(session, "jdk", jdkToolchain);
2650             if (tcs != null && !tcs.isEmpty()) {
2651                 tc = tcs.get(0);
2652             }
2653         }
2654 
2655         if (tc == null) {
2656             tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
2657         }
2658 
2659         return tc;
2660     }
2661 
2662     
2663 
2664 
2665 
2666 
2667 
2668 
2669     private void populateCompileArtifactMap(Map<String, Artifact> compileArtifactMap, Collection<Artifact> artifactList)
2670             throws MavenReportException {
2671         if (artifactList == null) {
2672             return;
2673         }
2674 
2675         for (Artifact newArtifact : artifactList) {
2676             File file = newArtifact.getFile();
2677 
2678             if (file == null) {
2679                 throw new MavenReportException(
2680                         "Error in plugin descriptor - " + "dependency was not resolved for artifact: "
2681                                 + newArtifact.getGroupId() + ":" + newArtifact.getArtifactId() + ":"
2682                                 + newArtifact.getVersion());
2683             }
2684 
2685             if (compileArtifactMap.get(newArtifact.getDependencyConflictId()) != null) {
2686                 Artifact oldArtifact = compileArtifactMap.get(newArtifact.getDependencyConflictId());
2687 
2688                 ArtifactVersion oldVersion = new DefaultArtifactVersion(oldArtifact.getVersion());
2689                 ArtifactVersion newVersion = new DefaultArtifactVersion(newArtifact.getVersion());
2690                 if (newVersion.compareTo(oldVersion) > 0) {
2691                     compileArtifactMap.put(newArtifact.getDependencyConflictId(), newArtifact);
2692                 }
2693             } else {
2694                 compileArtifactMap.put(newArtifact.getDependencyConflictId(), newArtifact);
2695             }
2696         }
2697     }
2698 
2699     
2700 
2701 
2702 
2703 
2704 
2705     private String getBottomText() {
2706         final String inceptionYear = project.getInceptionYear();
2707 
2708         
2709         final LocalDate localDate = MavenArchiver.parseBuildOutputTimestamp(outputTimestamp)
2710                 .map(instant -> instant.atZone(ZoneOffset.UTC).toLocalDate())
2711                 .orElseGet(LocalDate::now);
2712 
2713         final String currentYear = Integer.toString(localDate.getYear());
2714 
2715         String theBottom = StringUtils.replace(this.bottom, "{currentYear}", currentYear);
2716 
2717         if ((inceptionYear == null) || inceptionYear.equals(currentYear)) {
2718             theBottom = StringUtils.replace(theBottom, "{inceptionYear}–", "");
2719         } else {
2720             theBottom = StringUtils.replace(theBottom, "{inceptionYear}", inceptionYear);
2721         }
2722 
2723         if (project.getOrganization() == null) {
2724             theBottom = StringUtils.replace(theBottom, " {organizationName}", "");
2725         } else {
2726             if (StringUtils.isNotEmpty(project.getOrganization().getName())) {
2727                 if (StringUtils.isNotEmpty(project.getOrganization().getUrl())) {
2728                     theBottom = StringUtils.replace(
2729                             theBottom,
2730                             "{organizationName}",
2731                             "<a href=\"" + project.getOrganization().getUrl() + "\">"
2732                                     + project.getOrganization().getName() + "</a>");
2733                 } else {
2734                     theBottom = StringUtils.replace(
2735                             theBottom,
2736                             "{organizationName}",
2737                             project.getOrganization().getName());
2738                 }
2739             } else {
2740                 theBottom = StringUtils.replace(theBottom, " {organizationName}", "");
2741             }
2742         }
2743 
2744         return theBottom;
2745     }
2746 
2747     
2748 
2749 
2750 
2751 
2752 
2753 
2754 
2755 
2756 
2757 
2758 
2759 
2760 
2761 
2762     private Optional<File> getStylesheetFile(final File javadocOutputDirectory) {
2763         if (stylesheetfile == null || stylesheetfile.isEmpty()) {
2764             if ("java".equalsIgnoreCase(stylesheet)) {
2765                 
2766                 return Optional.empty();
2767             }
2768 
2769             getLog().warn("Parameter 'stylesheet' is no longer evaluated, rather use 'addStylesheets'"
2770                     + " to customize the CSS!");
2771             return Optional.empty();
2772         }
2773 
2774         if (new File(stylesheetfile).exists()) {
2775             return Optional.of(new File(stylesheetfile));
2776         }
2777 
2778         return getResource(new File(javadocOutputDirectory, DEFAULT_CSS_NAME), stylesheetfile);
2779     }
2780 
2781     private void addAddStyleSheets(List<String> arguments) throws MavenReportException {
2782         if (addStylesheets == null) {
2783             return;
2784         }
2785 
2786         for (String addStylesheet : addStylesheets) {
2787             Optional<File> styleSheet = getAddStylesheet(getJavadocDirectory(), addStylesheet);
2788 
2789             if (styleSheet.isPresent()) {
2790                 addArgIfNotEmpty(
2791                         arguments,
2792                         "--add-stylesheet",
2793                         JavadocUtil.quotedPathArgument(styleSheet.get().getAbsolutePath()),
2794                         JavaVersion.parse("10"));
2795             }
2796         }
2797     }
2798 
2799     private Optional<File> getAddStylesheet(final File javadocOutputDirectory, final String stylesheet)
2800             throws MavenReportException {
2801         if (stylesheet == null || stylesheet.isEmpty()) {
2802             return Optional.empty();
2803         }
2804 
2805         File addstylesheetfile = new File(getJavadocDirectory(), stylesheet);
2806         if (addstylesheetfile.exists()) {
2807             Optional<File> stylesheetfile = getStylesheetFile(javadocOutputDirectory);
2808             if (stylesheetfile.isPresent()) {
2809                 if (stylesheetfile.get().getName().equals(addstylesheetfile.getName())) {
2810                     throw new MavenReportException("additional stylesheet must have a different name "
2811                             + "than stylesheetfile: " + stylesheetfile.get().getName());
2812                 }
2813             }
2814 
2815             return Optional.of(addstylesheetfile);
2816         }
2817 
2818         throw new MavenReportException(
2819                 "additional stylesheet file does not exist: " + addstylesheetfile.getAbsolutePath());
2820     }
2821 
2822     
2823 
2824 
2825 
2826 
2827 
2828 
2829 
2830 
2831 
2832 
2833 
2834     private Optional<File> getHelpFile(final File javadocOutputDirectory) {
2835         if (helpfile == null || helpfile.isEmpty()) {
2836             return Optional.empty();
2837         }
2838 
2839         if (new File(helpfile).exists()) {
2840             return Optional.of(new File(helpfile));
2841         }
2842 
2843         return getResource(new File(javadocOutputDirectory, "help-doc.html"), helpfile);
2844     }
2845 
2846     
2847 
2848 
2849 
2850 
2851 
2852 
2853     private String getAccessLevel() {
2854         String accessLevel;
2855         if ("public".equalsIgnoreCase(show)
2856                 || "protected".equalsIgnoreCase(show)
2857                 || "package".equalsIgnoreCase(show)
2858                 || "private".equalsIgnoreCase(show)) {
2859             accessLevel = "-" + show;
2860         } else {
2861             if (getLog().isErrorEnabled()) {
2862                 getLog().error("Unrecognized access level to show '" + show + "'. Defaulting to protected.");
2863             }
2864             accessLevel = "-protected";
2865         }
2866 
2867         return accessLevel;
2868     }
2869 
2870     
2871 
2872 
2873 
2874 
2875 
2876 
2877 
2878     private String getBootclassPath() throws MavenReportException {
2879         Set<BootclasspathArtifact> bootclasspathArtifacts = collectBootClasspathArtifacts();
2880 
2881         List<String> bootclassPath = new ArrayList<>();
2882         for (BootclasspathArtifact aBootclasspathArtifact : bootclasspathArtifacts) {
2883             if ((StringUtils.isNotEmpty(aBootclasspathArtifact.getGroupId()))
2884                     && (StringUtils.isNotEmpty(aBootclasspathArtifact.getArtifactId()))
2885                     && (StringUtils.isNotEmpty(aBootclasspathArtifact.getVersion()))) {
2886                 bootclassPath.addAll(getArtifactsAbsolutePath(aBootclasspathArtifact));
2887             }
2888         }
2889 
2890         bootclassPath = JavadocUtil.pruneFiles(bootclassPath);
2891 
2892         StringBuilder path = new StringBuilder();
2893         path.append(StringUtils.join(bootclassPath.iterator(), File.pathSeparator));
2894 
2895         if (bootclasspath != null && !bootclasspath.isEmpty()) {
2896             path.append(JavadocUtil.unifyPathSeparator(bootclasspath));
2897         }
2898 
2899         return path.toString();
2900     }
2901 
2902     
2903 
2904 
2905 
2906 
2907 
2908 
2909 
2910 
2911 
2912 
2913 
2914     private String getDocletPath() throws MavenReportException {
2915         Set<DocletArtifact> docletArtifacts = collectDocletArtifacts();
2916         List<String> pathParts = new ArrayList<>();
2917 
2918         for (DocletArtifact docletArtifact : docletArtifacts) {
2919             if (!isDocletArtifactEmpty(docletArtifact)) {
2920                 pathParts.addAll(getArtifactsAbsolutePath(docletArtifact));
2921             }
2922         }
2923 
2924         if (!(docletPath == null || docletPath.isEmpty())) {
2925             pathParts.add(JavadocUtil.unifyPathSeparator(docletPath));
2926         }
2927 
2928         String path = StringUtils.join(pathParts.iterator(), File.pathSeparator);
2929 
2930         if ((path == null || path.isEmpty()) && getLog().isWarnEnabled()) {
2931             getLog().warn("No docletpath option was found. Please review <docletpath/> or <docletArtifact/>"
2932                     + " or <doclets/>.");
2933         }
2934 
2935         return path;
2936     }
2937 
2938     
2939 
2940 
2941 
2942 
2943 
2944 
2945     private boolean isDocletArtifactEmpty(DocletArtifact aDocletArtifact) {
2946         if (aDocletArtifact == null) {
2947             return true;
2948         }
2949 
2950         return StringUtils.isEmpty(aDocletArtifact.getGroupId())
2951                 && StringUtils.isEmpty(aDocletArtifact.getArtifactId())
2952                 && StringUtils.isEmpty(aDocletArtifact.getVersion());
2953     }
2954 
2955     
2956 
2957 
2958 
2959 
2960 
2961 
2962 
2963     private String getTagletPath() throws MavenReportException {
2964         Set<TagletArtifact> tArtifacts = collectTagletArtifacts();
2965         Collection<String> pathParts = new ArrayList<>();
2966 
2967         for (TagletArtifact tagletArtifact : tArtifacts) {
2968             if ((tagletArtifact != null)
2969                     && (StringUtils.isNotEmpty(tagletArtifact.getGroupId()))
2970                     && (StringUtils.isNotEmpty(tagletArtifact.getArtifactId()))
2971                     && (StringUtils.isNotEmpty(tagletArtifact.getVersion()))) {
2972                 pathParts.addAll(getArtifactsAbsolutePath(tagletArtifact));
2973             }
2974         }
2975 
2976         Set<Taglet> taglets = collectTaglets();
2977         for (Taglet taglet : taglets) {
2978             if (taglet == null) {
2979                 continue;
2980             }
2981 
2982             if ((taglet.getTagletArtifact() != null)
2983                     && (StringUtils.isNotEmpty(taglet.getTagletArtifact().getGroupId()))
2984                     && (StringUtils.isNotEmpty(taglet.getTagletArtifact().getArtifactId()))
2985                     && (StringUtils.isNotEmpty(taglet.getTagletArtifact().getVersion()))) {
2986                 pathParts.addAll(JavadocUtil.pruneFiles(getArtifactsAbsolutePath(taglet.getTagletArtifact())));
2987             } else if (StringUtils.isNotEmpty(taglet.getTagletpath())) {
2988                 for (Path path :
2989                         JavadocUtil.prunePaths(project, Collections.singletonList(taglet.getTagletpath()), true)) {
2990                     pathParts.add(path.toString());
2991                 }
2992             }
2993         }
2994 
2995         if (StringUtils.isNotEmpty(tagletpath)) {
2996             pathParts.addAll(Arrays.asList(JavadocUtil.splitPath(tagletpath)));
2997         }
2998 
2999         return StringUtils.join(pathParts, File.pathSeparator);
3000     }
3001 
3002     private Set<String> collectLinks() throws MavenReportException {
3003         Set<String> links = new LinkedHashSet<>();
3004 
3005         if (includeDependencySources) {
3006             try {
3007                 resolveDependencyBundles();
3008             } catch (IOException e) {
3009                 throw new MavenReportException(
3010                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3011             }
3012 
3013             if (isNotEmpty(dependencyJavadocBundles)) {
3014                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3015                     JavadocOptions options = bundle.getOptions();
3016                     if (options != null && isNotEmpty(options.getLinks())) {
3017                         links.addAll(options.getLinks());
3018                     }
3019                 }
3020             }
3021         }
3022 
3023         if (isNotEmpty(this.links)) {
3024             links.addAll(this.links);
3025         }
3026 
3027         links.addAll(getDependenciesLinks());
3028 
3029         return followLinks(links);
3030     }
3031 
3032     private Set<Group> collectGroups() throws MavenReportException {
3033         Set<Group> groups = new LinkedHashSet<>();
3034 
3035         if (includeDependencySources) {
3036             try {
3037                 resolveDependencyBundles();
3038             } catch (IOException e) {
3039                 throw new MavenReportException(
3040                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3041             }
3042 
3043             if (isNotEmpty(dependencyJavadocBundles)) {
3044                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3045                     JavadocOptions options = bundle.getOptions();
3046                     if (options != null && isNotEmpty(options.getGroups())) {
3047                         groups.addAll(options.getGroups());
3048                     }
3049                 }
3050             }
3051         }
3052 
3053         if (this.groups != null && this.groups.length > 0) {
3054             groups.addAll(Arrays.asList(this.groups));
3055         }
3056 
3057         return groups;
3058     }
3059 
3060     private Set<ResourcesArtifact> collectResourcesArtifacts() throws MavenReportException {
3061         Set<ResourcesArtifact> result = new LinkedHashSet<>();
3062 
3063         if (includeDependencySources) {
3064             try {
3065                 resolveDependencyBundles();
3066             } catch (IOException e) {
3067                 throw new MavenReportException(
3068                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3069             }
3070 
3071             if (isNotEmpty(dependencyJavadocBundles)) {
3072                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3073                     JavadocOptions options = bundle.getOptions();
3074                     if (options != null && isNotEmpty(options.getResourcesArtifacts())) {
3075                         result.addAll(options.getResourcesArtifacts());
3076                     }
3077                 }
3078             }
3079         }
3080 
3081         if (this.resourcesArtifacts != null && this.resourcesArtifacts.length > 0) {
3082             result.addAll(Arrays.asList(this.resourcesArtifacts));
3083         }
3084 
3085         return result;
3086     }
3087 
3088     private Set<BootclasspathArtifact> collectBootClasspathArtifacts() throws MavenReportException {
3089         Set<BootclasspathArtifact> result = new LinkedHashSet<>();
3090 
3091         if (includeDependencySources) {
3092             try {
3093                 resolveDependencyBundles();
3094             } catch (IOException e) {
3095                 throw new MavenReportException(
3096                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3097             }
3098 
3099             if (isNotEmpty(dependencyJavadocBundles)) {
3100                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3101                     JavadocOptions options = bundle.getOptions();
3102                     if (options != null && isNotEmpty(options.getBootclasspathArtifacts())) {
3103                         result.addAll(options.getBootclasspathArtifacts());
3104                     }
3105                 }
3106             }
3107         }
3108 
3109         if (this.bootclasspathArtifacts != null && this.bootclasspathArtifacts.length > 0) {
3110             result.addAll(Arrays.asList(this.bootclasspathArtifacts));
3111         }
3112 
3113         return result;
3114     }
3115 
3116     private Set<OfflineLink> collectOfflineLinks() throws MavenReportException {
3117         Set<OfflineLink> result = new LinkedHashSet<>();
3118 
3119         OfflineLink javaApiLink = getDefaultJavadocApiLink();
3120         if (javaApiLink != null) {
3121             result.add(javaApiLink);
3122         }
3123 
3124         if (includeDependencySources) {
3125             try {
3126                 resolveDependencyBundles();
3127             } catch (IOException e) {
3128                 throw new MavenReportException(
3129                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3130             }
3131 
3132             if (isNotEmpty(dependencyJavadocBundles)) {
3133                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3134                     JavadocOptions options = bundle.getOptions();
3135                     if (options != null && isNotEmpty(options.getOfflineLinks())) {
3136                         result.addAll(options.getOfflineLinks());
3137                     }
3138                 }
3139             }
3140         }
3141 
3142         if (this.offlineLinks != null && this.offlineLinks.length > 0) {
3143             result.addAll(Arrays.asList(this.offlineLinks));
3144         }
3145 
3146         return result;
3147     }
3148 
3149     private Set<Tag> collectTags() throws MavenReportException {
3150         Set<Tag> tags = new LinkedHashSet<>();
3151 
3152         if (includeDependencySources) {
3153             try {
3154                 resolveDependencyBundles();
3155             } catch (IOException e) {
3156                 throw new MavenReportException(
3157                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3158             }
3159 
3160             if (isNotEmpty(dependencyJavadocBundles)) {
3161                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3162                     JavadocOptions options = bundle.getOptions();
3163                     if (options != null && isNotEmpty(options.getTags())) {
3164                         tags.addAll(options.getTags());
3165                     }
3166                 }
3167             }
3168         }
3169 
3170         if (this.tags != null && this.tags.length > 0) {
3171             tags.addAll(Arrays.asList(this.tags));
3172         }
3173 
3174         return tags;
3175     }
3176 
3177     private Set<TagletArtifact> collectTagletArtifacts() throws MavenReportException {
3178         Set<TagletArtifact> tArtifacts = new LinkedHashSet<>();
3179 
3180         if (includeDependencySources) {
3181             try {
3182                 resolveDependencyBundles();
3183             } catch (IOException e) {
3184                 throw new MavenReportException(
3185                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3186             }
3187 
3188             if (isNotEmpty(dependencyJavadocBundles)) {
3189                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3190                     JavadocOptions options = bundle.getOptions();
3191                     if (options != null && isNotEmpty(options.getTagletArtifacts())) {
3192                         tArtifacts.addAll(options.getTagletArtifacts());
3193                     }
3194                 }
3195             }
3196         }
3197 
3198         if (tagletArtifact != null) {
3199             tArtifacts.add(tagletArtifact);
3200         }
3201 
3202         if (tagletArtifacts != null && tagletArtifacts.length > 0) {
3203             tArtifacts.addAll(Arrays.asList(tagletArtifacts));
3204         }
3205 
3206         return tArtifacts;
3207     }
3208 
3209     private Set<DocletArtifact> collectDocletArtifacts() throws MavenReportException {
3210         Set<DocletArtifact> dArtifacts = new LinkedHashSet<>();
3211 
3212         if (includeDependencySources) {
3213             try {
3214                 resolveDependencyBundles();
3215             } catch (IOException e) {
3216                 throw new MavenReportException(
3217                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3218             }
3219 
3220             if (isNotEmpty(dependencyJavadocBundles)) {
3221                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3222                     JavadocOptions options = bundle.getOptions();
3223                     if (options != null && isNotEmpty(options.getDocletArtifacts())) {
3224                         dArtifacts.addAll(options.getDocletArtifacts());
3225                     }
3226                 }
3227             }
3228         }
3229 
3230         if (docletArtifact != null) {
3231             dArtifacts.add(docletArtifact);
3232         }
3233 
3234         if (docletArtifacts != null && docletArtifacts.length > 0) {
3235             dArtifacts.addAll(Arrays.asList(docletArtifacts));
3236         }
3237 
3238         return dArtifacts;
3239     }
3240 
3241     private Set<Taglet> collectTaglets() throws MavenReportException {
3242         Set<Taglet> result = new LinkedHashSet<>();
3243 
3244         if (includeDependencySources) {
3245             try {
3246                 resolveDependencyBundles();
3247             } catch (IOException e) {
3248                 throw new MavenReportException(
3249                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
3250             }
3251 
3252             if (isNotEmpty(dependencyJavadocBundles)) {
3253                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3254                     JavadocOptions options = bundle.getOptions();
3255                     if (options != null && isNotEmpty(options.getTaglets())) {
3256                         result.addAll(options.getTaglets());
3257                     }
3258                 }
3259             }
3260         }
3261 
3262         if (taglets != null && taglets.length > 0) {
3263             result.addAll(Arrays.asList(taglets));
3264         }
3265 
3266         return result;
3267     }
3268 
3269     
3270 
3271 
3272 
3273 
3274 
3275 
3276     private List<String> getArtifactsAbsolutePath(JavadocPathArtifact javadocArtifact) throws MavenReportException {
3277         if ((StringUtils.isEmpty(javadocArtifact.getGroupId()))
3278                 && (StringUtils.isEmpty(javadocArtifact.getArtifactId()))
3279                 && (StringUtils.isEmpty(javadocArtifact.getVersion()))) {
3280             return Collections.emptyList();
3281         }
3282 
3283         List<String> path = new ArrayList<>();
3284 
3285         try {
3286             Artifact artifact = createAndResolveArtifact(javadocArtifact);
3287             path.add(artifact.getFile().getAbsolutePath());
3288 
3289             DependencyFilter filter = new ScopeDependencyFilter(
3290                     Arrays.asList(Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED), Collections.emptySet());
3291             DependencyRequest req = new DependencyRequest(
3292                     new CollectRequest(
3293                             new org.eclipse.aether.graph.Dependency(RepositoryUtils.toArtifact(artifact), null),
3294                             RepositoryUtils.toRepos(project.getRemoteArtifactRepositories())),
3295                     filter);
3296             Iterable<ArtifactResult> deps =
3297                     repoSystem.resolveDependencies(repoSession, req).getArtifactResults();
3298             for (ArtifactResult a : deps) {
3299                 path.add(a.getArtifact().getFile().getAbsolutePath());
3300             }
3301 
3302             return path;
3303         } catch (ArtifactResolutionException e) {
3304             throw new MavenReportException("Unable to resolve artifact:" + javadocArtifact, e);
3305         } catch (DependencyResolutionException e) {
3306             throw new MavenReportException("Unable to resolve dependencies for:" + javadocArtifact, e);
3307         }
3308     }
3309 
3310     
3311 
3312 
3313 
3314 
3315 
3316 
3317 
3318     private Artifact createAndResolveArtifact(JavadocPathArtifact javadocArtifact)
3319             throws org.eclipse.aether.resolution.ArtifactResolutionException {
3320         org.eclipse.aether.artifact.Artifact artifact = new DefaultArtifact(
3321                 javadocArtifact.getGroupId(),
3322                 javadocArtifact.getArtifactId(),
3323                 javadocArtifact.getClassifier(),
3324                 "jar",
3325                 javadocArtifact.getVersion());
3326         ArtifactRequest req = new ArtifactRequest(artifact, project.getRemoteProjectRepositories(), null);
3327         return RepositoryUtils.toArtifact(
3328                 repoSystem.resolveArtifact(repoSession, req).getArtifact());
3329     }
3330 
3331     
3332 
3333 
3334 
3335 
3336 
3337 
3338 
3339     private void addMemoryArg(Commandline cmd, String arg, String memory) {
3340         if (memory != null && !memory.isEmpty()) {
3341             try {
3342                 cmd.createArg().setValue("-J" + arg + JavadocUtil.parseJavadocMemory(memory));
3343             } catch (IllegalArgumentException e) {
3344                 if (getLog().isErrorEnabled()) {
3345                     getLog().error("Malformed memory pattern for '" + arg + memory + "'. Ignore this option.");
3346                 }
3347             }
3348         }
3349     }
3350 
3351     
3352 
3353 
3354 
3355 
3356     private void addProxyArg(Commandline cmd) {
3357         if (settings == null || settings.getProxies().isEmpty()) {
3358             return;
3359         }
3360 
3361         Map<String, Proxy> activeProxies = new HashMap<>();
3362 
3363         for (Proxy proxy : settings.getProxies()) {
3364             if (proxy.isActive()) {
3365                 String protocol = proxy.getProtocol();
3366 
3367                 if (!activeProxies.containsKey(protocol)) {
3368                     activeProxies.put(protocol, proxy);
3369                 }
3370             }
3371         }
3372 
3373         if (activeProxies.containsKey("https")) {
3374             Proxy httpsProxy = activeProxies.get("https");
3375             if (StringUtils.isNotEmpty(httpsProxy.getHost())) {
3376                 cmd.createArg().setValue("-J-Dhttps.proxyHost=" + httpsProxy.getHost());
3377                 cmd.createArg().setValue("-J-Dhttps.proxyPort=" + httpsProxy.getPort());
3378 
3379                 if (StringUtils.isNotEmpty(httpsProxy.getNonProxyHosts())
3380                         && (!activeProxies.containsKey("http")
3381                                 || StringUtils.isEmpty(activeProxies.get("http").getNonProxyHosts()))) {
3382                     cmd.createArg()
3383                             .setValue("-J-Dhttp.nonProxyHosts=\""
3384                                     + httpsProxy.getNonProxyHosts().replace("|", "^|") + "\"");
3385                 }
3386             }
3387         }
3388 
3389         if (activeProxies.containsKey("http")) {
3390             Proxy httpProxy = activeProxies.get("http");
3391             if (StringUtils.isNotEmpty(httpProxy.getHost())) {
3392                 cmd.createArg().setValue("-J-Dhttp.proxyHost=" + httpProxy.getHost());
3393                 cmd.createArg().setValue("-J-Dhttp.proxyPort=" + httpProxy.getPort());
3394 
3395                 if (!activeProxies.containsKey("https")) {
3396                     cmd.createArg().setValue("-J-Dhttps.proxyHost=" + httpProxy.getHost());
3397                     cmd.createArg().setValue("-J-Dhttps.proxyPort=" + httpProxy.getPort());
3398                 }
3399 
3400                 if (StringUtils.isNotEmpty(httpProxy.getNonProxyHosts())) {
3401                     cmd.createArg()
3402                             .setValue("-J-Dhttp.nonProxyHosts=\""
3403                                     + httpProxy.getNonProxyHosts().replace("|", "^|") + "\"");
3404                 }
3405             }
3406         }
3407 
3408         
3409     }
3410 
3411     
3412 
3413 
3414 
3415 
3416 
3417 
3418     private String getJavadocExecutable() throws IOException {
3419         Toolchain tc = getToolchain();
3420 
3421         if (tc != null) {
3422             getLog().info("Toolchain in maven-javadoc-plugin: " + tc);
3423             if (javadocExecutable != null) {
3424                 getLog().warn("Toolchains are ignored, 'javadocExecutable' parameter is set to " + javadocExecutable);
3425             } else {
3426                 javadocExecutable = tc.findTool("javadoc");
3427             }
3428         }
3429 
3430         String javadocCommand = "javadoc" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "");
3431 
3432         File javadocExe;
3433 
3434         
3435         
3436         
3437         if (javadocExecutable != null && !javadocExecutable.isEmpty()) {
3438             javadocExe = new File(javadocExecutable);
3439 
3440             if (javadocExe.isDirectory()) {
3441                 javadocExe = new File(javadocExe, javadocCommand);
3442             }
3443 
3444             if (SystemUtils.IS_OS_WINDOWS && javadocExe.getName().indexOf('.') < 0) {
3445                 javadocExe = new File(javadocExe.getPath() + ".exe");
3446             }
3447 
3448             if (!javadocExe.isFile()) {
3449                 throw new IOException("The javadoc executable '" + javadocExe
3450                         + "' doesn't exist or is not a file. Verify the <javadocExecutable/> parameter.");
3451             }
3452 
3453             return javadocExe.getAbsolutePath();
3454         }
3455         
3456         
3457         
3458         
3459         
3460         
3461         
3462         
3463         
3464         
3465         
3466         
3467         
3468         
3469         
3470         
3471         
3472         
3473         
3474         
3475         
3476         
3477         
3478         
3479         
3480         
3481         
3482         
3483         
3484         
3485         
3486         
3487         
3488         
3489         
3490         if (SystemUtils.IS_OS_AIX) {
3491             javadocExe =
3492                     new File(SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "sh", javadocCommand);
3493         }
3494         
3495         
3496         else if (SystemUtils.IS_OS_MAC_OSX && !JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("1.7"))
3497         
3498         {
3499             javadocExe = new File(SystemUtils.getJavaHome() + File.separator + "bin", javadocCommand);
3500         } else if (isJavaVersionAtLeast(org.apache.commons.lang3.JavaVersion.JAVA_9)) {
3501             javadocExe = new File(SystemUtils.getJavaHome() + File.separator + "bin", javadocCommand);
3502         } else {
3503             
3504             javadocExe = new File(
3505                     SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "bin", javadocCommand);
3506         }
3507 
3508         
3509         
3510         
3511         if (!javadocExe.exists() || !javadocExe.isFile()) {
3512             Properties env = CommandLineUtils.getSystemEnvVars();
3513             String javaHome = env.getProperty("JAVA_HOME");
3514             if (javaHome == null || javaHome.isEmpty()) {
3515                 throw new IOException("The environment variable JAVA_HOME is not correctly set.");
3516             }
3517             if ((!new File(javaHome).getCanonicalFile().exists())
3518                     || (new File(javaHome).getCanonicalFile().isFile())) {
3519                 throw new IOException("The environment variable JAVA_HOME=" + javaHome
3520                         + " doesn't exist or is not a valid directory.");
3521             }
3522 
3523             javadocExe = new File(javaHome + File.separator + "bin", javadocCommand);
3524         }
3525 
3526         if (!javadocExe.getCanonicalFile().exists()
3527                 || !javadocExe.getCanonicalFile().isFile()) {
3528             throw new IOException("The javadoc executable '" + javadocExe
3529                     + "' doesn't exist or is not a file. Verify the JAVA_HOME environment variable.");
3530         }
3531 
3532         return javadocExe.getAbsolutePath();
3533     }
3534 
3535     
3536 
3537 
3538 
3539 
3540 
3541 
3542     private void setFJavadocVersion(File jExecutable) throws MavenReportException {
3543         JavaVersion jVersion;
3544         try {
3545             jVersion = JavadocUtil.getJavadocVersion(jExecutable);
3546         } catch (IOException | CommandLineException | IllegalArgumentException e) {
3547             if (getLog().isWarnEnabled()) {
3548                 getLog().warn("Unable to find the javadoc version: " + e.getMessage());
3549                 getLog().warn("Using the Java version instead of, i.e. " + JAVA_VERSION);
3550             }
3551             jVersion = JAVA_VERSION;
3552         }
3553 
3554         if (javadocVersion != null && !javadocVersion.isEmpty()) {
3555             try {
3556                 javadocRuntimeVersion = JavaVersion.parse(javadocVersion);
3557             } catch (NumberFormatException e) {
3558                 throw new MavenReportException("Unable to parse javadoc version: " + e.getMessage(), e);
3559             }
3560 
3561             if (javadocRuntimeVersion.compareTo(jVersion) != 0 && getLog().isWarnEnabled()) {
3562                 getLog().warn("Are you sure about the <javadocVersion/> parameter? It seems to be " + jVersion);
3563             }
3564         } else {
3565             javadocRuntimeVersion = jVersion;
3566         }
3567     }
3568 
3569     
3570 
3571 
3572 
3573 
3574 
3575 
3576     private boolean isJavaDocVersionAtLeast(JavaVersion requiredVersion) {
3577         return JAVA_VERSION.compareTo(requiredVersion) >= 0;
3578     }
3579 
3580     
3581 
3582 
3583 
3584 
3585 
3586 
3587 
3588     private void addArgIf(List<String> arguments, boolean b, String value) {
3589         if (b) {
3590             arguments.add(value);
3591         }
3592     }
3593 
3594     
3595 
3596 
3597 
3598 
3599 
3600 
3601 
3602 
3603 
3604 
3605     private void addArgIf(List<String> arguments, boolean b, String value, JavaVersion requiredJavaVersion) {
3606         if (b) {
3607             if (isJavaDocVersionAtLeast(requiredJavaVersion)) {
3608                 addArgIf(arguments, true, value);
3609             } else {
3610                 if (getLog().isWarnEnabled()) {
3611                     getLog().warn(value + " option is not supported on Java version < " + requiredJavaVersion
3612                             + ". Ignore this option.");
3613                 }
3614             }
3615         }
3616     }
3617 
3618     
3619 
3620 
3621 
3622 
3623 
3624 
3625 
3626 
3627 
3628 
3629     private void addArgIfNotEmpty(List<String> arguments, String key, String value) {
3630         addArgIfNotEmpty(arguments, key, value, false);
3631     }
3632 
3633     
3634 
3635 
3636 
3637 
3638 
3639 
3640 
3641 
3642 
3643 
3644 
3645 
3646 
3647 
3648     private void addArgIfNotEmpty(
3649             List<String> arguments,
3650             String key,
3651             String value,
3652             boolean repeatKey,
3653             boolean splitValue,
3654             JavaVersion requiredJavaVersion) {
3655         if (value != null && !value.isEmpty()) {
3656             if (isJavaDocVersionAtLeast(requiredJavaVersion)) {
3657                 addArgIfNotEmpty(arguments, key, value, repeatKey, splitValue);
3658             } else {
3659                 if (getLog().isWarnEnabled()) {
3660                     getLog().warn(key + " option is not supported on Java version < " + requiredJavaVersion
3661                             + ". Ignore this option.");
3662                 }
3663             }
3664         }
3665     }
3666 
3667     
3668 
3669 
3670 
3671 
3672 
3673 
3674 
3675 
3676 
3677 
3678 
3679     private void addArgIfNotEmpty(
3680             List<String> arguments, String key, String value, boolean repeatKey, boolean splitValue) {
3681         if (value != null && !value.isEmpty()) {
3682             if (key != null && !key.isEmpty()) {
3683                 arguments.add(key);
3684             }
3685 
3686             if (splitValue) {
3687                 StringTokenizer token = new StringTokenizer(value, ",");
3688                 while (token.hasMoreTokens()) {
3689                     String current = token.nextToken().trim();
3690 
3691                     if (current != null && !current.isEmpty()) {
3692                         arguments.add(current);
3693 
3694                         if (token.hasMoreTokens() && repeatKey) {
3695                             arguments.add(key);
3696                         }
3697                     }
3698                 }
3699             } else {
3700                 arguments.add(value);
3701             }
3702         }
3703     }
3704 
3705     
3706 
3707 
3708 
3709 
3710 
3711 
3712 
3713 
3714 
3715 
3716     private void addArgIfNotEmpty(List<String> arguments, String key, String value, boolean repeatKey) {
3717         addArgIfNotEmpty(arguments, key, value, repeatKey, true);
3718     }
3719 
3720     
3721 
3722 
3723 
3724 
3725 
3726 
3727 
3728 
3729 
3730     private void addArgIfNotEmpty(List<String> arguments, String key, String value, JavaVersion requiredJavaVersion) {
3731         addArgIfNotEmpty(arguments, key, value, requiredJavaVersion, false);
3732     }
3733 
3734     
3735 
3736 
3737 
3738 
3739 
3740 
3741 
3742 
3743 
3744 
3745 
3746     private void addArgIfNotEmpty(
3747             List<String> arguments, String key, String value, JavaVersion requiredJavaVersion, boolean repeatKey) {
3748         if (value != null && !value.isEmpty()) {
3749             if (isJavaDocVersionAtLeast(requiredJavaVersion)) {
3750                 addArgIfNotEmpty(arguments, key, value, repeatKey);
3751             } else {
3752                 if (getLog().isWarnEnabled()) {
3753                     getLog().warn(key + " option is not supported on Java version < " + requiredJavaVersion);
3754                 }
3755             }
3756         }
3757     }
3758 
3759     
3760 
3761 
3762 
3763 
3764 
3765 
3766 
3767 
3768 
3769 
3770 
3771 
3772     private void addLinkofflineArguments(List<String> arguments, Set<OfflineLink> offlineLinksList)
3773             throws MavenReportException {
3774         for (OfflineLink offlineLink : offlineLinksList) {
3775             String url = offlineLink.getUrl();
3776             if (url == null || url.isEmpty()) {
3777                 continue;
3778             }
3779             url = cleanUrl(url);
3780 
3781             String location = offlineLink.getLocation();
3782             if (location == null || location.isEmpty()) {
3783                 continue;
3784             }
3785             if (isValidJavadocLink(location, false)) {
3786                 addArgIfNotEmpty(
3787                         arguments,
3788                         "-linkoffline",
3789                         JavadocUtil.quotedPathArgument(url) + " " + JavadocUtil.quotedPathArgument(location),
3790                         true);
3791             }
3792         }
3793     }
3794 
3795     private Set<OfflineLink> getOfflineLinks() throws MavenReportException {
3796         Set<OfflineLink> offlineLinksList = collectOfflineLinks();
3797 
3798         offlineLinksList.addAll(getModulesLinks());
3799 
3800         return offlineLinksList;
3801     }
3802 
3803     
3804 
3805 
3806 
3807 
3808 
3809 
3810 
3811 
3812 
3813 
3814 
3815 
3816 
3817 
3818 
3819 
3820 
3821 
3822     private void addLinkArguments(List<String> arguments) throws MavenReportException {
3823         Set<String> links = collectLinks();
3824 
3825         for (String link : links) {
3826             if (link == null || link.isEmpty()) {
3827                 continue;
3828             }
3829 
3830             if ((settings.isOffline() || offline) && !link.startsWith("file:")) {
3831                 continue;
3832             }
3833 
3834             while (link.endsWith("/")) {
3835                 link = link.substring(0, link.lastIndexOf("/"));
3836             }
3837 
3838             addArgIfNotEmpty(arguments, "-link", JavadocUtil.quotedPathArgument(link), true, false);
3839         }
3840     }
3841 
3842     
3843 
3844 
3845 
3846 
3847 
3848 
3849 
3850 
3851     private void copyAllResources(File javadocOutputDirectory) throws MavenReportException {
3852 
3853         
3854         
3855         
3856 
3857         if (docfilessubdirs) {
3858             
3859 
3860 
3861 
3862             try {
3863                 copyJavadocResources(javadocOutputDirectory);
3864             } catch (IOException e) {
3865                 throw new MavenReportException("Unable to copy javadoc resources: " + e.getMessage(), e);
3866             }
3867         }
3868 
3869         
3870         
3871         
3872 
3873         copyAdditionalJavadocResources(javadocOutputDirectory);
3874     }
3875 
3876     
3877 
3878 
3879 
3880 
3881 
3882 
3883 
3884 
3885 
3886     private void copyJavadocResources(File anOutputDirectory) throws IOException {
3887         if (anOutputDirectory == null || !anOutputDirectory.exists()) {
3888             throw new IOException("The outputDirectory " + anOutputDirectory + " doesn't exists.");
3889         }
3890 
3891         if (includeDependencySources) {
3892             resolveDependencyBundles();
3893             if (isNotEmpty(dependencyJavadocBundles)) {
3894                 for (JavadocBundle bundle : dependencyJavadocBundles) {
3895                     File dir = bundle.getResourcesDirectory();
3896                     JavadocOptions options = bundle.getOptions();
3897                     if (dir != null && dir.isDirectory()) {
3898                         JavadocUtil.copyJavadocResources(
3899                                 anOutputDirectory, dir, options == null ? null : options.getExcludedDocfilesSubdirs());
3900                     }
3901                 }
3902             }
3903         }
3904 
3905         if (getJavadocDirectory() != null) {
3906             JavadocUtil.copyJavadocResources(anOutputDirectory, getJavadocDirectory(), excludedocfilessubdir);
3907         }
3908 
3909         if (isAggregator()) {
3910             for (MavenProject subProject : getAggregatedProjects()) {
3911                 if (subProject != project && getJavadocDirectory() != null) {
3912                     String javadocDirRelative = PathUtils.toRelative(
3913                             project.getBasedir(), getJavadocDirectory().getAbsolutePath());
3914                     File javadocDir = new File(subProject.getBasedir(), javadocDirRelative);
3915                     JavadocUtil.copyJavadocResources(anOutputDirectory, javadocDir, excludedocfilessubdir);
3916                 }
3917             }
3918         }
3919     }
3920 
3921     private synchronized void resolveDependencyBundles() throws IOException {
3922         if (dependencyJavadocBundles == null) {
3923             dependencyJavadocBundles =
3924                     resourceResolver.resolveDependencyJavadocBundles(getDependencySourceResolverConfig());
3925             if (dependencyJavadocBundles == null) {
3926                 dependencyJavadocBundles = new ArrayList<>();
3927             }
3928         }
3929     }
3930 
3931     
3932 
3933 
3934 
3935 
3936 
3937 
3938     private void copyAdditionalJavadocResources(File anOutputDirectory) throws MavenReportException {
3939         Set<ResourcesArtifact> resourcesArtifacts = collectResourcesArtifacts();
3940         if (isEmpty(resourcesArtifacts)) {
3941             return;
3942         }
3943 
3944         UnArchiver unArchiver;
3945         try {
3946             unArchiver = archiverManager.getUnArchiver("jar");
3947         } catch (NoSuchArchiverException e) {
3948             throw new MavenReportException(
3949                     "Unable to extract resources artifact. " + "No archiver for 'jar' available.", e);
3950         }
3951 
3952         for (ResourcesArtifact item : resourcesArtifacts) {
3953             Artifact artifact;
3954             try {
3955                 artifact = createAndResolveArtifact(item);
3956             } catch (ArtifactResolutionException e) {
3957                 throw new MavenReportException("Unable to resolve artifact:" + item, e);
3958             }
3959 
3960             unArchiver.setSourceFile(artifact.getFile());
3961             unArchiver.setDestDirectory(anOutputDirectory);
3962             
3963             IncludeExcludeFileSelector[] selectors =
3964                     new IncludeExcludeFileSelector[] {new IncludeExcludeFileSelector()};
3965             selectors[0].setExcludes(new String[] {"META-INF/**"});
3966             unArchiver.setFileSelectors(selectors);
3967 
3968             getLog().info("Extracting contents of resources artifact: " + artifact.getArtifactId());
3969             try {
3970                 unArchiver.extract();
3971             } catch (ArchiverException e) {
3972                 throw new MavenReportException(
3973                         "Extraction of resources failed. Artifact that failed was: " + artifact.getArtifactId(), e);
3974             }
3975         }
3976     }
3977 
3978     
3979 
3980 
3981 
3982     private List<String> getPackageNames(Map<Path, Collection<String>> sourcePaths) {
3983         List<String> returnList = new ArrayList<>();
3984 
3985         if (!(sourcepath == null || sourcepath.isEmpty())) {
3986             return returnList;
3987         }
3988 
3989         for (Entry<Path, Collection<String>> currentPathEntry : sourcePaths.entrySet()) {
3990             for (String currentFile : currentPathEntry.getValue()) {
3991                 
3992 
3993 
3994 
3995                 if (currentFile.contains("doc-files")) {
3996                     continue;
3997                 }
3998 
3999                 int lastIndexOfSeparator = currentFile.lastIndexOf("/");
4000                 if (lastIndexOfSeparator != -1) {
4001                     String packagename =
4002                             currentFile.substring(0, lastIndexOfSeparator).replace('/', '.');
4003 
4004                     if (!returnList.contains(packagename)) {
4005                         returnList.add(packagename);
4006                     }
4007                 }
4008             }
4009         }
4010 
4011         return returnList;
4012     }
4013 
4014     
4015 
4016 
4017 
4018 
4019 
4020 
4021     private Collection<String> getPackageNamesRespectingJavaModules(Collection<JavadocModule> javadocModules)
4022             throws MavenReportException {
4023         if (!(sourcepath == null || sourcepath.isEmpty())) {
4024             return Collections.emptyList();
4025         }
4026 
4027         Set<String> returnList = new LinkedHashSet<>();
4028         for (JavadocModule javadocModule : javadocModules) {
4029             Collection<Path> artifactSourcePaths = javadocModule.getSourcePaths();
4030             Set<String> exportedPackages = new HashSet<>();
4031             boolean exportAllPackages;
4032             ResolvePathResult resolvedPath = getResolvePathResult(javadocModule.getArtifactFile());
4033             if (resolvedPath != null && resolvedPath.getModuleNameSource() == ModuleNameSource.MODULEDESCRIPTOR) {
4034                 Set<JavaModuleDescriptor.JavaExports> exports =
4035                         resolvedPath.getModuleDescriptor().exports();
4036                 if (exports.isEmpty()) {
4037                     continue;
4038                 }
4039                 for (JavaModuleDescriptor.JavaExports export : exports) {
4040                     exportedPackages.add(export.source());
4041                 }
4042                 exportAllPackages = false;
4043             } else {
4044                 exportAllPackages = true;
4045             }
4046 
4047             for (Map.Entry<Path, Collection<String>> currentPathEntry :
4048                     getFiles(artifactSourcePaths).entrySet()) {
4049                 for (String currentFile : currentPathEntry.getValue()) {
4050                     
4051 
4052 
4053 
4054                     if (currentFile.contains("doc-files")) {
4055                         continue;
4056                     }
4057 
4058                     int lastIndexOfSeparator = currentFile.lastIndexOf('/');
4059                     if (lastIndexOfSeparator != -1) {
4060                         String packagename =
4061                                 currentFile.substring(0, lastIndexOfSeparator).replace('/', '.');
4062 
4063                         if (exportAllPackages || exportedPackages.contains(packagename)) {
4064                             returnList.add(packagename);
4065                         }
4066                     }
4067                 }
4068             }
4069         }
4070 
4071         return returnList;
4072     }
4073 
4074     
4075 
4076 
4077 
4078     private List<String> getFilesWithUnnamedPackages(Map<Path, Collection<String>> sourcePaths) {
4079         List<String> returnList = new ArrayList<>();
4080 
4081         if (!(sourcepath == null || sourcepath.isEmpty())) {
4082             return returnList;
4083         }
4084 
4085         for (Entry<Path, Collection<String>> currentPathEntry : sourcePaths.entrySet()) {
4086             Path currentSourcePath = currentPathEntry.getKey();
4087 
4088             for (String currentFile : currentPathEntry.getValue()) {
4089                 
4090 
4091 
4092 
4093                 if (currentFile.contains("doc-files")) {
4094                     continue;
4095                 }
4096 
4097                 if (currentFile.indexOf('/') == -1) {
4098                     returnList.add(currentSourcePath
4099                             .resolve(currentFile)
4100                             .toAbsolutePath()
4101                             .toString());
4102                 }
4103             }
4104         }
4105 
4106         return returnList;
4107     }
4108 
4109     
4110 
4111 
4112 
4113 
4114     private List<String> getSpecialFiles(Map<Path, Collection<String>> sourcePaths) {
4115         if (!(sourcepath == null || sourcepath.isEmpty())) {
4116             return new ArrayList<>();
4117         }
4118 
4119         boolean containsModuleDescriptor = false;
4120         for (Collection<String> sourcepathFiles : sourcePaths.values()) {
4121             containsModuleDescriptor = sourcepathFiles.contains("module-info.java");
4122             if (containsModuleDescriptor) {
4123                 break;
4124             }
4125         }
4126 
4127         if (containsModuleDescriptor) {
4128             return getModuleSourcePathFiles(sourcePaths);
4129         } else {
4130             return getFilesWithUnnamedPackages(sourcePaths);
4131         }
4132     }
4133 
4134     private List<String> getModuleSourcePathFiles(Map<Path, Collection<String>> sourcePaths) {
4135         List<String> returnList = new ArrayList<>();
4136 
4137         for (Entry<Path, Collection<String>> currentPathEntry : sourcePaths.entrySet()) {
4138             Path currentSourcePath = currentPathEntry.getKey();
4139             if (currentPathEntry.getValue().contains("module-info.java")) {
4140                 returnList.add(currentSourcePath
4141                         .resolve("module-info.java")
4142                         .toAbsolutePath()
4143                         .toString());
4144             } else {
4145                 for (String currentFile : currentPathEntry.getValue()) {
4146                     
4147 
4148 
4149 
4150                     if (currentFile.contains("doc-files")) {
4151                         continue;
4152                     }
4153 
4154                     returnList.add(currentSourcePath
4155                             .resolve(currentFile)
4156                             .toAbsolutePath()
4157                             .toString());
4158                 }
4159             }
4160         }
4161         return returnList;
4162     }
4163 
4164     
4165 
4166 
4167 
4168 
4169 
4170 
4171 
4172 
4173 
4174 
4175 
4176     private void addCommandLineOptions(Commandline cmd, List<String> arguments, File javadocOutputDirectory)
4177             throws MavenReportException {
4178         File optionsFile = new File(javadocOutputDirectory, OPTIONS_FILE_NAME);
4179 
4180         StringBuilder options = new StringBuilder();
4181         options.append(StringUtils.join(arguments.iterator(), SystemUtils.LINE_SEPARATOR));
4182 
4183         Charset outputFileEncoding;
4184         if (JAVA_VERSION.isAtLeast("9") && JAVA_VERSION.isBefore("12")) {
4185             outputFileEncoding = StandardCharsets.UTF_8;
4186         } else {
4187             outputFileEncoding = Charset.defaultCharset();
4188         }
4189         try {
4190             Files.write(optionsFile.toPath(), Collections.singleton(options), outputFileEncoding);
4191         } catch (IOException e) {
4192             throw new MavenReportException(
4193                     "Unable to write '" + optionsFile.getName() + "' temporary file for command execution", e);
4194         }
4195 
4196         cmd.createArg().setValue("@" + OPTIONS_FILE_NAME);
4197     }
4198 
4199     
4200 
4201 
4202 
4203 
4204 
4205 
4206 
4207 
4208 
4209 
4210 
4211 
4212 
4213 
4214 
4215 
4216 
4217     private void addCommandLineArgFile(Commandline cmd, File javadocOutputDirectory, List<String> files)
4218             throws MavenReportException {
4219         File argfileFile;
4220         if (JAVA_VERSION.compareTo(SINCE_JAVADOC_1_4) >= 0) {
4221             argfileFile = new File(javadocOutputDirectory, ARGFILE_FILE_NAME);
4222             cmd.createArg().setValue("@" + ARGFILE_FILE_NAME);
4223         } else {
4224             argfileFile = new File(javadocOutputDirectory, FILES_FILE_NAME);
4225             cmd.createArg().setValue("@" + FILES_FILE_NAME);
4226         }
4227 
4228         List<String> quotedFiles = new ArrayList<>(files.size());
4229         for (String file : files) {
4230             quotedFiles.add(JavadocUtil.quotedPathArgument(file));
4231         }
4232 
4233         Charset cs;
4234         if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("9")
4235                 && JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("12")) {
4236             cs = StandardCharsets.UTF_8;
4237         } else {
4238             cs = Charset.defaultCharset();
4239         }
4240 
4241         try {
4242             Files.write(argfileFile.toPath(), quotedFiles, cs);
4243         } catch (IOException e) {
4244             throw new MavenReportException(
4245                     "Unable to write '" + argfileFile.getName() + "' temporary file for command execution", e);
4246         }
4247     }
4248 
4249     
4250 
4251 
4252 
4253 
4254 
4255 
4256 
4257 
4258 
4259 
4260 
4261     private void addCommandLinePackages(Commandline cmd, File javadocOutputDirectory, Collection<String> packageNames)
4262             throws MavenReportException {
4263         File packagesFile = new File(javadocOutputDirectory, PACKAGES_FILE_NAME);
4264 
4265         try {
4266             FileUtils.fileWrite(
4267                     packagesFile.getAbsolutePath(),
4268                     null ,
4269                     StringUtils.join(packageNames.iterator(), SystemUtils.LINE_SEPARATOR));
4270         } catch (IOException e) {
4271             throw new MavenReportException(
4272                     "Unable to write '" + packagesFile.getName() + "' temporary file for command execution", e);
4273         }
4274 
4275         cmd.createArg().setValue("@" + PACKAGES_FILE_NAME);
4276     }
4277 
4278     
4279 
4280 
4281 
4282 
4283     private void validateJavadocOptions() throws MavenReportException {
4284         
4285         if (StringUtils.isNotEmpty(getEncoding()) && !JavadocUtil.validateEncoding(getEncoding())) {
4286             throw new MavenReportException("Unsupported option <encoding/> '" + getEncoding() + "'");
4287         }
4288 
4289         
4290         if (StringUtils.isNotEmpty(this.locale)) {
4291             this.locale = siteTool.getSiteLocales(locale).get(0).toString();
4292         }
4293     }
4294 
4295     
4296 
4297 
4298 
4299 
4300 
4301 
4302     private void validateStandardDocletOptions() throws MavenReportException {
4303         
4304         if (StringUtils.isNotEmpty(getDocencoding()) && !JavadocUtil.validateEncoding(getDocencoding())) {
4305             throw new MavenReportException("Unsupported option <docencoding/> '" + getDocencoding() + "'");
4306         }
4307 
4308         
4309         if (StringUtils.isNotEmpty(getCharset()) && !JavadocUtil.validateEncoding(getCharset())) {
4310             throw new MavenReportException("Unsupported option <charset/> '" + getCharset() + "'");
4311         }
4312 
4313         
4314         if ((helpfile != null && !helpfile.isEmpty()) && nohelp) {
4315             throw new MavenReportException("Option <nohelp/> conflicts with <helpfile/>");
4316         }
4317 
4318         
4319         if (getOverview() != null && getOverview().exists() && nooverview) {
4320             throw new MavenReportException("Option <nooverview/> conflicts with <overview/>");
4321         }
4322 
4323         
4324         if (splitindex && noindex) {
4325             throw new MavenReportException("Option <noindex/> conflicts with <splitindex/>");
4326         }
4327 
4328         
4329         if ((stylesheet != null && !stylesheet.isEmpty())
4330                 && !(stylesheet.equalsIgnoreCase("maven") || stylesheet.equalsIgnoreCase("java"))) {
4331             throw new MavenReportException("Option <stylesheet/> supports only \"maven\" or \"java\" value.");
4332         }
4333     }
4334 
4335     
4336 
4337 
4338 
4339 
4340 
4341 
4342 
4343 
4344 
4345 
4346 
4347     private void addJavadocOptions(
4348             File javadocOutputDirectory,
4349             List<String> arguments,
4350             Collection<JavadocModule> allSourcePaths,
4351             Set<OfflineLink> offlineLinks)
4352             throws MavenReportException {
4353         Collection<Path> sourcePaths = allSourcePaths.stream()
4354                 .flatMap(e -> e.getSourcePaths().stream())
4355                 .collect(Collectors.toList());
4356 
4357         validateJavadocOptions();
4358 
4359         
4360         addArgIfNotEmpty(arguments, "-locale", JavadocUtil.quotedArgument(this.locale));
4361 
4362         
4363 
4364         if (old && isJavaDocVersionAtLeast(SINCE_JAVADOC_1_4)) {
4365             if (getLog().isWarnEnabled()) {
4366                 getLog().warn("Javadoc 1.4+ doesn't support the -1.1 switch anymore. Ignore this option.");
4367             }
4368         } else {
4369             addArgIf(arguments, old, "-1.1");
4370         }
4371 
4372         addArgIfNotEmpty(arguments, "-bootclasspath", JavadocUtil.quotedPathArgument(getBootclassPath()));
4373 
4374         if (isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
4375             addArgIf(arguments, breakiterator, "-breakiterator", SINCE_JAVADOC_1_5);
4376         }
4377 
4378         List<MavenProject> aggregatedProjects = reactorProjects; 
4379         Map<String, MavenProject> reactorKeys = new HashMap<>(aggregatedProjects.size());
4380         for (MavenProject reactorProject : aggregatedProjects) {
4381             reactorKeys.put(
4382                     ArtifactUtils.key(
4383                             reactorProject.getGroupId(), reactorProject.getArtifactId(), reactorProject.getVersion()),
4384                     reactorProject);
4385         }
4386 
4387         Map<String, JavaModuleDescriptor> allModuleDescriptors = new HashMap<>();
4388 
4389         
4390         boolean supportModulePath = !legacyMode;
4391 
4392         if (supportModulePath) {
4393             supportModulePath &= javadocRuntimeVersion.isAtLeast("9");
4394             if (release != null) {
4395                 supportModulePath &= JavaVersion.parse(release).isAtLeast("9");
4396             } else if (source != null) {
4397                 supportModulePath &= JavaVersion.parse(source).isAtLeast("9");
4398             }
4399         }
4400 
4401         if (supportModulePath) {
4402             for (JavadocModule entry : allSourcePaths) {
4403                 if (entry.getModuleNameSource() == null || entry.getModuleNameSource() == ModuleNameSource.FILENAME) {
4404                     Path moduleDescriptor = findMainDescriptor(entry.getSourcePaths());
4405 
4406                     if (moduleDescriptor != null) {
4407                         try {
4408                             allModuleDescriptors.put(
4409                                     entry.getGav(),
4410                                     locationManager
4411                                             .parseModuleDescriptor(moduleDescriptor)
4412                                             .getModuleDescriptor());
4413                         } catch (IOException e) {
4414                             throw new MavenReportException(e.getMessage(), e);
4415                         }
4416                     }
4417                 } else {
4418                     allModuleDescriptors.put(entry.getGav(), entry.getModuleDescriptor());
4419                 }
4420             }
4421         }
4422 
4423         Collection<String> additionalModules = new ArrayList<>();
4424 
4425         ResolvePathResult mainResolvePathResult = null;
4426 
4427         Map<String, Collection<Path>> patchModules = new HashMap<>();
4428 
4429         Path moduleSourceDir = null;
4430         if (supportModulePath && !allModuleDescriptors.isEmpty()) {
4431             Collection<String> unnamedProjects = new ArrayList<>();
4432             for (JavadocModule javadocModule : allSourcePaths) {
4433                 MavenProject aggregatedProject = reactorKeys.get(javadocModule.getGav());
4434                 if (aggregatedProject != null && !"pom".equals(aggregatedProject.getPackaging())) {
4435                     ResolvePathResult result = null;
4436 
4437                     
4438                     File artifactFile = getClassesFile(aggregatedProject);
4439                     if (artifactFile != null) {
4440                         ResolvePathRequest<File> request = ResolvePathRequest.ofFile(artifactFile);
4441                         try {
4442                             result = locationManager.resolvePath(request);
4443                         } catch (RuntimeException e) {
4444                             
4445                             if (!"java.lang.module.FindException"
4446                                     .equals(e.getClass().getName())) {
4447                                 throw e;
4448                             }
4449                         } catch (IOException e) {
4450                             throw new MavenReportException(e.getMessage(), e);
4451                         }
4452                     } else {
4453                         Path moduleDescriptor = findMainDescriptor(javadocModule.getSourcePaths());
4454 
4455                         if (moduleDescriptor != null) {
4456                             try {
4457                                 result = locationManager.parseModuleDescriptor(moduleDescriptor);
4458                             } catch (IOException e) {
4459                                 throw new MavenReportException(e.getMessage(), e);
4460                             }
4461                         }
4462                     }
4463 
4464                     if (result != null && result.getModuleDescriptor() != null) {
4465                         moduleSourceDir = javadocOutputDirectory.toPath().resolve("src");
4466                         try {
4467                             moduleSourceDir = Files.createDirectories(moduleSourceDir);
4468 
4469                             additionalModules.add(result.getModuleDescriptor().name());
4470 
4471                             patchModules.put(result.getModuleDescriptor().name(), javadocModule.getSourcePaths());
4472 
4473                             Path modulePath = moduleSourceDir.resolve(
4474                                     result.getModuleDescriptor().name());
4475                             if (!Files.isDirectory(modulePath)) {
4476                                 Files.createDirectory(modulePath);
4477                             }
4478                         } catch (IOException e) {
4479                             throw new MavenReportException(e.getMessage(), e);
4480                         }
4481                     } else {
4482                         unnamedProjects.add(javadocModule.getGav());
4483                     }
4484 
4485                     if (aggregatedProject.equals(getProject())) {
4486                         mainResolvePathResult = result;
4487                     }
4488                 } else {
4489                     
4490                     getLog().error("no reactor project: " + javadocModule.getGav());
4491                 }
4492             }
4493 
4494             if (!unnamedProjects.isEmpty()) {
4495                 getLog().error("Creating an aggregated report for both named and unnamed modules is not possible.");
4496                 getLog().error("Ensure that every module has a module descriptor or is a jar with a MANIFEST.MF "
4497                         + "containing an Automatic-Module-Name.");
4498                 getLog().error("Fix the following projects:");
4499                 for (String unnamedProject : unnamedProjects) {
4500                     getLog().error(" - " + unnamedProject);
4501                 }
4502                 throw new MavenReportException("Aggregator report contains named and unnamed modules");
4503             }
4504 
4505             if (mainResolvePathResult != null
4506                     && ModuleNameSource.MANIFEST.equals(mainResolvePathResult.getModuleNameSource())) {
4507                 arguments.add("--add-modules");
4508                 arguments.add("ALL-MODULE-PATH");
4509             }
4510         }
4511 
4512         
4513         boolean moduleDescriptorSource = false;
4514         for (Path sourcepath : sourcePaths) {
4515             if (Files.isRegularFile(sourcepath.resolve("module-info.java"))) {
4516                 moduleDescriptorSource = true;
4517                 break;
4518             }
4519         }
4520 
4521         final ModuleNameSource mainModuleNameSource;
4522         if (mainResolvePathResult != null) {
4523             mainModuleNameSource = mainResolvePathResult.getModuleNameSource();
4524         } else {
4525             mainModuleNameSource = null;
4526         }
4527 
4528         if (supportModulePath
4529                 && (isAggregator()
4530                         || ModuleNameSource.MODULEDESCRIPTOR.equals(mainModuleNameSource)
4531                         || ModuleNameSource.MANIFEST.equals(mainModuleNameSource))) {
4532             List<File> pathElements = new ArrayList<>(getPathElements());
4533             File artifactFile = getClassesFile(project);
4534             if (artifactFile != null) {
4535                 pathElements.add(0, artifactFile);
4536             }
4537 
4538             ResolvePathsRequest<File> request = ResolvePathsRequest.ofFiles(pathElements);
4539 
4540             String mainModuleName = null;
4541             if (mainResolvePathResult != null) {
4542                 request.setModuleDescriptor(mainResolvePathResult.getModuleDescriptor());
4543                 mainModuleName = mainResolvePathResult.getModuleDescriptor().name();
4544             }
4545 
4546             request.setAdditionalModules(additionalModules);
4547             request.setIncludeStatic(isAggregator());
4548 
4549             try {
4550                 ResolvePathsResult<File> result = locationManager.resolvePaths(request);
4551 
4552                 Set<File> modulePathElements =
4553                         new HashSet<>(result.getModulepathElements().keySet());
4554 
4555                 Collection<File> classPathElements =
4556                         new ArrayList<>(result.getClasspathElements().size());
4557 
4558                 for (File file : result.getClasspathElements()) {
4559                     if (file.isDirectory() && new File(file, "module-info.class").exists()) {
4560                         modulePathElements.add(file);
4561                     } else if (ModuleNameSource.MANIFEST.equals(mainModuleNameSource)) {
4562                         ModuleNameSource depModuleNameSource = locationManager
4563                                 .resolvePath(ResolvePathRequest.ofFile(file))
4564                                 .getModuleNameSource();
4565                         if (ModuleNameSource.MODULEDESCRIPTOR.equals(depModuleNameSource)) {
4566                             modulePathElements.add(file);
4567                         } else {
4568                             patchModules.get(mainModuleName).add(file.toPath());
4569                         }
4570                     } else {
4571                         classPathElements.add(file);
4572                     }
4573                 }
4574 
4575                 
4576                 for (Entry<File, Exception> pathExceptionEntry :
4577                         result.getPathExceptions().entrySet()) {
4578                     Exception exception = pathExceptionEntry.getValue();
4579                     
4580                     if ("java.lang.module.FindException"
4581                             .equals(exception.getClass().getName())) {
4582                         File jarPath = pathExceptionEntry.getKey();
4583                         classPathElements.add(jarPath);
4584                     }
4585                 }
4586 
4587                 String classpath = StringUtils.join(classPathElements.iterator(), File.pathSeparator);
4588                 addArgIfNotEmpty(arguments, "--class-path", JavadocUtil.quotedPathArgument(classpath), false, false);
4589 
4590                 String modulepath = StringUtils.join(modulePathElements.iterator(), File.pathSeparator);
4591                 addArgIfNotEmpty(arguments, "--module-path", JavadocUtil.quotedPathArgument(modulepath), false, false);
4592             } catch (IOException e) {
4593                 throw new MavenReportException(e.getMessage(), e);
4594             }
4595         } else if (supportModulePath && moduleDescriptorSource && !isTest()) {
4596             String modulepath = StringUtils.join(getPathElements().iterator(), File.pathSeparator);
4597             addArgIfNotEmpty(arguments, "--module-path", JavadocUtil.quotedPathArgument(modulepath), false, false);
4598         } else {
4599             String classpath = StringUtils.join(getPathElements().iterator(), File.pathSeparator);
4600             addArgIfNotEmpty(arguments, "-classpath", JavadocUtil.quotedPathArgument(classpath), false, false);
4601         }
4602 
4603         for (Entry<String, Collection<Path>> entry : patchModules.entrySet()) {
4604             if (!entry.getValue().isEmpty()) {
4605                 addArgIfNotEmpty(
4606                         arguments,
4607                         "--patch-module",
4608                         entry.getKey() + '=' + JavadocUtil.quotedPathArgument(getSourcePath(entry.getValue())),
4609                         false,
4610                         false);
4611             }
4612         }
4613 
4614         if (doclet != null && !doclet.isEmpty()) {
4615             addArgIfNotEmpty(arguments, "-doclet", JavadocUtil.quotedArgument(doclet));
4616             addArgIfNotEmpty(arguments, "-docletpath", JavadocUtil.quotedPathArgument(getDocletPath()));
4617         }
4618 
4619         if (encoding == null || encoding.isEmpty()) {
4620             getLog().warn("Source files encoding has not been set, using platform encoding "
4621                     + Charset.defaultCharset().name() + ", i.e. build is platform dependent!");
4622         }
4623         addArgIfNotEmpty(arguments, "-encoding", JavadocUtil.quotedArgument(getEncoding()));
4624 
4625         addArgIfNotEmpty(
4626                 arguments, "-extdirs", JavadocUtil.quotedPathArgument(JavadocUtil.unifyPathSeparator(extdirs)));
4627 
4628         if ((getOverview() != null) && (getOverview().exists())) {
4629             addArgIfNotEmpty(
4630                     arguments,
4631                     "-overview",
4632                     JavadocUtil.quotedPathArgument(getOverview().getAbsolutePath()));
4633         }
4634 
4635         arguments.add(getAccessLevel());
4636 
4637         if (isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
4638             addArgIf(arguments, quiet, "-quiet", SINCE_JAVADOC_1_5);
4639         }
4640 
4641         if (javadocRuntimeVersion.isAtLeast("9") && release != null) {
4642             arguments.add("--release");
4643             arguments.add(release);
4644         } else {
4645             addArgIfNotEmpty(arguments, "-source", JavadocUtil.quotedArgument(source), SINCE_JAVADOC_1_4);
4646         }
4647 
4648         if ((sourcepath == null || sourcepath.isEmpty()) && (subpackages != null && !subpackages.isEmpty())) {
4649             sourcepath = StringUtils.join(sourcePaths.iterator(), File.pathSeparator);
4650         }
4651 
4652         if (moduleSourceDir == null) {
4653             if (!disableSourcepathUsage) {
4654                 addArgIfNotEmpty(
4655                         arguments,
4656                         "-sourcepath",
4657                         JavadocUtil.quotedPathArgument(getSourcePath(sourcePaths)),
4658                         false,
4659                         false);
4660             }
4661 
4662         } else if (mainResolvePathResult == null
4663                 || ModuleNameSource.MODULEDESCRIPTOR.equals(mainResolvePathResult.getModuleNameSource())) {
4664             addArgIfNotEmpty(
4665                     arguments, "--module-source-path", JavadocUtil.quotedPathArgument(moduleSourceDir.toString()));
4666         }
4667 
4668         if ((sourcepath != null && !sourcepath.isEmpty()) && isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
4669             addArgIfNotEmpty(arguments, "-subpackages", subpackages, SINCE_JAVADOC_1_5);
4670         }
4671 
4672         
4673         addArgIfNotEmpty(arguments, "-exclude", getExcludedPackages(sourcePaths), SINCE_JAVADOC_1_4);
4674 
4675         addArgIf(arguments, verbose, "-verbose");
4676 
4677         if (additionalOptions != null) {
4678             for (String additionalOption : additionalOptions) {
4679                 arguments.add(additionalOption.replaceAll("(?<!\\\\)\\\\(?!\\\\|:)", "\\\\"));
4680             }
4681         }
4682     }
4683 
4684     private ResolvePathResult getResolvePathResult(File artifactFile) {
4685         if (artifactFile == null) {
4686             return null;
4687         }
4688 
4689         ResolvePathResult resolvePathResult = null;
4690         ResolvePathRequest<File> resolvePathRequest = ResolvePathRequest.ofFile(artifactFile);
4691         try {
4692             resolvePathResult = locationManager.resolvePath(resolvePathRequest);
4693 
4694             
4695             if (resolvePathResult.getModuleDescriptor() == null) {
4696                 return null;
4697             }
4698         } catch (IOException | RuntimeException  e) {
4699             if (getLog().isDebugEnabled()) {
4700                 Throwable cause = e;
4701                 while (cause.getCause() != null) {
4702                     cause = cause.getCause();
4703                 }
4704 
4705                 getLog().debug("resolve path for: " + artifactFile + " cause error: " + cause);
4706             }
4707         }
4708         return resolvePathResult;
4709     }
4710 
4711     private Path findMainDescriptor(Collection<Path> roots) throws MavenReportException {
4712         for (Map.Entry<Path, Collection<String>> entry : getFiles(roots).entrySet()) {
4713             if (entry.getValue().contains("module-info.java")) {
4714                 return entry.getKey().resolve("module-info.java");
4715             }
4716         }
4717         return null;
4718     }
4719 
4720     
4721 
4722 
4723 
4724 
4725 
4726 
4727 
4728 
4729 
4730 
4731 
4732     private void addStandardDocletOptions(
4733             File javadocOutputDirectory, List<String> arguments, Set<OfflineLink> offlineLinks)
4734             throws MavenReportException {
4735         validateStandardDocletOptions();
4736 
4737         
4738 
4739         addArgIf(arguments, author, "-author");
4740 
4741         addArgIfNotEmpty(arguments, "-bottom", JavadocUtil.quotedArgument(getBottomText()), false, false);
4742 
4743         if (!isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
4744             addArgIf(arguments, breakiterator, "-breakiterator", SINCE_JAVADOC_1_4);
4745         }
4746 
4747         addArgIfNotEmpty(arguments, "-charset", JavadocUtil.quotedArgument(getCharset()));
4748 
4749         addArgIfNotEmpty(arguments, "-d", JavadocUtil.quotedPathArgument(javadocOutputDirectory.toString()));
4750 
4751         addArgIfNotEmpty(arguments, "-docencoding", JavadocUtil.quotedArgument(getDocencoding()));
4752 
4753         addArgIf(arguments, docfilessubdirs, "-docfilessubdirs", SINCE_JAVADOC_1_4);
4754 
4755         addArgIf(arguments, (doclint != null && !doclint.isEmpty()), "-Xdoclint:" + getDoclint(), SINCE_JAVADOC_1_8);
4756 
4757         addArgIfNotEmpty(arguments, "-doctitle", JavadocUtil.quotedArgument(getDoctitle()), false, false);
4758 
4759         if (docfilessubdirs) {
4760             addArgIfNotEmpty(
4761                     arguments,
4762                     "-excludedocfilessubdir",
4763                     JavadocUtil.quotedPathArgument(excludedocfilessubdir),
4764                     SINCE_JAVADOC_1_4);
4765         }
4766 
4767         addArgIfNotEmpty(arguments, "-footer", JavadocUtil.quotedArgument(footer), false, false);
4768 
4769         addGroups(arguments);
4770 
4771         addArgIfNotEmpty(arguments, "-header", JavadocUtil.quotedArgument(header), false, false);
4772 
4773         Optional<File> helpFile = getHelpFile(javadocOutputDirectory);
4774         if (helpFile.isPresent()) {
4775             addArgIfNotEmpty(
4776                     arguments,
4777                     "-helpfile",
4778                     JavadocUtil.quotedPathArgument(helpFile.get().getAbsolutePath()));
4779         }
4780 
4781         addArgIf(arguments, keywords, "-keywords", SINCE_JAVADOC_1_4_2);
4782 
4783         addLinkArguments(arguments);
4784 
4785         addLinkofflineArguments(arguments, offlineLinks);
4786 
4787         addArgIf(arguments, linksource, "-linksource", SINCE_JAVADOC_1_4);
4788 
4789         if (sourcetab > 0) {
4790             if (javadocRuntimeVersion == SINCE_JAVADOC_1_4_2) {
4791                 addArgIfNotEmpty(arguments, "-linksourcetab", String.valueOf(sourcetab));
4792             }
4793             addArgIfNotEmpty(arguments, "-sourcetab", String.valueOf(sourcetab), SINCE_JAVADOC_1_5);
4794         }
4795 
4796         addArgIf(arguments, nocomment, "-nocomment", SINCE_JAVADOC_1_4);
4797 
4798         addArgIf(arguments, nodeprecated, "-nodeprecated");
4799 
4800         addArgIf(arguments, nodeprecatedlist, "-nodeprecatedlist");
4801 
4802         addArgIf(arguments, nohelp, "-nohelp");
4803 
4804         addArgIf(arguments, noindex, "-noindex");
4805 
4806         addArgIf(arguments, nonavbar, "-nonavbar");
4807 
4808         addArgIf(arguments, nooverview, "-nooverview");
4809 
4810         addArgIfNotEmpty(arguments, "-noqualifier", JavadocUtil.quotedArgument(noqualifier), SINCE_JAVADOC_1_4);
4811 
4812         addArgIf(arguments, nosince, "-nosince");
4813 
4814         if (!notimestamp
4815                 && MavenArchiver.parseBuildOutputTimestamp(outputTimestamp).isPresent()) {
4816             
4817             notimestamp = true;
4818         }
4819 
4820         addArgIf(arguments, notimestamp, "-notimestamp", SINCE_JAVADOC_1_5);
4821 
4822         addArgIf(arguments, notree, "-notree");
4823 
4824         addArgIfNotEmpty(arguments, "-packagesheader", JavadocUtil.quotedArgument(packagesheader), SINCE_JAVADOC_1_4_2);
4825 
4826         if (!isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) 
4827         {
4828             addArgIf(arguments, quiet, "-quiet", SINCE_JAVADOC_1_4);
4829         }
4830 
4831         addArgIf(arguments, serialwarn, "-serialwarn");
4832 
4833         addArgIf(arguments, splitindex, "-splitindex");
4834 
4835         Optional<File> stylesheetfile = getStylesheetFile(javadocOutputDirectory);
4836 
4837         if (stylesheetfile.isPresent()) {
4838             addArgIfNotEmpty(
4839                     arguments,
4840                     "-stylesheetfile",
4841                     JavadocUtil.quotedPathArgument(stylesheetfile.get().getAbsolutePath()));
4842         }
4843 
4844         addAddStyleSheets(arguments);
4845 
4846         if ((sourcepath != null && !sourcepath.isEmpty()) && !isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
4847             addArgIfNotEmpty(arguments, "-subpackages", subpackages, SINCE_JAVADOC_1_4);
4848         }
4849 
4850         addArgIfNotEmpty(arguments, "-taglet", JavadocUtil.quotedArgument(taglet), SINCE_JAVADOC_1_4);
4851         addTaglets(arguments);
4852         addTagletsFromTagletArtifacts(arguments);
4853         addArgIfNotEmpty(arguments, "-tagletpath", JavadocUtil.quotedPathArgument(getTagletPath()), SINCE_JAVADOC_1_4);
4854 
4855         addTags(arguments);
4856 
4857         addArgIfNotEmpty(arguments, "-top", JavadocUtil.quotedArgument(top), false, false, SINCE_JAVADOC_1_6);
4858 
4859         addArgIf(arguments, use, "-use");
4860 
4861         addArgIf(arguments, version, "-version");
4862 
4863         addArgIfNotEmpty(arguments, "-windowtitle", JavadocUtil.quotedArgument(getWindowtitle()), false, false);
4864     }
4865 
4866     
4867 
4868 
4869 
4870 
4871 
4872     private void addGroups(List<String> arguments) throws MavenReportException {
4873         Set<Group> groups = collectGroups();
4874         if (isEmpty(groups)) {
4875             return;
4876         }
4877 
4878         for (Group group : groups) {
4879             if (group == null || StringUtils.isEmpty(group.getTitle()) || StringUtils.isEmpty(group.getPackages())) {
4880                 if (getLog().isWarnEnabled()) {
4881                     getLog().warn("A group option is empty. Ignore this option.");
4882                 }
4883             } else {
4884                 String groupTitle = StringUtils.replace(group.getTitle(), ",", ",");
4885                 addArgIfNotEmpty(
4886                         arguments,
4887                         "-group",
4888                         JavadocUtil.quotedArgument(groupTitle) + " " + JavadocUtil.quotedArgument(group.getPackages()),
4889                         true);
4890             }
4891         }
4892     }
4893 
4894     
4895 
4896 
4897 
4898 
4899 
4900     private void addTags(List<String> arguments) throws MavenReportException {
4901         final String lineSeparator;
4902         if (javadocRuntimeVersion.isBefore("9")) {
4903             lineSeparator = " ";
4904         } else {
4905             lineSeparator = " \\\\" + SystemUtils.LINE_SEPARATOR;
4906         }
4907 
4908         for (Tag tag : collectTags()) {
4909             if (StringUtils.isEmpty(tag.getName())) {
4910                 if (getLog().isWarnEnabled()) {
4911                     getLog().warn("A tag name is empty. Ignore this option.");
4912                 }
4913             } else {
4914                 String value = "\"" + tag.getName();
4915                 if (StringUtils.isNotEmpty(tag.getPlacement())) {
4916                     value += ":" + tag.getPlacement().replaceAll("\\R", lineSeparator);
4917                     if (StringUtils.isNotEmpty(tag.getHead())) {
4918                         value += ":" + tag.getHead().replaceAll("\\R", lineSeparator);
4919                     }
4920                 }
4921                 value += "\"";
4922                 addArgIfNotEmpty(arguments, "-tag", value, SINCE_JAVADOC_1_4);
4923             }
4924         }
4925     }
4926 
4927     
4928 
4929 
4930 
4931 
4932     private void addTaglets(List<String> arguments) {
4933         if (taglets == null) {
4934             return;
4935         }
4936 
4937         for (Taglet taglet1 : taglets) {
4938             if ((taglet1 == null) || (StringUtils.isEmpty(taglet1.getTagletClass()))) {
4939                 if (getLog().isWarnEnabled()) {
4940                     getLog().warn("A taglet option is empty. Ignore this option.");
4941                 }
4942             } else {
4943                 addArgIfNotEmpty(
4944                         arguments, "-taglet", JavadocUtil.quotedArgument(taglet1.getTagletClass()), SINCE_JAVADOC_1_4);
4945             }
4946         }
4947     }
4948 
4949     
4950 
4951 
4952 
4953 
4954 
4955 
4956     private void addTagletsFromTagletArtifacts(List<String> arguments) throws MavenReportException {
4957         Set<TagletArtifact> tArtifacts = new LinkedHashSet<>();
4958         if (tagletArtifacts != null && tagletArtifacts.length > 0) {
4959             tArtifacts.addAll(Arrays.asList(tagletArtifacts));
4960         }
4961 
4962         if (includeDependencySources) {
4963             try {
4964                 resolveDependencyBundles();
4965             } catch (IOException e) {
4966                 throw new MavenReportException(
4967                         "Failed to resolve javadoc bundles from dependencies: " + e.getMessage(), e);
4968             }
4969 
4970             if (isNotEmpty(dependencyJavadocBundles)) {
4971                 for (JavadocBundle bundle : dependencyJavadocBundles) {
4972                     JavadocOptions options = bundle.getOptions();
4973                     if (options != null && isNotEmpty(options.getTagletArtifacts())) {
4974                         tArtifacts.addAll(options.getTagletArtifacts());
4975                     }
4976                 }
4977             }
4978         }
4979 
4980         if (isEmpty(tArtifacts)) {
4981             return;
4982         }
4983 
4984         List<String> tagletsPath = new ArrayList<>();
4985 
4986         for (TagletArtifact aTagletArtifact : tArtifacts) {
4987             if ((StringUtils.isNotEmpty(aTagletArtifact.getGroupId()))
4988                     && (StringUtils.isNotEmpty(aTagletArtifact.getArtifactId()))
4989                     && (StringUtils.isNotEmpty(aTagletArtifact.getVersion()))) {
4990                 Artifact artifact;
4991                 try {
4992                     artifact = createAndResolveArtifact(aTagletArtifact);
4993                 } catch (ArtifactResolutionException e) {
4994                     throw new MavenReportException("Unable to resolve artifact:" + aTagletArtifact, e);
4995                 }
4996 
4997                 tagletsPath.add(artifact.getFile().getAbsolutePath());
4998             }
4999         }
5000 
5001         tagletsPath = JavadocUtil.pruneFiles(tagletsPath);
5002 
5003         for (String tagletJar : tagletsPath) {
5004             if (!tagletJar.toLowerCase(Locale.ENGLISH).endsWith(".jar")) {
5005                 continue;
5006             }
5007 
5008             List<String> tagletClasses;
5009             try {
5010                 tagletClasses = JavadocUtil.getTagletClassNames(new File(tagletJar));
5011             } catch (IOException e) {
5012                 if (getLog().isWarnEnabled()) {
5013                     getLog().warn("Unable to auto-detect Taglet class names from '" + tagletJar
5014                             + "'. Try to specify them with <taglets/>.");
5015                 }
5016                 if (getLog().isDebugEnabled()) {
5017                     getLog().debug("IOException: " + e.getMessage(), e);
5018                 }
5019                 continue;
5020             } catch (ClassNotFoundException e) {
5021                 if (getLog().isWarnEnabled()) {
5022                     getLog().warn("Unable to auto-detect Taglet class names from '" + tagletJar
5023                             + "'. Try to specify them with <taglets/>.");
5024                 }
5025                 if (getLog().isDebugEnabled()) {
5026                     getLog().debug("ClassNotFoundException: " + e.getMessage(), e);
5027                 }
5028                 continue;
5029             } catch (NoClassDefFoundError e) {
5030                 if (getLog().isWarnEnabled()) {
5031                     getLog().warn("Unable to auto-detect Taglet class names from '" + tagletJar
5032                             + "'. Try to specify them with <taglets/>.");
5033                 }
5034                 if (getLog().isDebugEnabled()) {
5035                     getLog().debug("NoClassDefFoundError: " + e.getMessage(), e);
5036                 }
5037                 continue;
5038             }
5039 
5040             if (tagletClasses != null && !tagletClasses.isEmpty()) {
5041                 for (String tagletClass : tagletClasses) {
5042                     addArgIfNotEmpty(arguments, "-taglet", JavadocUtil.quotedArgument(tagletClass), SINCE_JAVADOC_1_4);
5043                 }
5044             }
5045         }
5046     }
5047 
5048     
5049 
5050 
5051 
5052 
5053 
5054 
5055     private void executeJavadocCommandLine(Commandline cmd, File javadocOutputDirectory) throws MavenReportException {
5056         if (staleDataPath != null) {
5057             if (!isUpToDate(cmd)) {
5058                 doExecuteJavadocCommandLine(cmd, javadocOutputDirectory);
5059                 StaleHelper.writeStaleData(cmd, staleDataPath.toPath());
5060             }
5061         } else {
5062             doExecuteJavadocCommandLine(cmd, javadocOutputDirectory);
5063         }
5064     }
5065 
5066     
5067 
5068 
5069 
5070 
5071 
5072 
5073     private boolean isUpToDate(Commandline cmd) throws MavenReportException {
5074         try {
5075             List<String> curdata = StaleHelper.getStaleData(cmd);
5076             Path cacheData = staleDataPath.toPath();
5077             List<String> prvdata;
5078             if (Files.isRegularFile(cacheData)) {
5079                 prvdata = Files.lines(cacheData, StandardCharsets.UTF_8).collect(Collectors.toList());
5080             } else {
5081                 prvdata = null;
5082             }
5083             if (curdata.equals(prvdata)) {
5084                 getLog().info("Skipping javadoc generation, everything is up to date.");
5085                 return true;
5086             } else {
5087                 if (prvdata == null) {
5088                     getLog().info("No previous run data found, generating javadoc.");
5089                 } else {
5090                     getLog().info("Configuration changed, re-generating javadoc.");
5091                     if (getLog().isDebugEnabled()) {
5092                         List<String> newStrings = new ArrayList<>(curdata);
5093                         List<String> remStrings = new ArrayList<>(prvdata);
5094                         newStrings.removeAll(prvdata);
5095                         remStrings.removeAll(curdata);
5096                         if (!remStrings.isEmpty()) {
5097                             getLog().debug("     Removed: " + String.join(", ", remStrings));
5098                         }
5099                         if (!newStrings.isEmpty()) {
5100                             getLog().debug("     Added: " + String.join(", ", newStrings));
5101                         }
5102                     }
5103                 }
5104             }
5105         } catch (IOException e) {
5106             throw new MavenReportException("Error checking uptodate status", e);
5107         }
5108         return false;
5109     }
5110 
5111     
5112 
5113 
5114 
5115 
5116 
5117 
5118     private void doExecuteJavadocCommandLine(Commandline cmd, File javadocOutputDirectory) throws MavenReportException {
5119         if (getLog().isDebugEnabled()) {
5120             
5121             getLog().debug(CommandLineUtils.toString(cmd.getCommandline()).replaceAll("'", ""));
5122         }
5123 
5124         String cmdLine = null;
5125         if (debug) {
5126             cmdLine = CommandLineUtils.toString(cmd.getCommandline()).replaceAll("'", "");
5127 
5128             writeDebugJavadocScript(cmdLine, javadocOutputDirectory);
5129         }
5130 
5131         CommandLineUtils.StringStreamConsumer err = new JavadocUtil.JavadocOutputStreamConsumer();
5132         CommandLineUtils.StringStreamConsumer out = new JavadocUtil.JavadocOutputStreamConsumer();
5133         try {
5134             int exitCode = CommandLineUtils.executeCommandLine(cmd, out, err);
5135 
5136             String output = StringUtils.isEmpty(out.getOutput())
5137                     ? null
5138                     : '\n' + out.getOutput().trim();
5139 
5140             if (exitCode != 0) {
5141                 if (cmdLine == null) {
5142                     cmdLine = CommandLineUtils.toString(cmd.getCommandline()).replaceAll("'", "");
5143                 }
5144                 writeDebugJavadocScript(cmdLine, javadocOutputDirectory);
5145 
5146                 if ((output != null && !output.isEmpty())
5147                         && StringUtils.isEmpty(err.getOutput())
5148                         && isJavadocVMInitError(output)) {
5149                     throw new MavenReportException(output + '\n' + '\n' + JavadocUtil.ERROR_INIT_VM + '\n'
5150                             + "Or, try to reduce the Java heap size for the Javadoc goal using "
5151                             + "-Dminmemory=<size> and -Dmaxmemory=<size>." + '\n' + '\n' + "Command line was: "
5152                             + cmdLine
5153                             + '\n' + '\n' + "Refer to the generated Javadoc files in '" + javadocOutputDirectory
5154                             + "' dir.\n");
5155                 }
5156 
5157                 if (output != null && !output.isEmpty()) {
5158                     getLog().info(output);
5159                 }
5160 
5161                 StringBuilder msg = new StringBuilder("\nExit code: ");
5162                 msg.append(exitCode);
5163                 if (StringUtils.isNotEmpty(err.getOutput())) {
5164                     
5165                     List<String> nonInfoLines = new ArrayList<>();
5166                     for (String str : err.getOutput().split("\\R")) {
5167                         if (isInformationalOutput(str)) {
5168                             getLog().debug(str);
5169                         } else {
5170                             nonInfoLines.add(str);
5171                         }
5172                     }
5173                     if (!nonInfoLines.isEmpty()) {
5174                         msg.append('\n'); 
5175                         msg.append(String.join("\n", nonInfoLines));
5176                     }
5177                 }
5178                 msg.append('\n');
5179                 msg.append("Command line was: ").append(cmdLine).append('\n').append('\n');
5180 
5181                 msg.append("Refer to the generated Javadoc files in '")
5182                         .append(javadocOutputDirectory)
5183                         .append("' dir.\n");
5184 
5185                 throw new MavenReportException(msg.toString());
5186             }
5187 
5188             if (output != null && !output.isEmpty()) {
5189                 getLog().info(output);
5190             }
5191         } catch (CommandLineException e) {
5192             throw new MavenReportException("Unable to execute javadoc command: " + e.getMessage(), e);
5193         }
5194 
5195         
5196         
5197         
5198 
5199         if (containsWarnings(err.getOutput())) {
5200             if (getLog().isWarnEnabled()) {
5201                 getLog().warn("Javadoc Warnings");
5202 
5203                 StringTokenizer token = new StringTokenizer(err.getOutput(), "\n");
5204                 while (token.hasMoreTokens()) {
5205                     String current = token.nextToken().trim();
5206 
5207                     
5208                     if (isInformationalOutput(current)) {
5209                         getLog().debug(current);
5210                     } else {
5211                         getLog().warn(current);
5212                     }
5213                 }
5214             }
5215 
5216             if (failOnWarnings) {
5217                 throw new MavenReportException("Project contains Javadoc Warnings");
5218             }
5219         }
5220     }
5221 
5222     private boolean containsWarnings(String output) {
5223         
5224         if (this.javadocRuntimeVersion.isBefore("17")) {
5225             return output != null && !output.isEmpty();
5226         } else {
5227             return Arrays.stream(output.split("\\R"))
5228                     .reduce((first, second) -> second) 
5229                     .filter(line -> line.matches("\\d+ warnings?"))
5230                     .isPresent();
5231         }
5232     }
5233 
5234     
5235 
5236 
5237 
5238 
5239 
5240 
5241 
5242 
5243 
5244 
5245 
5246     private boolean isInformationalOutput(String str) {
5247         return str == null
5248                 || str.trim().isEmpty()
5249                 || str.startsWith("Loading source files for package ") 
5250                 || str.startsWith("Loading source file ") 
5251                 || str.startsWith("Generating ")
5252                 || str.startsWith("Constructing Javadoc information") 
5253                 || str.startsWith("Building index for ")
5254                 || str.startsWith("Building tree for ")
5255                 || str.startsWith("Standard Doclet version ");
5256     }
5257 
5258     
5259 
5260 
5261 
5262 
5263 
5264 
5265 
5266 
5267     private int fixFrameInjectionBug(File javadocOutputDirectory, String outputEncoding) throws IOException {
5268         final String fixData;
5269 
5270         try (InputStream in = this.getClass().getResourceAsStream("frame-injection-fix.txt")) {
5271             if (in == null) {
5272                 throw new FileNotFoundException("Missing resource 'frame-injection-fix.txt' in classpath.");
5273             }
5274             fixData = org.codehaus.plexus.util.StringUtils.unifyLineSeparators(IOUtil.toString(in, "US-ASCII"))
5275                     .trim();
5276         }
5277 
5278         final DirectoryScanner ds = new DirectoryScanner();
5279         ds.setBasedir(javadocOutputDirectory);
5280         ds.setCaseSensitive(false);
5281         ds.setIncludes(new String[] {"**/index.html", "**/index.htm", "**/toc.html", "**/toc.htm"});
5282         ds.addDefaultExcludes();
5283         ds.scan();
5284         int patched = 0;
5285         for (String f : ds.getIncludedFiles()) {
5286             final File file = new File(javadocOutputDirectory, f);
5287             
5288             
5289             final String fileContents = FileUtils.fileRead(file, outputEncoding);
5290             
5291             if (!StringUtils.contains(fileContents, "function validURL(url) {")) {
5292                 
5293                 final String patchedFileContents =
5294                         StringUtils.replaceOnce(fileContents, "function loadFrames() {", fixData);
5295                 if (!patchedFileContents.equals(fileContents)) {
5296                     FileUtils.fileWrite(file, outputEncoding, patchedFileContents);
5297                     patched++;
5298                 }
5299             }
5300         }
5301         return patched;
5302     }
5303 
5304     
5305 
5306 
5307 
5308 
5309 
5310 
5311     private Optional<File> getResource(File outputFile, String inputResourceName) {
5312         if (inputResourceName.startsWith("/")) {
5313             inputResourceName = inputResourceName.replaceFirst("//*", "");
5314         }
5315 
5316         List<String> classPath = new ArrayList<>();
5317         classPath.add(project.getBuild().getSourceDirectory());
5318 
5319         URL resourceURL = getResource(classPath, inputResourceName);
5320         if (resourceURL != null) {
5321             getLog().debug(inputResourceName + " found in the main src directory of the project.");
5322             return Optional.of(FileUtils.toFile(resourceURL));
5323         }
5324 
5325         classPath.clear();
5326         List<Resource> resources = project.getBuild().getResources();
5327         for (Resource resource : resources) {
5328             classPath.add(resource.getDirectory());
5329         }
5330         resourceURL = getResource(classPath, inputResourceName);
5331         if (resourceURL != null) {
5332             getLog().debug(inputResourceName + " found in the main resources directories of the project.");
5333             return Optional.of(FileUtils.toFile(resourceURL));
5334         }
5335 
5336         if (javadocDirectory.exists()) {
5337             classPath.clear();
5338             classPath.add(javadocDirectory.getAbsolutePath());
5339             resourceURL = getResource(classPath, inputResourceName);
5340             if (resourceURL != null) {
5341                 getLog().debug(inputResourceName + " found in the main javadoc directory of the project.");
5342                 return Optional.of(FileUtils.toFile(resourceURL));
5343             }
5344         }
5345 
5346         classPath.clear();
5347         final String pluginId = "org.apache.maven.plugins:maven-javadoc-plugin";
5348         Plugin javadocPlugin = getPlugin(project, pluginId);
5349         if (javadocPlugin != null && javadocPlugin.getDependencies() != null) {
5350             List<Dependency> dependencies = javadocPlugin.getDependencies();
5351             for (Dependency dependency : dependencies) {
5352                 ResourcesArtifact resourceArtifact = new ResourcesArtifact();
5353                 resourceArtifact.setGroupId(dependency.getGroupId());
5354                 resourceArtifact.setArtifactId(dependency.getArtifactId());
5355                 resourceArtifact.setVersion(dependency.getVersion());
5356                 resourceArtifact.setClassifier(dependency.getClassifier());
5357                 Artifact artifact = null;
5358                 try {
5359                     artifact = createAndResolveArtifact(resourceArtifact);
5360                 } catch (Exception e) {
5361                     logError("Unable to retrieve the dependency: " + dependency + ". Ignored.", e);
5362                 }
5363 
5364                 if (artifact != null && artifact.getFile().exists()) {
5365                     classPath.add(artifact.getFile().getAbsolutePath());
5366                 }
5367             }
5368             resourceURL = getResource(classPath, inputResourceName);
5369             if (resourceURL != null) {
5370                 getLog().debug(inputResourceName + " found in javadoc plugin dependencies.");
5371                 try {
5372                     JavadocUtil.copyResource(resourceURL, outputFile);
5373 
5374                     return Optional.of(outputFile);
5375                 } catch (IOException e) {
5376                     logError("IOException: " + e.getMessage(), e);
5377                 }
5378             }
5379         }
5380 
5381         getLog().warn("Unable to find the resource '" + inputResourceName + "'. Using default Javadoc resources.");
5382 
5383         return Optional.empty();
5384     }
5385 
5386     
5387 
5388 
5389 
5390 
5391 
5392 
5393     private URL getResource(final List<String> classPath, final String resource) {
5394         List<URL> urls = new ArrayList<>(classPath.size());
5395         for (String filename : classPath) {
5396             try {
5397                 urls.add(new File(filename).toURI().toURL());
5398             } catch (MalformedURLException | IllegalArgumentException e) {
5399                 getLog().error("MalformedURLException: " + e.getMessage());
5400             }
5401         }
5402 
5403         URLClassLoader javadocClassLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), null);
5404         try {
5405             return javadocClassLoader.getResource(resource);
5406         } finally {
5407             try {
5408                 javadocClassLoader.close();
5409             } catch (IOException ex) {
5410                 
5411             }
5412         }
5413     }
5414 
5415     
5416 
5417 
5418 
5419 
5420     private String getFullJavadocGoal() {
5421         String javadocPluginVersion = null;
5422         String resource = "META-INF/maven/org.apache.maven.plugins/maven-javadoc-plugin/pom.properties";
5423         try (InputStream resourceAsStream =
5424                 AbstractJavadocMojo.class.getClassLoader().getResourceAsStream(resource)) {
5425             if (resourceAsStream != null) {
5426                 Properties properties = new Properties();
5427                 properties.load(resourceAsStream);
5428                 if (StringUtils.isNotEmpty(properties.getProperty("version"))) {
5429                     javadocPluginVersion = properties.getProperty("version");
5430                 }
5431             }
5432         } catch (IOException e) {
5433             
5434         }
5435 
5436         StringBuilder sb = new StringBuilder();
5437 
5438         sb.append("org.apache.maven.plugins:maven-javadoc-plugin:");
5439         if (javadocPluginVersion != null && !javadocPluginVersion.isEmpty()) {
5440             sb.append(javadocPluginVersion).append(":");
5441         }
5442 
5443         if (this instanceof TestJavadocReport) {
5444             sb.append("test-javadoc");
5445         } else {
5446             sb.append("javadoc");
5447         }
5448 
5449         return sb.toString();
5450     }
5451 
5452     
5453 
5454 
5455 
5456 
5457 
5458 
5459 
5460 
5461 
5462     private List<OfflineLink> getModulesLinks() throws MavenReportException {
5463         List<MavenProject> aggregatedProjects = reactorProjects;
5464         if (!detectOfflineLinks || isAggregator() || aggregatedProjects.isEmpty()) {
5465             return Collections.emptyList();
5466         }
5467 
5468         getLog().debug("Trying to add links for modules...");
5469 
5470         Set<String> dependencyArtifactIds = new HashSet<>();
5471         final Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts();
5472         for (Artifact artifact : dependencyArtifacts) {
5473             dependencyArtifactIds.add(artifact.getId());
5474         }
5475 
5476         List<OfflineLink> modulesLinks = new ArrayList<>();
5477         String javadocDirRelative = PathUtils.toRelative(project.getBasedir(), getPluginReportOutputDirectory());
5478         for (MavenProject p : aggregatedProjects) {
5479             if (!dependencyArtifactIds.contains(p.getArtifact().getId()) || (p.getUrl() == null)) {
5480                 continue;
5481             }
5482 
5483             File location = new File(p.getBasedir(), javadocDirRelative);
5484 
5485             if (!location.exists()) {
5486                 if (getLog().isDebugEnabled()) {
5487                     getLog().debug("Javadoc directory not found: " + location);
5488                 }
5489 
5490                 String javadocGoal = getFullJavadocGoal();
5491                 getLog().info("The goal '" + javadocGoal + "' has not been previously called for the module: '"
5492                         + p.getId() + "'. Trying to invoke it...");
5493 
5494                 File invokerDir = new File(project.getBuild().getDirectory(), "invoker");
5495                 invokerDir.mkdirs();
5496                 File invokerLogFile = FileUtils.createTempFile("maven-javadoc-plugin", ".txt", invokerDir);
5497                 try {
5498                     JavadocUtil.invokeMaven(
5499                             getLog(),
5500                             session.getRepositorySession().getLocalRepository().getBasedir(),
5501                             p.getFile(),
5502                             Collections.singletonList(javadocGoal),
5503                             null,
5504                             invokerLogFile,
5505                             session.getRequest().getGlobalSettingsFile(),
5506                             session.getRequest().getUserSettingsFile(),
5507                             session.getRequest().getGlobalToolchainsFile(),
5508                             session.getRequest().getUserToolchainsFile());
5509                 } catch (MavenInvocationException e) {
5510                     logError("MavenInvocationException: " + e.getMessage(), e);
5511 
5512                     String invokerLogContent = JavadocUtil.readFile(invokerLogFile, null );
5513 
5514                     
5515                     
5516                     
5517                     if (invokerLogContent != null && invokerLogContent.contains(JavadocUtil.ERROR_INIT_VM)) {
5518                         throw new MavenReportException(e.getMessage(), e);
5519                     }
5520                 } finally {
5521                     
5522                     if (!location.exists()) {
5523                         getLog().warn("Creating fake javadoc directory to prevent repeated invocations: " + location);
5524                         location.mkdirs();
5525                     }
5526                 }
5527             }
5528 
5529             if (location.exists()) {
5530                 String url = getJavadocLink(p);
5531 
5532                 OfflineLink ol = new OfflineLink();
5533                 ol.setUrl(url);
5534                 ol.setLocation(location.getAbsolutePath());
5535 
5536                 if (getLog().isDebugEnabled()) {
5537                     getLog().debug("Added Javadoc offline link: " + url + " for the module: " + p.getId());
5538                 }
5539 
5540                 modulesLinks.add(ol);
5541             }
5542         }
5543 
5544         return modulesLinks;
5545     }
5546 
5547     
5548 
5549 
5550 
5551 
5552 
5553 
5554 
5555 
5556     private List<String> getDependenciesLinks() {
5557         if (!detectLinks) {
5558             return Collections.emptyList();
5559         }
5560 
5561         getLog().debug("Trying to add links for dependencies...");
5562 
5563         List<String> dependenciesLinks = new ArrayList<>();
5564 
5565         final Set<Artifact> dependencies = project.getDependencyArtifacts();
5566         for (Artifact artifact : dependencies) {
5567             if (artifact.getFile() == null || !artifact.getFile().exists()) {
5568                 continue;
5569             }
5570 
5571             Optional<DependencyLink> depLink = this.dependencyLinks.stream()
5572                     .filter(d -> matches(d, artifact))
5573                     .findAny();
5574 
5575             final String url;
5576             final boolean detected;
5577             if (depLink.isPresent()) {
5578                 url = depLink.get().getUrl();
5579                 detected = false;
5580             } else {
5581                 try {
5582                     MavenProject artifactProject = mavenProjectBuilder
5583                             .build(artifact, getProjectBuildingRequest(project))
5584                             .getProject();
5585 
5586                     url = getJavadocLink(artifactProject);
5587                     detected = true;
5588                 } catch (ProjectBuildingException e) {
5589                     logError("ProjectBuildingException for " + artifact.toString() + ": " + e.getMessage(), e);
5590                     continue;
5591                 }
5592             }
5593 
5594             if (url != null && isValidJavadocLink(url, detected)) {
5595                 getLog().debug("Added Javadoc link: " + url + " for " + artifact.getId());
5596 
5597                 dependenciesLinks.add(url);
5598             }
5599         }
5600 
5601         return dependenciesLinks;
5602     }
5603 
5604     private boolean matches(DependencyLink d, Artifact artifact) {
5605         if (d.getGroupId() != null && !d.getGroupId().equals(artifact.getGroupId())) {
5606             return false;
5607         }
5608         if (d.getArtifactId() != null && !d.getArtifactId().equals(artifact.getArtifactId())) {
5609             return false;
5610         }
5611         if (d.getClassifier() != null && !d.getClassifier().equals(artifact.getClassifier())) {
5612             return false;
5613         }
5614         return true;
5615     }
5616 
5617     
5618 
5619 
5620 
5621 
5622 
5623 
5624 
5625 
5626     protected final OfflineLink getDefaultJavadocApiLink() {
5627         if (!detectJavaApiLink) {
5628             return null;
5629         }
5630 
5631         final JavaVersion javaApiversion;
5632         if (release != null) {
5633             javaApiversion = JavaVersion.parse(release);
5634         } else if (source != null && !source.isEmpty()) {
5635             javaApiversion = JavaVersion.parse(source);
5636         } else {
5637             final String pluginId = "org.apache.maven.plugins:maven-compiler-plugin";
5638             String sourceConfigured = getPluginParameter(project, pluginId, "source");
5639             if (sourceConfigured != null) {
5640                 javaApiversion = JavaVersion.parse(sourceConfigured);
5641             } else {
5642                 getLog().debug("No maven-compiler-plugin defined in ${build.plugins} or in "
5643                         + "${project.build.pluginManagement} for the " + project.getId()
5644                         + ". Added Javadoc API link according the javadoc executable version i.e.: "
5645                         + javadocRuntimeVersion);
5646 
5647                 javaApiversion = javadocRuntimeVersion;
5648             }
5649         }
5650 
5651         final String javaApiKey;
5652         if (javaApiversion.asMajor().isAtLeast("9")) {
5653             javaApiKey = "api_" + javaApiversion.asMajor();
5654         } else {
5655             javaApiKey = "api_1." + javaApiversion.asMajor().toString().charAt(0);
5656         }
5657 
5658         final String javaApiLink;
5659         if (javaApiLinks != null && javaApiLinks.containsKey(javaApiKey)) {
5660             javaApiLink = javaApiLinks.getProperty(javaApiKey);
5661         } else if (javaApiversion.isAtLeast("16")) {
5662             javaApiLink = null; 
5663         } else if (javaApiversion.isAtLeast("11")) {
5664             javaApiLink =
5665                     String.format("https://docs.oracle.com/en/java/javase/%s/docs/api/", javaApiversion.getValue(1));
5666         } else if (javaApiversion.asMajor().isAtLeast("6")) {
5667             javaApiLink = String.format(
5668                     "https://docs.oracle.com/javase/%s/docs/api/",
5669                     javaApiversion.asMajor().getValue(1));
5670         } else if (javaApiversion.isAtLeast("1.5")) {
5671             javaApiLink = "https://docs.oracle.com/javase/1.5.0/docs/api/";
5672         } else {
5673             javaApiLink = null;
5674         }
5675 
5676         if (getLog().isDebugEnabled()) {
5677             if (javaApiLink != null) {
5678                 getLog().debug("Found Java API link: " + javaApiLink);
5679             } else {
5680                 getLog().debug("No Java API link found.");
5681             }
5682         }
5683 
5684         if (javaApiLink == null) {
5685             return null;
5686         }
5687 
5688         final Path javaApiListFile;
5689         final String resourceName;
5690         if (javaApiversion.isAtLeast("10")) {
5691             javaApiListFile = getJavadocOptionsFile().getParentFile().toPath().resolve("element-list");
5692             resourceName = "java-api-element-list-" + javaApiversion.toString().substring(0, 2);
5693         } else if (javaApiversion.asMajor().isAtLeast("9")) {
5694             javaApiListFile = getJavadocOptionsFile().getParentFile().toPath().resolve("package-list");
5695             resourceName = "java-api-package-list-9";
5696         } else {
5697             javaApiListFile = getJavadocOptionsFile().getParentFile().toPath().resolve("package-list");
5698             resourceName = "java-api-package-list-1."
5699                     + javaApiversion.asMajor().toString().charAt(0);
5700         }
5701 
5702         OfflineLink link = new OfflineLink();
5703         link.setLocation(javaApiListFile.getParent().toAbsolutePath().toString());
5704         link.setUrl(javaApiLink);
5705 
5706         InputStream in = this.getClass().getResourceAsStream(resourceName);
5707         if (in != null) {
5708             try (InputStream closableIS = in) {
5709                 
5710                 Files.copy(closableIS, javaApiListFile, StandardCopyOption.REPLACE_EXISTING);
5711             } catch (IOException ioe) {
5712                 logError("Can't get " + resourceName + ": " + ioe.getMessage(), ioe);
5713                 return null;
5714             }
5715         }
5716 
5717         return link;
5718     }
5719 
5720     
5721 
5722 
5723 
5724 
5725 
5726 
5727 
5728     private Set<String> followLinks(Set<String> links) {
5729         if (javadocRuntimeVersion.isAtLeast("12")) {
5730             return links;
5731         }
5732         Set<String> redirectLinks = new LinkedHashSet<>(links.size());
5733         for (String link : links) {
5734             try {
5735                 redirectLinks.add(
5736                         JavadocUtil.getRedirectUrl(new URL(link), settings).toString());
5737             } catch (MalformedURLException | IllegalArgumentException e) {
5738                 
5739                 getLog().debug("Could not follow " + link + ". Reason: " + e.getMessage());
5740             } catch (IOException e) {
5741                 
5742                 getLog().debug("Could not follow " + link + ". Reason: " + e.getMessage());
5743 
5744                 
5745                 
5746                 
5747                 redirectLinks.add(link);
5748             }
5749         }
5750         return redirectLinks;
5751     }
5752 
5753     
5754 
5755 
5756 
5757 
5758 
5759 
5760 
5761 
5762     protected boolean isValidJavadocLink(String link, boolean detecting) {
5763         try {
5764             final URI packageListUri;
5765             final URI elementListUri;
5766 
5767             if (link.trim().toLowerCase(Locale.ENGLISH).startsWith("http:")
5768                     || link.trim().toLowerCase(Locale.ENGLISH).startsWith("https:")
5769                     || link.trim().toLowerCase(Locale.ENGLISH).startsWith("ftp:")
5770                     || link.trim().toLowerCase(Locale.ENGLISH).startsWith("file:")) {
5771                 packageListUri = new URI(link + '/' + PACKAGE_LIST);
5772                 elementListUri = new URI(link + '/' + ELEMENT_LIST);
5773             } else {
5774                 
5775                 File dir = new File(link);
5776                 if (!dir.isAbsolute()) {
5777                     dir = new File(getPluginReportOutputDirectory(), link);
5778                 }
5779                 if (!dir.isDirectory()) {
5780                     if (detecting) {
5781                         getLog().warn("The given File link: " + dir + " is not a dir.");
5782                     } else {
5783                         getLog().error("The given File link: " + dir + " is not a dir.");
5784                     }
5785                 }
5786                 packageListUri = new File(dir, PACKAGE_LIST).toURI();
5787                 elementListUri = new File(dir, ELEMENT_LIST).toURI();
5788             }
5789 
5790             try {
5791                 if (JavadocUtil.isValidElementList(elementListUri.toURL(), settings, validateLinks)) {
5792                     return true;
5793                 }
5794             } catch (IOException e) {
5795                 
5796             }
5797 
5798             if (JavadocUtil.isValidPackageList(packageListUri.toURL(), settings, validateLinks)) {
5799                 return true;
5800             }
5801 
5802             if (getLog().isErrorEnabled()) {
5803                 if (detecting) {
5804                     getLog().warn("Invalid links: " + link + " with /" + PACKAGE_LIST + " or / " + ELEMENT_LIST
5805                             + ". Ignored it.");
5806                 } else {
5807                     getLog().error("Invalid links: " + link + " with /" + PACKAGE_LIST + " or / " + ELEMENT_LIST
5808                             + ". Ignored it.");
5809                 }
5810             }
5811 
5812             return false;
5813         } catch (URISyntaxException | MalformedURLException | IllegalArgumentException e) {
5814             if (getLog().isErrorEnabled()) {
5815                 if (detecting) {
5816                     getLog().warn("Malformed link: " + e.getMessage() + ". Ignored it.");
5817                 } else {
5818                     getLog().error("Malformed link: " + e.getMessage() + ". Ignored it.");
5819                 }
5820             }
5821             return false;
5822         } catch (IOException e) {
5823             if (getLog().isErrorEnabled()) {
5824                 if (detecting) {
5825                     getLog().warn("Error fetching link: " + link + ". Ignored it.");
5826                 } else {
5827                     getLog().error("Error fetching link: " + link + ". Ignored it.");
5828                 }
5829             }
5830             return false;
5831         }
5832     }
5833 
5834     
5835 
5836 
5837 
5838 
5839 
5840 
5841 
5842     private void writeDebugJavadocScript(String cmdLine, File javadocOutputDirectory) {
5843         File commandLineFile = new File(javadocOutputDirectory, DEBUG_JAVADOC_SCRIPT_NAME);
5844         commandLineFile.getParentFile().mkdirs();
5845 
5846         try {
5847             FileUtils.fileWrite(commandLineFile.getAbsolutePath(), null , cmdLine);
5848 
5849             if (!SystemUtils.IS_OS_WINDOWS) {
5850                 Runtime.getRuntime().exec(new String[] {"chmod", "a+x", commandLineFile.getAbsolutePath()});
5851             }
5852         } catch (IOException e) {
5853             logError("Unable to write '" + commandLineFile.getName() + "' debug script file", e);
5854         }
5855     }
5856 
5857     
5858 
5859 
5860 
5861 
5862 
5863 
5864 
5865     private boolean isJavadocVMInitError(String output) {
5866         
5867 
5868 
5869 
5870         return !(output.contains("Javadoc") || output.contains("javadoc"));
5871     }
5872 
5873     
5874     
5875     
5876 
5877     
5878 
5879 
5880 
5881 
5882     private static String getJavadocLink(MavenProject p) {
5883         if (p.getUrl() == null) {
5884             return null;
5885         }
5886 
5887         String url = cleanUrl(p.getUrl());
5888 
5889         return url + "/apidocs";
5890     }
5891 
5892     
5893 
5894 
5895 
5896 
5897     private static String cleanUrl(String url) {
5898         if (url == null) {
5899             return "";
5900         }
5901 
5902         url = url.trim();
5903         while (url.endsWith("/")) {
5904             url = url.substring(0, url.lastIndexOf("/"));
5905         }
5906 
5907         return url;
5908     }
5909 
5910     
5911 
5912 
5913 
5914 
5915 
5916 
5917 
5918     private static Plugin getPlugin(MavenProject p, String pluginId) {
5919         if ((p.getBuild() == null) || (p.getBuild().getPluginsAsMap() == null)) {
5920             return null;
5921         }
5922 
5923         Plugin plugin = p.getBuild().getPluginsAsMap().get(pluginId);
5924 
5925         if ((plugin == null)
5926                 && (p.getBuild().getPluginManagement() != null)
5927                 && (p.getBuild().getPluginManagement().getPluginsAsMap() != null)) {
5928             plugin = p.getBuild().getPluginManagement().getPluginsAsMap().get(pluginId);
5929         }
5930 
5931         return plugin;
5932     }
5933 
5934     
5935 
5936 
5937 
5938 
5939 
5940 
5941 
5942     private static String getPluginParameter(MavenProject p, String pluginId, String param) {
5943         
5944         Plugin plugin = getPlugin(p, pluginId);
5945         if (plugin != null) {
5946             Xpp3Dom xpp3Dom = (Xpp3Dom) plugin.getConfiguration();
5947             if (xpp3Dom != null
5948                     && xpp3Dom.getChild(param) != null
5949                     && StringUtils.isNotEmpty(xpp3Dom.getChild(param).getValue())) {
5950                 return xpp3Dom.getChild(param).getValue();
5951             }
5952         }
5953 
5954         return null;
5955     }
5956 
5957     
5958 
5959 
5960 
5961 
5962 
5963 
5964     protected final File getJavadocOptionsFile() {
5965         if (javadocOptionsDir != null && !javadocOptionsDir.exists()) {
5966             javadocOptionsDir.mkdirs();
5967         }
5968 
5969         return new File(javadocOptionsDir, "javadoc-options-" + getAttachmentClassifier() + ".xml");
5970     }
5971 
5972     
5973 
5974 
5975 
5976 
5977 
5978 
5979 
5980 
5981     protected final JavadocOptions buildJavadocOptions() throws IOException {
5982         JavadocOptions options = new JavadocOptions();
5983 
5984         options.setBootclasspathArtifacts(toList(bootclasspathArtifacts));
5985         options.setDocfilesSubdirsUsed(docfilessubdirs);
5986         options.setDocletArtifacts(toList(docletArtifact, docletArtifacts));
5987         options.setExcludedDocfilesSubdirs(excludedocfilessubdir == null ? null : excludedocfilessubdir.trim());
5988         options.setExcludePackageNames(toList(excludePackageNames));
5989         options.setGroups(toList(groups));
5990         options.setLinks(links);
5991         options.setOfflineLinks(toList(offlineLinks));
5992         options.setResourcesArtifacts(toList(resourcesArtifacts));
5993         options.setTagletArtifacts(toList(tagletArtifact, tagletArtifacts));
5994         options.setTaglets(toList(taglets));
5995         options.setTags(toList(tags));
5996 
5997         if (getProject() != null && getJavadocDirectory() != null) {
5998             options.setJavadocResourcesDirectory(
5999                     toRelative(getProject().getBasedir(), getJavadocDirectory().getAbsolutePath()));
6000         }
6001 
6002         File optionsFile = getJavadocOptionsFile();
6003 
6004         try (Writer writer = WriterFactory.newXmlWriter(optionsFile)) {
6005             new JavadocOptionsXpp3Writer().write(writer, options);
6006         }
6007 
6008         return options;
6009     }
6010 
6011     
6012 
6013 
6014 
6015 
6016     protected String getAttachmentClassifier() {
6017         return JAVADOC_RESOURCES_ATTACHMENT_CLASSIFIER;
6018     }
6019 
6020     
6021 
6022 
6023 
6024 
6025 
6026     protected void logError(String message, Throwable t) {
6027         if (getLog().isDebugEnabled()) {
6028             getLog().error(message, t);
6029         } else {
6030             getLog().error(message);
6031         }
6032     }
6033 
6034     protected List<MavenProject> getReactorProjects() {
6035         return reactorProjects;
6036     }
6037 
6038     
6039 
6040 
6041 
6042 
6043     protected void failOnError(String prefix, Exception e) throws MojoExecutionException {
6044         if (failOnError) {
6045             if (e instanceof RuntimeException) {
6046                 throw (RuntimeException) e;
6047             }
6048             throw new MojoExecutionException(prefix + ": " + e.getMessage(), e);
6049         }
6050 
6051         getLog().error(prefix + ": " + e.getMessage(), e);
6052     }
6053 
6054     
6055 
6056 
6057     private List<MavenProject> getAggregatedProjects() {
6058         if (this.reactorProjects == null) {
6059             return Collections.emptyList();
6060         }
6061         Map<Path, MavenProject> reactorProjectsMap = new HashMap<>();
6062         for (MavenProject reactorProject : this.reactorProjects) {
6063             if (!isSkippedJavadoc(reactorProject)
6064                     && 
6065                     !isSkippedModule(reactorProject)) {
6066                 reactorProjectsMap.put(reactorProject.getBasedir().toPath(), reactorProject);
6067             }
6068         }
6069 
6070         return new ArrayList<>(modulesForAggregatedProject(project, reactorProjectsMap));
6071     }
6072 
6073     
6074 
6075 
6076 
6077     protected boolean isSkippedModule(MavenProject mavenProject) {
6078         if (this.skippedModules == null || this.skippedModules.isEmpty()) {
6079             return false;
6080         }
6081         if (this.patternsToSkip == null) {
6082             this.patternsToSkip = Arrays.stream(StringUtils.split(this.skippedModules, ','))
6083                     .map(String::trim)
6084                     
6085                     
6086                     .map(s -> !s.contains(":") ? ".*:" + s : s)
6087                     .map(Pattern::compile)
6088                     .collect(Collectors.toList());
6089         }
6090         Optional<Pattern> found = this.patternsToSkip.stream()
6091                 .filter(pattern -> pattern.matcher(mavenProject.getGroupId() + ":" + mavenProject.getArtifactId())
6092                         .matches())
6093                 .findAny();
6094         return found.isPresent() || isSkippedJavadoc(mavenProject);
6095     }
6096 
6097     
6098 
6099 
6100 
6101     protected boolean isSkippedJavadoc(MavenProject mavenProject) {
6102         String property = mavenProject.getProperties().getProperty("maven.javadoc.skip");
6103         if (property != null) {
6104             boolean skip = BooleanUtils.toBoolean(property);
6105             getLog().debug("isSkippedJavadoc " + mavenProject + " " + skip);
6106             return skip;
6107         }
6108         final String pluginId = "org.apache.maven.plugins:maven-javadoc-plugin";
6109         property = getPluginParameter(mavenProject, pluginId, "skip");
6110         if (property != null) {
6111             boolean skip = BooleanUtils.toBoolean(property);
6112             getLog().debug("isSkippedJavadoc " + mavenProject + " " + skip);
6113             return skip;
6114         }
6115         if (mavenProject.getParent() != null) {
6116             return isSkippedJavadoc(mavenProject.getParent());
6117         }
6118         getLog().debug("isSkippedJavadoc " + mavenProject + " " + false);
6119         return false;
6120     }
6121 }