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