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