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