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