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.ByteArrayOutputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.UnsupportedEncodingException;
30 import java.lang.reflect.Modifier;
31 import java.net.Authenticator;
32 import java.net.PasswordAuthentication;
33 import java.net.URL;
34 import java.net.URLClassLoader;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Properties;
41 import java.util.Set;
42 import java.util.StringTokenizer;
43 import java.util.jar.JarEntry;
44 import java.util.jar.JarInputStream;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
47 import java.util.regex.PatternSyntaxException;
48
49 import org.apache.maven.artifact.Artifact;
50 import org.apache.maven.project.MavenProject;
51 import org.apache.maven.settings.Proxy;
52 import org.apache.maven.settings.Settings;
53 import org.codehaus.plexus.util.FileUtils;
54 import org.codehaus.plexus.util.IOUtil;
55 import org.codehaus.plexus.util.StringUtils;
56 import org.codehaus.plexus.util.cli.CommandLineException;
57 import org.codehaus.plexus.util.cli.CommandLineUtils;
58 import org.codehaus.plexus.util.cli.Commandline;
59
60
61
62
63
64
65
66
67 public class JavadocUtil
68 {
69
70
71
72
73
74
75
76
77
78 protected static List pruneDirs( MavenProject project, List dirs )
79 {
80 List pruned = new ArrayList( dirs.size() );
81 for ( Iterator i = dirs.iterator(); i.hasNext(); )
82 {
83 String dir = (String) i.next();
84
85 if ( dir == null )
86 {
87 continue;
88 }
89
90 File directory = new File( dir );
91 if ( !directory.isAbsolute() )
92 {
93 directory = new File( project.getBasedir(), directory.getPath() );
94 }
95
96 if ( directory.isDirectory() && !pruned.contains( dir ) )
97 {
98 pruned.add( directory.getAbsolutePath() );
99 }
100 }
101
102 return pruned;
103 }
104
105
106
107
108
109
110
111
112 protected static List pruneFiles( List files )
113 {
114 List pruned = new ArrayList( files.size() );
115 for ( Iterator i = files.iterator(); i.hasNext(); )
116 {
117 String f = (String) i.next();
118
119 if ( f == null )
120 {
121 continue;
122 }
123
124 File file = new File( f );
125 if ( file.isFile() && !pruned.contains( f ) )
126 {
127 pruned.add( f );
128 }
129 }
130
131 return pruned;
132 }
133
134
135
136
137
138
139
140
141
142
143 protected static List getExcludedNames( List sourcePaths, String[] subpackagesList, String[] excludedPackages )
144 {
145 List excludedNames = new ArrayList();
146 for ( Iterator i = sourcePaths.iterator(); i.hasNext(); )
147 {
148 String path = (String) i.next();
149 for ( int j = 0; j < subpackagesList.length; j++ )
150 {
151 List excludes = getExcludedPackages( path, excludedPackages );
152 excludedNames.addAll( excludes );
153 }
154 }
155
156 return excludedNames;
157 }
158
159
160
161
162
163
164
165 protected static List getCompileArtifacts( Set artifacts )
166 {
167 return getCompileArtifacts( artifacts, false );
168 }
169
170
171
172
173
174
175
176 protected static List getCompileArtifacts( Set artifacts, boolean withTestScope )
177 {
178 List list = new ArrayList( artifacts.size() );
179
180 for ( Iterator i = artifacts.iterator(); i.hasNext(); )
181 {
182 Artifact a = (Artifact) i.next();
183
184
185 if ( a.getArtifactHandler().isAddedToClasspath() )
186 {
187
188 if ( withTestScope )
189 {
190 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() )
191 || Artifact.SCOPE_PROVIDED.equals( a.getScope() )
192 || Artifact.SCOPE_SYSTEM.equals( a.getScope() )
193 || Artifact.SCOPE_TEST.equals( a.getScope() ) )
194 {
195 list.add( a );
196 }
197 }
198 else
199 {
200 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() )
201 || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
202 {
203 list.add( a );
204 }
205 }
206 }
207 }
208
209 return list;
210 }
211
212
213
214
215
216
217
218
219
220
221 protected static String quotedArgument( String value )
222 {
223 String arg = value;
224
225 if ( StringUtils.isNotEmpty( arg ) )
226 {
227 if ( arg.indexOf( "'" ) != -1 )
228 {
229 arg = StringUtils.replace( arg, "'", "\\'" );
230 }
231 arg = "'" + arg + "'";
232
233
234 arg = StringUtils.replace( arg, "\n", " " );
235 }
236
237 return arg;
238 }
239
240
241
242
243
244
245
246
247 protected static String quotedPathArgument( String value )
248 {
249 String path = value;
250
251 if ( StringUtils.isNotEmpty( path ) )
252 {
253 path = path.replace( '\\', '/' );
254 if ( path.indexOf( "\'" ) != -1 )
255 {
256 String split[] = path.split( "\'" );
257 path = "";
258
259 for ( int i = 0; i < split.length; i++ )
260 {
261 if ( i != split.length - 1 )
262 {
263 path = path + split[i] + "\\'";
264 }
265 else
266 {
267 path = path + split[i];
268 }
269 }
270 }
271 path = "'" + path + "'";
272 }
273
274 return path;
275 }
276
277
278
279
280
281
282
283
284
285
286 protected static void copyJavadocResources( File outputDirectory, File javadocDir )
287 throws IOException
288 {
289 copyJavadocResources( outputDirectory, javadocDir, null );
290 }
291
292
293
294
295
296
297
298
299
300
301
302 protected static void copyJavadocResources( File outputDirectory, File javadocDir, String excludedocfilessubdir )
303 throws IOException
304 {
305 List excludes = new ArrayList();
306 excludes.addAll( Arrays.asList( FileUtils.getDefaultExcludes() ) );
307
308 if ( StringUtils.isNotEmpty( excludedocfilessubdir ) )
309 {
310 StringTokenizer st = new StringTokenizer( excludedocfilessubdir, ":" );
311 String current;
312 while ( st.hasMoreTokens() )
313 {
314 current = st.nextToken();
315 excludes.add( "**/" + current + "/*" );
316 }
317 }
318
319 if ( javadocDir.exists() && javadocDir.isDirectory() )
320 {
321 List docFiles = FileUtils.getDirectoryNames( javadocDir, "**/doc-files", StringUtils.join( excludes
322 .iterator(), "," ), false, true );
323 for ( Iterator it = docFiles.iterator(); it.hasNext(); )
324 {
325 String docFile = (String) it.next();
326
327 File docFileOutput = new File( outputDirectory, docFile );
328 FileUtils.mkdir( docFileOutput.getAbsolutePath() );
329 FileUtils.copyDirectory( new File( javadocDir, docFile ), docFileOutput );
330 }
331 }
332 }
333
334
335
336
337
338
339
340
341
342
343 protected static List getIncludedFiles( File sourceDirectory, String[] fileList, String[] excludePackages )
344 {
345 List files = new ArrayList();
346
347 for ( int j = 0; j < fileList.length; j++ )
348 {
349 boolean include = true;
350 for ( int k = 0; k < excludePackages.length && include; k++ )
351 {
352
353 String[] excludeName = excludePackages[k].split( "[*]" );
354
355 if ( excludeName.length > 1 )
356 {
357 int u = 0;
358 while ( include && u < excludeName.length )
359 {
360 if ( !"".equals( excludeName[u].trim() ) && fileList[j].indexOf( excludeName[u] ) != -1 )
361 {
362 include = false;
363 }
364 u++;
365 }
366 }
367 else
368 {
369 if ( fileList[j].startsWith( sourceDirectory.toString() + File.separatorChar + excludeName[0] ) )
370 {
371 if ( excludeName[0].endsWith( String.valueOf( File.separatorChar ) ) )
372 {
373 int i = fileList[j].lastIndexOf( File.separatorChar );
374 String packageName = fileList[j].substring( 0, i + 1 );
375 File currentPackage = new File( packageName );
376 File excludedPackage = new File( sourceDirectory, excludeName[0] );
377 if ( currentPackage.equals( excludedPackage )
378 && fileList[j].substring( i ).indexOf( ".java" ) != -1 )
379 {
380 include = true;
381 }
382 else
383 {
384 include = false;
385 }
386 }
387 else
388 {
389 include = false;
390 }
391 }
392 }
393 }
394
395 if ( include )
396 {
397 files.add( quotedPathArgument( fileList[j] ) );
398 }
399 }
400
401 return files;
402 }
403
404
405
406
407
408
409
410
411
412 protected static List getExcludedPackages( String sourceDirectory, String[] excludePackagenames )
413 {
414 List files = new ArrayList();
415 for ( int i = 0; i < excludePackagenames.length; i++ )
416 {
417 String[] fileList = FileUtils.getFilesFromExtension( sourceDirectory, new String[] { "java" } );
418 for ( int j = 0; j < fileList.length; j++ )
419 {
420 String[] excludeName = excludePackagenames[i].split( "[*]" );
421 int u = 0;
422 while ( u < excludeName.length )
423 {
424 if ( !"".equals( excludeName[u].trim() ) && fileList[j].indexOf( excludeName[u] ) != -1
425 && sourceDirectory.indexOf( excludeName[u] ) == -1 )
426 {
427 files.add( fileList[j] );
428 }
429 u++;
430 }
431 }
432 }
433
434 List excluded = new ArrayList();
435 for ( Iterator it = files.iterator(); it.hasNext(); )
436 {
437 String file = (String) it.next();
438 int idx = file.lastIndexOf( File.separatorChar );
439 String tmpStr = file.substring( 0, idx );
440 tmpStr = tmpStr.replace( '\\', '/' );
441 String[] srcSplit = tmpStr.split( sourceDirectory.replace( '\\', '/' ) + '/' );
442 String excludedPackage = srcSplit[1].replace( '/', '.' );
443
444 if ( !excluded.contains( excludedPackage ) )
445 {
446 excluded.add( excludedPackage );
447 }
448 }
449
450 return excluded;
451 }
452
453
454
455
456
457
458
459
460 protected static void addFilesFromSource( List files, File sourceDirectory, String[] excludePackages )
461 {
462 String[] fileList = FileUtils.getFilesFromExtension( sourceDirectory.getPath(), new String[] { "java" } );
463 if ( fileList != null && fileList.length != 0 )
464 {
465 List tmpFiles = getIncludedFiles( sourceDirectory, fileList, excludePackages );
466 files.addAll( tmpFiles );
467 }
468 }
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484 protected static float getJavadocVersion( File javadocExe )
485 throws IOException, CommandLineException, IllegalArgumentException, PatternSyntaxException
486 {
487 if ( ( javadocExe == null ) || ( !javadocExe.exists() ) || ( !javadocExe.isFile() ) )
488 {
489 throw new IOException( "The javadoc executable '" + javadocExe + "' doesn't exist or is not a file. " );
490 }
491
492 Commandline cmd = new Commandline();
493 cmd.setExecutable( javadocExe.getAbsolutePath() );
494 cmd.setWorkingDirectory( javadocExe.getParentFile() );
495 cmd.createArg().setValue( "-J-version" );
496
497 CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
498 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
499
500 int exitCode = CommandLineUtils.executeCommandLine( cmd, out, err );
501
502 if ( exitCode != 0 )
503 {
504 StringBuffer msg = new StringBuffer( "Exit code: " + exitCode + " - " + err.getOutput() );
505 msg.append( '\n' );
506 msg.append( "Command line was:" + CommandLineUtils.toString( cmd.getCommandline() ) );
507 throw new CommandLineException( msg.toString() );
508 }
509
510 if ( StringUtils.isNotEmpty( err.getOutput() ) )
511 {
512 return parseJavadocVersion( err.getOutput() );
513 }
514 else if ( StringUtils.isNotEmpty( out.getOutput() ) )
515 {
516 return parseJavadocVersion( out.getOutput() );
517 }
518
519 throw new IllegalArgumentException( "No output found from the command line 'javadoc -J-version'" );
520 }
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563 protected static float parseJavadocVersion( String output )
564 throws IllegalArgumentException, PatternSyntaxException
565 {
566 if ( StringUtils.isEmpty( output ) )
567 {
568 throw new IllegalArgumentException( "The output could not be null." );
569 }
570
571 Pattern pattern = Pattern.compile( "(?s).*?([0-9]+\\.[0-9]+)(\\.([0-9]+))?.*" );
572
573 Matcher matcher = pattern.matcher( output );
574 if ( !matcher.matches() )
575 {
576 throw new PatternSyntaxException( "Unrecognized version of Javadoc: '" + output + "'", pattern.pattern(),
577 pattern.toString().length() - 1 );
578 }
579
580 String version = matcher.group( 3 );
581 if ( version == null )
582 {
583 version = matcher.group( 1 );
584 }
585 else
586 {
587 version = matcher.group( 1 ) + version;
588 }
589
590 return Float.parseFloat( version );
591 }
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622 protected static String parseJavadocMemory( String memory )
623 throws IllegalArgumentException
624 {
625 if ( StringUtils.isEmpty( memory ) )
626 {
627 throw new IllegalArgumentException( "The memory could not be null." );
628 }
629
630 Pattern p = Pattern.compile( "^\\s*(\\d+)\\s*?\\s*$" );
631 Matcher m = p.matcher( memory );
632 if ( m.matches() )
633 {
634 return m.group( 1 ) + "m";
635 }
636
637 p = Pattern.compile( "^\\s*(\\d+)\\s*k(b)?\\s*$", Pattern.CASE_INSENSITIVE );
638 m = p.matcher( memory );
639 if ( m.matches() )
640 {
641 return m.group( 1 ) + "k";
642 }
643
644 p = Pattern.compile( "^\\s*(\\d+)\\s*m(b)?\\s*$", Pattern.CASE_INSENSITIVE );
645 m = p.matcher( memory );
646 if ( m.matches() )
647 {
648 return m.group( 1 ) + "m";
649 }
650
651 p = Pattern.compile( "^\\s*(\\d+)\\s*g(b)?\\s*$", Pattern.CASE_INSENSITIVE );
652 m = p.matcher( memory );
653 if ( m.matches() )
654 {
655 return ( Integer.parseInt( m.group( 1 ) ) * 1024 ) + "m";
656 }
657
658 p = Pattern.compile( "^\\s*(\\d+)\\s*t(b)?\\s*$", Pattern.CASE_INSENSITIVE );
659 m = p.matcher( memory );
660 if ( m.matches() )
661 {
662 return ( Integer.parseInt( m.group( 1 ) ) * 1024 * 1024 ) + "m";
663 }
664
665 throw new IllegalArgumentException( "Could convert not to a memory size: " + memory );
666 }
667
668
669
670
671
672
673
674
675 protected static void fetchURL( Settings settings, URL url )
676 throws IOException
677 {
678 if ( url == null )
679 {
680 throw new IOException( "The url is null" );
681 }
682
683 Properties oldSystemProperties = new Properties();
684 oldSystemProperties.putAll( System.getProperties() );
685
686 if ( settings != null )
687 {
688 String scheme = url.getProtocol();
689
690 if ( !"file".equals( scheme ) )
691 {
692 Proxy activeProxy = settings.getActiveProxy();
693 if ( activeProxy != null )
694 {
695 if ( "http".equals( scheme ) || "https".equals( scheme ) || "ftp".equals( scheme ) )
696 {
697 scheme += ".";
698 }
699 else
700 {
701 scheme = "";
702 }
703
704 if ( StringUtils.isNotEmpty( activeProxy.getHost() ) )
705 {
706 Properties systemProperties = System.getProperties();
707 systemProperties.setProperty( scheme + "proxySet", "true" );
708 systemProperties.setProperty( scheme + "proxyHost", activeProxy.getHost() );
709
710 if ( activeProxy.getPort() > 0 )
711 {
712 systemProperties
713 .setProperty( scheme + "proxyPort", String.valueOf( activeProxy.getPort() ) );
714 }
715
716 if ( StringUtils.isNotEmpty( activeProxy.getNonProxyHosts() ) )
717 {
718 systemProperties.setProperty( scheme + "nonProxyHosts", activeProxy.getNonProxyHosts() );
719 }
720
721 final String userName = activeProxy.getUsername();
722 if ( StringUtils.isNotEmpty( userName ) )
723 {
724 final String pwd = StringUtils.isEmpty( activeProxy.getPassword() ) ? "" : activeProxy
725 .getPassword();
726 Authenticator.setDefault( new Authenticator()
727 {
728 protected PasswordAuthentication getPasswordAuthentication()
729 {
730 return new PasswordAuthentication( userName, pwd.toCharArray() );
731 }
732 } );
733 }
734 }
735 }
736 }
737 }
738
739 InputStream in = null;
740 try
741 {
742 in = url.openStream();
743 }
744 finally
745 {
746 IOUtil.close( in );
747
748
749 if ( ( settings != null ) && ( !"file".equals( url.getProtocol() ) )
750 && ( settings.getActiveProxy() != null )
751 && ( StringUtils.isNotEmpty( settings.getActiveProxy().getHost() ) ) )
752 {
753 System.setProperties( oldSystemProperties );
754 Authenticator.setDefault( null );
755 }
756 }
757 }
758
759
760
761
762
763
764
765 protected static boolean validateEncoding( String charsetName )
766 {
767 if ( StringUtils.isEmpty( charsetName ) )
768 {
769 return false;
770 }
771
772 OutputStream ost = new ByteArrayOutputStream();
773 OutputStreamWriter osw = null;
774 try
775 {
776 osw = new OutputStreamWriter( ost, charsetName );
777 }
778 catch ( UnsupportedEncodingException exc )
779 {
780 return false;
781 }
782 finally
783 {
784 IOUtil.close( osw );
785 }
786 return true;
787 }
788
789
790
791
792
793
794
795
796
797 protected static String hideProxyPassword( String cmdLine, Settings settings )
798 {
799 if ( cmdLine == null )
800 {
801 throw new IllegalArgumentException( "cmdLine could not be null" );
802 }
803
804 if ( settings == null )
805 {
806 return cmdLine;
807 }
808
809 Proxy activeProxy = settings.getActiveProxy();
810 if ( activeProxy != null && StringUtils.isNotEmpty( activeProxy.getHost() )
811 && StringUtils.isNotEmpty( activeProxy.getUsername() )
812 && StringUtils.isNotEmpty( activeProxy.getPassword() ) )
813 {
814 String pass = "-J-Dhttp.proxyPassword=\"" + activeProxy.getPassword() + "\"";
815 String hidepass =
816 "-J-Dhttp.proxyPassword=\"" + StringUtils.repeat( "*", activeProxy.getPassword().length() ) + "\"";
817
818 return StringUtils.replace( cmdLine, pass, hidepass );
819 }
820
821 return cmdLine;
822 }
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838 protected static List getTagletClassNames( File jarFile )
839 throws IOException, ClassNotFoundException, NoClassDefFoundError
840 {
841 List classes = getClassNamesFromJar( jarFile );
842 ClassLoader cl;
843
844
845 File tools = new File( System.getProperty( "java.home" ), "../lib/tools.jar" );
846 if ( tools.exists() && tools.isFile() )
847 {
848 cl = new URLClassLoader( new URL[] { jarFile.toURI().toURL(), tools.toURI().toURL() }, null );
849 }
850 else
851 {
852 cl = new URLClassLoader( new URL[] { jarFile.toURI().toURL() }, null );
853 }
854
855 List tagletClasses = new ArrayList();
856
857 Class tagletClass = cl.loadClass( "com.sun.tools.doclets.Taglet" );
858 for ( Iterator it = classes.iterator(); it.hasNext(); )
859 {
860 String s = (String) it.next();
861
862 Class c = cl.loadClass( s );
863
864 if ( tagletClass.isAssignableFrom( c ) && !Modifier.isAbstract( c.getModifiers() ) )
865 {
866 tagletClasses.add( c.getName() );
867 }
868 }
869
870 return tagletClasses;
871 }
872
873
874
875
876
877
878
879
880
881
882 private static List getClassNamesFromJar( File jarFile )
883 throws IOException
884 {
885 if ( jarFile == null || !jarFile.exists() || !jarFile.isFile() )
886 {
887 throw new IOException( "The jar '" + jarFile + "' doesn't exist or is not a file." );
888 }
889
890 List classes = new ArrayList();
891 JarInputStream jarStream = null;
892
893 try
894 {
895 jarStream = new JarInputStream( new FileInputStream( jarFile ) );
896 JarEntry jarEntry = jarStream.getNextJarEntry();
897 while ( jarEntry != null )
898 {
899 if ( jarEntry == null )
900 {
901 break;
902 }
903
904 if ( jarEntry.getName().toLowerCase( Locale.ENGLISH ).endsWith( ".class" ) )
905 {
906 String name = jarEntry.getName().substring( 0, jarEntry.getName().indexOf( "." ) );
907
908 classes.add( name.replaceAll( "/", "\\." ) );
909 }
910
911 jarStream.closeEntry();
912 jarEntry = jarStream.getNextJarEntry();
913 }
914 }
915 finally
916 {
917 IOUtil.close( jarStream );
918 }
919
920 return classes;
921 }
922 }