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