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