1 package org.apache.maven.shared.verifier;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.FileReader;
27 import java.io.FilenameFilter;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.nio.charset.Charset;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Properties;
41 import java.util.StringTokenizer;
42 import java.util.regex.Pattern;
43
44 import javax.xml.parsers.ParserConfigurationException;
45 import javax.xml.parsers.SAXParser;
46 import javax.xml.parsers.SAXParserFactory;
47
48 import org.apache.maven.shared.utils.StringUtils;
49 import org.apache.maven.shared.utils.io.FileUtils;
50 import org.xml.sax.InputSource;
51 import org.xml.sax.SAXException;
52 import org.xml.sax.SAXParseException;
53 import org.xml.sax.helpers.DefaultHandler;
54
55
56
57
58
59 public class Verifier
60 {
61 private static final String LOG_FILENAME = "log.txt";
62
63 private static final String[] DEFAULT_CLI_ARGUMENTS = {"-e", "--batch-mode"};
64
65
66
67
68
69
70 private static final String CLEAN_CLI_ARGUMENT = "org.apache.maven.plugins:maven-clean-plugin:clean";
71
72 private String localRepo;
73
74 private final String basedir;
75
76 private final String[] defaultCliArguments;
77
78 private List<String> cliArguments = new ArrayList<>();
79
80 private Properties systemProperties = new Properties();
81
82 private Map<String, String> environmentVariables = new HashMap<>();
83
84 private Properties verifierProperties = new Properties();
85
86 private boolean autoclean = true;
87
88 private String localRepoLayout = "default";
89
90
91
92
93
94 private Boolean forkJvm;
95
96 private String logFileName = LOG_FILENAME;
97
98 private String mavenHome;
99
100
101 private boolean mavenDebug = false;
102
103
104
105
106
107
108
109
110 private String forkMode;
111
112 private boolean debugJvm = false;
113
114 private boolean useWrapper;
115
116 private static MavenLauncher embeddedLauncher;
117
118 public Verifier( String basedir )
119 throws VerificationException
120 {
121 this( basedir, null );
122 }
123
124 public Verifier( String basedir, boolean debug )
125 throws VerificationException
126 {
127 this( basedir, null, debug );
128 }
129
130 public Verifier( String basedir, String settingsFile )
131 throws VerificationException
132 {
133 this( basedir, settingsFile, false );
134 }
135
136 public Verifier( String basedir, String settingsFile, boolean debug )
137 throws VerificationException
138 {
139 this( basedir, settingsFile, debug, DEFAULT_CLI_ARGUMENTS );
140 }
141
142 public Verifier( String basedir, String settingsFile, boolean debug, String[] defaultCliArguments )
143 throws VerificationException
144 {
145 this( basedir, settingsFile, debug, null, defaultCliArguments );
146 }
147
148 public Verifier( String basedir, String settingsFile, boolean debug, boolean forkJvm )
149 throws VerificationException
150 {
151 this( basedir, settingsFile, debug, forkJvm, DEFAULT_CLI_ARGUMENTS );
152 }
153
154 public Verifier( String basedir, String settingsFile, boolean debug, boolean forkJvm, String[] defaultCliArguments )
155 throws VerificationException
156 {
157 this( basedir, settingsFile, debug, forkJvm, defaultCliArguments, null );
158 }
159
160 public Verifier( String basedir, String settingsFile, boolean debug, String mavenHome )
161 throws VerificationException
162 {
163 this( basedir, settingsFile, debug, null, DEFAULT_CLI_ARGUMENTS, mavenHome );
164 }
165
166 public Verifier( String basedir, String settingsFile, boolean debug, String mavenHome,
167 String[] defaultCliArguments )
168 throws VerificationException
169 {
170 this( basedir, settingsFile, debug, null, defaultCliArguments, mavenHome );
171 }
172
173 private Verifier( String basedir, String settingsFile, boolean debug, Boolean forkJvm, String[] defaultCliArguments,
174 String mavenHome ) throws VerificationException
175 {
176 this.basedir = basedir;
177
178 this.forkJvm = forkJvm;
179 this.forkMode = System.getProperty( "verifier.forkMode" );
180
181 findLocalRepo( settingsFile );
182 if ( mavenHome == null )
183 {
184 this.mavenHome = System.getProperty( "maven.home" );
185 useWrapper = Files.exists( Paths.get( getBasedir(), "mvnw" ) );
186 }
187 else
188 {
189 this.mavenHome = mavenHome;
190 useWrapper = false;
191 }
192
193 if ( StringUtils.isEmpty( mavenHome ) && StringUtils.isEmpty( forkMode ) )
194 {
195 forkMode = "auto";
196 }
197
198 this.defaultCliArguments = defaultCliArguments == null ? new String[0] : defaultCliArguments.clone();
199 }
200
201 public void setLocalRepo( String localRepo )
202 {
203 this.localRepo = localRepo;
204 }
205
206
207
208
209 @Deprecated
210 public void resetStreams()
211 {
212 }
213
214
215
216
217
218 @Deprecated
219 public void displayStreamBuffers()
220 {
221 }
222
223
224
225
226
227 public void verify( boolean chokeOnErrorOutput )
228 throws VerificationException
229 {
230 List<String> lines = loadFile( getBasedir(), "expected-results.txt", false );
231
232 for ( String line : lines )
233 {
234 verifyExpectedResult( line );
235 }
236
237 if ( chokeOnErrorOutput )
238 {
239 verifyErrorFreeLog();
240 }
241 }
242
243 public void verifyErrorFreeLog()
244 throws VerificationException
245 {
246 List<String> lines = loadFile( getBasedir(), getLogFileName(), false );
247
248 for ( String line : lines )
249 {
250
251 if ( stripAnsi( line ).contains( "[ERROR]" ) && !isVelocityError( line ) )
252 {
253 throw new VerificationException( "Error in execution: " + line );
254 }
255 }
256 }
257
258
259
260
261
262
263
264
265 private static boolean isVelocityError( String line )
266 {
267 return line.contains( "VM_global_library.vm" ) || line.contains( "VM #" ) && line.contains( "macro" );
268 }
269
270
271
272
273
274
275
276 public void verifyTextInLog( String text )
277 throws VerificationException
278 {
279 List<String> lines = loadFile( getBasedir(), getLogFileName(), false );
280
281 boolean result = false;
282 for ( String line : lines )
283 {
284 if ( stripAnsi( line ).contains( text ) )
285 {
286 result = true;
287 break;
288 }
289 }
290 if ( !result )
291 {
292 throw new VerificationException( "Text not found in log: " + text );
293 }
294 }
295
296 public static String stripAnsi( String msg )
297 {
298 return msg.replaceAll( "\u001B\\[[;\\d]*[ -/]*[@-~]", "" );
299 }
300
301 public Properties loadProperties( String filename )
302 throws VerificationException
303 {
304 Properties properties = new Properties();
305
306 File propertiesFile = new File( getBasedir(), filename );
307 try ( FileInputStream fis = new FileInputStream( propertiesFile ) )
308 {
309 properties.load( fis );
310 }
311 catch ( IOException e )
312 {
313 throw new VerificationException( "Error reading properties file", e );
314 }
315
316 return properties;
317 }
318
319
320
321
322
323
324
325
326
327
328
329 public List<String> loadLines( String filename, String encoding )
330 throws IOException
331 {
332 List<String> lines = new ArrayList<>();
333
334 try ( BufferedReader reader = getReader( filename, encoding ) )
335 {
336 String line;
337 while ( ( line = reader.readLine() ) != null )
338 {
339 if ( line.length() > 0 )
340 {
341 lines.add( line );
342 }
343 }
344 }
345
346 return lines;
347 }
348
349 private BufferedReader getReader( String filename, String encoding ) throws IOException
350 {
351 File file = new File( getBasedir(), filename );
352
353 if ( StringUtils.isNotEmpty( encoding ) )
354 {
355 return Files.newBufferedReader( file.toPath(), Charset.forName( encoding ) );
356 }
357 else
358 {
359 return Files.newBufferedReader( file.toPath() );
360 }
361 }
362
363 public List<String> loadFile( String basedir, String filename, boolean hasCommand )
364 throws VerificationException
365 {
366 return loadFile( new File( basedir, filename ), hasCommand );
367 }
368
369 public List<String> loadFile( File file, boolean hasCommand )
370 throws VerificationException
371 {
372 List<String> lines = new ArrayList<>();
373
374 if ( file.exists() )
375 {
376 try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) )
377 {
378 String line = reader.readLine();
379
380 while ( line != null )
381 {
382 line = line.trim();
383
384 if ( !line.startsWith( "#" ) && line.length() != 0 )
385 {
386 lines.addAll( replaceArtifacts( line, hasCommand ) );
387 }
388 line = reader.readLine();
389 }
390 }
391 catch ( IOException e )
392 {
393 throw new VerificationException( e );
394 }
395 }
396
397 return lines;
398 }
399
400 private static final String MARKER = "${artifact:";
401
402 private List<String> replaceArtifacts( String line, boolean hasCommand )
403 {
404 int index = line.indexOf( MARKER );
405 if ( index >= 0 )
406 {
407 String newLine = line.substring( 0, index );
408 index = line.indexOf( "}", index );
409 if ( index < 0 )
410 {
411 throw new IllegalArgumentException( "line does not contain ending artifact marker: '" + line + "'" );
412 }
413 String artifact = line.substring( newLine.length() + MARKER.length(), index );
414
415 newLine += getArtifactPath( artifact );
416 newLine += line.substring( index + 1 );
417
418 List<String> l = new ArrayList<>();
419 l.add( newLine );
420
421 int endIndex = newLine.lastIndexOf( '/' );
422
423 String command = null;
424 String filespec;
425 if ( hasCommand )
426 {
427 int startIndex = newLine.indexOf( ' ' );
428
429 command = newLine.substring( 0, startIndex );
430
431 filespec = newLine.substring( startIndex + 1, endIndex );
432 }
433 else
434 {
435 filespec = newLine;
436 }
437
438 File dir = new File( filespec );
439 addMetadataToList( dir, hasCommand, l, command );
440 addMetadataToList( dir.getParentFile(), hasCommand, l, command );
441
442 return l;
443 }
444 else
445 {
446 return Collections.singletonList( line );
447 }
448 }
449
450 private static void addMetadataToList( File dir, boolean hasCommand, List<String> l, String command )
451 {
452 if ( dir.exists() && dir.isDirectory() )
453 {
454 String[] files = dir.list( new FilenameFilter()
455 {
456 public boolean accept( File dir, String name )
457 {
458 return name.startsWith( "maven-metadata" ) && name.endsWith( ".xml" );
459
460 }
461 } );
462
463 for ( String file : files )
464 {
465 if ( hasCommand )
466 {
467 l.add( command + " " + new File( dir, file ).getPath() );
468 }
469 else
470 {
471 l.add( new File( dir, file ).getPath() );
472 }
473 }
474 }
475 }
476
477 private String getArtifactPath( String artifact )
478 {
479 StringTokenizer tok = new StringTokenizer( artifact, ":" );
480 if ( tok.countTokens() != 4 )
481 {
482 throw new IllegalArgumentException( "Artifact must have 4 tokens: '" + artifact + "'" );
483 }
484
485 String[] a = new String[4];
486 for ( int i = 0; i < 4; i++ )
487 {
488 a[i] = tok.nextToken();
489 }
490
491 String groupId = a[0];
492 String artifactId = a[1];
493 String version = a[2];
494 String ext = a[3];
495 return getArtifactPath( groupId, artifactId, version, ext );
496 }
497
498 public String getArtifactPath( String groupId, String artifactId, String version, String ext )
499 {
500 return getArtifactPath( groupId, artifactId, version, ext, null );
501 }
502
503
504
505
506
507
508
509
510
511
512
513
514 public String getArtifactPath( String gid, String aid, String version, String ext, String classifier )
515 {
516 if ( classifier != null && classifier.length() == 0 )
517 {
518 classifier = null;
519 }
520 if ( "maven-plugin".equals( ext ) )
521 {
522 ext = "jar";
523 }
524 if ( "coreit-artifact".equals( ext ) )
525 {
526 ext = "jar";
527 classifier = "it";
528 }
529 if ( "test-jar".equals( ext ) )
530 {
531 ext = "jar";
532 classifier = "tests";
533 }
534
535 String repositoryPath;
536 if ( "legacy".equals( localRepoLayout ) )
537 {
538 repositoryPath = gid + "/" + ext + "s/" + aid + "-" + version + "." + ext;
539 }
540 else if ( "default".equals( localRepoLayout ) )
541 {
542 repositoryPath = gid.replace( '.', '/' );
543 repositoryPath = repositoryPath + "/" + aid + "/" + version;
544 repositoryPath = repositoryPath + "/" + aid + "-" + version;
545 if ( classifier != null )
546 {
547 repositoryPath = repositoryPath + "-" + classifier;
548 }
549 repositoryPath = repositoryPath + "." + ext;
550 }
551 else
552 {
553 throw new IllegalStateException( "Unknown layout: " + localRepoLayout );
554 }
555
556 return localRepo + "/" + repositoryPath;
557 }
558
559 public List<String> getArtifactFileNameList( String org, String name, String version, String ext )
560 {
561 List<String> files = new ArrayList<>();
562 String artifactPath = getArtifactPath( org, name, version, ext );
563 File dir = new File( artifactPath );
564 files.add( artifactPath );
565 addMetadataToList( dir, false, files, null );
566 addMetadataToList( dir.getParentFile(), false, files, null );
567 return files;
568 }
569
570
571
572
573
574
575
576
577
578
579 public String getArtifactMetadataPath( String gid, String aid, String version )
580 {
581 return getArtifactMetadataPath( gid, aid, version, "maven-metadata-local.xml" );
582 }
583
584
585
586
587
588
589
590
591
592
593
594 public String getArtifactMetadataPath( String gid, String aid, String version, String filename )
595 {
596 StringBuilder buffer = new StringBuilder( 256 );
597
598 buffer.append( localRepo );
599 buffer.append( '/' );
600
601 if ( "default".equals( localRepoLayout ) )
602 {
603 buffer.append( gid.replace( '.', '/' ) );
604 buffer.append( '/' );
605
606 if ( aid != null )
607 {
608 buffer.append( aid );
609 buffer.append( '/' );
610
611 if ( version != null )
612 {
613 buffer.append( version );
614 buffer.append( '/' );
615 }
616 }
617
618 buffer.append( filename );
619 }
620 else
621 {
622 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
623 }
624
625 return buffer.toString();
626 }
627
628
629
630
631
632
633
634
635
636 public String getArtifactMetadataPath( String gid, String aid )
637 {
638 return getArtifactMetadataPath( gid, aid, null );
639 }
640
641 private static String retrieveLocalRepo( String settingsXmlPath )
642 throws VerificationException
643 {
644 UserModelReader userModelReader = new UserModelReader();
645
646 String userHome = System.getProperty( "user.home" );
647
648 File userXml;
649
650 String repo = null;
651
652 if ( settingsXmlPath != null )
653 {
654 userXml = new File( settingsXmlPath );
655 }
656 else
657 {
658 userXml = new File( userHome, ".m2/settings.xml" );
659 }
660
661 if ( userXml.exists() )
662 {
663 userModelReader.parse( userXml );
664
665 String localRepository = userModelReader.getLocalRepository();
666 if ( localRepository != null )
667 {
668 repo = new File( localRepository ).getAbsolutePath();
669 }
670 }
671
672 return repo;
673 }
674
675 public void deleteArtifact( String org, String name, String version, String ext )
676 throws IOException
677 {
678 List<String> files = getArtifactFileNameList( org, name, version, ext );
679 for ( String fileName : files )
680 {
681 FileUtils.forceDelete( new File( fileName ) );
682 }
683 }
684
685
686
687
688
689
690
691
692 public void deleteArtifacts( String gid )
693 throws IOException
694 {
695 String path;
696 if ( "default".equals( localRepoLayout ) )
697 {
698 path = gid.replace( '.', '/' );
699 }
700 else if ( "legacy".equals( localRepoLayout ) )
701 {
702 path = gid;
703 }
704 else
705 {
706 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
707 }
708
709 FileUtils.deleteDirectory( new File( localRepo, path ) );
710 }
711
712
713
714
715
716
717
718
719
720
721 public void deleteArtifacts( String gid, String aid, String version )
722 throws IOException
723 {
724 String path;
725 if ( "default".equals( localRepoLayout ) )
726 {
727 path = gid.replace( '.', '/' ) + '/' + aid + '/' + version;
728 }
729 else
730 {
731 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
732 }
733
734 FileUtils.deleteDirectory( new File( localRepo, path ) );
735 }
736
737
738
739
740
741
742
743
744 public void deleteDirectory( String path )
745 throws IOException
746 {
747 FileUtils.deleteDirectory( new File( getBasedir(), path ) );
748 }
749
750
751
752
753
754
755
756
757
758 public void writeFile( String path, String contents )
759 throws IOException
760 {
761 FileUtils.fileWrite( new File( getBasedir(), path ).getAbsolutePath(), "UTF-8", contents );
762 }
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782 public File filterFile( String srcPath, String dstPath, String fileEncoding )
783 throws IOException
784 {
785 return filterFile( srcPath, dstPath, fileEncoding, newDefaultFilterMap() );
786 }
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802 public File filterFile( String srcPath, String dstPath, String fileEncoding, Map<String, String> filterMap )
803 throws IOException
804 {
805 File srcFile = new File( getBasedir(), srcPath );
806 String data = FileUtils.fileRead( srcFile, fileEncoding );
807
808 for ( Map.Entry<String, String> entry : filterMap.entrySet() )
809 {
810 data = StringUtils.replace( data, entry.getKey() , entry.getValue() );
811 }
812
813 File dstFile = new File( getBasedir(), dstPath );
814
815 dstFile.getParentFile().mkdirs();
816 FileUtils.fileWrite( dstFile.getPath(), fileEncoding, data );
817
818 return dstFile;
819 }
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836 @Deprecated
837 @SuppressWarnings( { "rawtypes", "unchecked" } )
838 public File filterFile( String srcPath, String dstPath, String fileEncoding, Properties filterProperties )
839 throws IOException
840 {
841 return filterFile( srcPath, dstPath, fileEncoding, (Map) filterProperties );
842 }
843
844
845
846
847
848
849
850
851
852 @Deprecated
853 public Properties newDefaultFilterProperties()
854 {
855 Properties filterProperties = new Properties();
856 filterProperties.putAll( newDefaultFilterMap() );
857 return filterProperties;
858 }
859
860
861
862
863
864
865
866
867 public Map<String, String> newDefaultFilterMap()
868 {
869 Map<String, String> filterMap = new HashMap<>();
870
871 String basedir = new File( getBasedir() ).getAbsolutePath();
872 filterMap.put( "@basedir@", basedir );
873
874
875
876
877
878 String baseurl = basedir;
879 if ( !baseurl.startsWith( "/" ) )
880 {
881 baseurl = '/' + baseurl;
882 }
883 baseurl = "file://" + baseurl.replace( '\\', '/' );
884 filterMap.put( "@baseurl@", baseurl );
885
886 return filterMap;
887 }
888
889
890
891
892
893
894
895 public void verifyFilePresent( String file ) throws VerificationException
896 {
897 verifyFilePresence( file, true );
898 }
899
900
901
902
903
904
905
906
907
908
909 public void verifyFileContentMatches( String file, String regex ) throws VerificationException
910 {
911 verifyFilePresent( file );
912 try
913 {
914 String content = FileUtils.fileRead( file );
915 if ( !Pattern.matches( regex, content ) )
916 {
917 throw new VerificationException( "Content of " + file + " does not match " + regex );
918 }
919 }
920 catch ( IOException e )
921 {
922 throw new VerificationException( "Could not read from " + file, e );
923 }
924 }
925
926
927
928
929
930
931
932 public void verifyFileNotPresent( String file ) throws VerificationException
933 {
934 verifyFilePresence( file, false );
935 }
936
937 private void verifyArtifactPresence( boolean wanted, String groupId, String artifactId, String version, String ext )
938 throws VerificationException
939 {
940 List<String> files = getArtifactFileNameList( groupId, artifactId, version, ext );
941 for ( String fileName : files )
942 {
943 verifyFilePresence( fileName, wanted );
944 }
945 }
946
947
948
949
950
951
952
953
954
955
956 public void verifyArtifactPresent( String groupId, String artifactId, String version, String ext )
957 throws VerificationException
958 {
959 verifyArtifactPresence( true, groupId, artifactId, version, ext );
960 }
961
962
963
964
965
966
967
968
969
970
971 public void verifyArtifactNotPresent( String groupId, String artifactId, String version, String ext )
972 throws VerificationException
973 {
974 verifyArtifactPresence( false, groupId, artifactId, version, ext );
975 }
976
977 private void verifyExpectedResult( String line )
978 throws VerificationException
979 {
980 boolean wanted = true;
981 if ( line.startsWith( "!" ) )
982 {
983 line = line.substring( 1 );
984 wanted = false;
985 }
986
987 verifyFilePresence( line, wanted );
988 }
989
990 private void verifyFilePresence( String filePath, boolean wanted )
991 throws VerificationException
992 {
993 if ( filePath.indexOf( "!/" ) > 0 )
994 {
995 String urlString = "jar:file:" + getBasedir() + "/" + filePath;
996
997 InputStream is = null;
998 try
999 {
1000 URL url = new URL( urlString );
1001
1002 is = url.openStream();
1003
1004 if ( is == null )
1005 {
1006 if ( wanted )
1007 {
1008 throw new VerificationException( "Expected JAR resource was not found: " + filePath );
1009 }
1010 }
1011 else
1012 {
1013 if ( !wanted )
1014 {
1015 throw new VerificationException( "Unwanted JAR resource was found: " + filePath );
1016 }
1017 }
1018 }
1019 catch ( MalformedURLException e )
1020 {
1021 throw new VerificationException( "Error looking for JAR resource", e );
1022 }
1023 catch ( IOException e )
1024 {
1025 if ( wanted )
1026 {
1027 throw new VerificationException( "Error looking for JAR resource: " + filePath );
1028 }
1029 }
1030 finally
1031 {
1032 if ( is != null )
1033 {
1034 try
1035 {
1036 is.close();
1037 }
1038 catch ( IOException e )
1039 {
1040
1041 }
1042 }
1043 }
1044 }
1045 else
1046 {
1047 File expectedFile = new File( filePath );
1048
1049
1050 if ( !expectedFile.isAbsolute() && !expectedFile.getPath().startsWith( File.separator ) )
1051 {
1052 expectedFile = new File( getBasedir(), filePath );
1053 }
1054
1055 if ( filePath.indexOf( '*' ) > -1 )
1056 {
1057 File parent = expectedFile.getParentFile();
1058
1059 if ( !parent.exists() )
1060 {
1061 if ( wanted )
1062 {
1063 throw new VerificationException(
1064 "Expected file pattern was not found: " + expectedFile.getPath() );
1065 }
1066 }
1067 else
1068 {
1069 String shortNamePattern = expectedFile.getName().replaceAll( "\\*", ".*" );
1070
1071 String[] candidates = parent.list();
1072
1073 boolean found = false;
1074
1075 if ( candidates != null )
1076 {
1077 for ( String candidate : candidates )
1078 {
1079 if ( candidate.matches( shortNamePattern ) )
1080 {
1081 found = true;
1082 break;
1083 }
1084 }
1085 }
1086
1087 if ( !found && wanted )
1088 {
1089 throw new VerificationException(
1090 "Expected file pattern was not found: " + expectedFile.getPath() );
1091 }
1092 else if ( found && !wanted )
1093 {
1094 throw new VerificationException( "Unwanted file pattern was found: " + expectedFile.getPath() );
1095 }
1096 }
1097 }
1098 else
1099 {
1100 if ( !expectedFile.exists() )
1101 {
1102 if ( wanted )
1103 {
1104 throw new VerificationException( "Expected file was not found: " + expectedFile.getPath() );
1105 }
1106 }
1107 else
1108 {
1109 if ( !wanted )
1110 {
1111 throw new VerificationException( "Unwanted file was found: " + expectedFile.getPath() );
1112 }
1113 }
1114 }
1115 }
1116 }
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 @Deprecated
1134 public void executeGoal( String goal )
1135 throws VerificationException
1136 {
1137 executeGoal( goal, environmentVariables );
1138 }
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 @Deprecated
1154 public void executeGoal( String goal, Map<String, String> envVars )
1155 throws VerificationException
1156 {
1157 executeGoals( Collections.singletonList( goal ), envVars );
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171 @Deprecated
1172 public void executeGoals( List<String> goals )
1173 throws VerificationException
1174 {
1175 executeGoals( goals, environmentVariables );
1176 }
1177
1178 public String getExecutable()
1179 {
1180
1181
1182
1183 if ( mavenHome != null )
1184 {
1185 return mavenHome + "/bin/mvn";
1186 }
1187 else
1188 {
1189 return "mvn";
1190 }
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 @Deprecated
1207 public void executeGoals( List<String> goals, Map<String, String> envVars )
1208 throws VerificationException
1209 {
1210 cliArguments.addAll( goals );
1211 environmentVariables.putAll( envVars );
1212 execute();
1213 }
1214
1215
1216
1217
1218 public void execute() throws VerificationException
1219 {
1220
1221 List<String> args = new ArrayList<>();
1222
1223 Collections.addAll( args, defaultCliArguments );
1224
1225 if ( this.mavenDebug )
1226 {
1227 args.add( "-X" );
1228 }
1229
1230
1231
1232
1233
1234
1235
1236 boolean useMavenRepoLocal = Boolean.valueOf( verifierProperties.getProperty( "use.mavenRepoLocal", "true" ) );
1237
1238 if ( useMavenRepoLocal )
1239 {
1240 args.add( "-Dmaven.repo.local=" + localRepo );
1241 }
1242
1243 if ( autoclean )
1244 {
1245 args.add( CLEAN_CLI_ARGUMENT );
1246 }
1247
1248 for ( String cliArgument : cliArguments )
1249 {
1250 args.add( cliArgument.replace( "${basedir}", getBasedir() ) );
1251 }
1252
1253 int ret;
1254 File logFile = new File( getBasedir(), getLogFileName() );
1255
1256 try
1257 {
1258 MavenLauncher launcher = getMavenLauncher( environmentVariables );
1259
1260 String[] cliArgs = args.toArray( new String[0] );
1261 ret = launcher.run( cliArgs, systemProperties, getBasedir(), logFile );
1262 }
1263 catch ( LauncherException e )
1264 {
1265 throw new VerificationException( "Failed to execute Maven", e );
1266 }
1267 catch ( IOException e )
1268 {
1269 throw new VerificationException( e );
1270 }
1271
1272 if ( ret > 0 )
1273 {
1274 throw new VerificationException(
1275 "Exit code was non-zero: " + ret + "; command line and log = \n" + new File( mavenHome,
1276 "bin/mvn" ) + " "
1277 + StringUtils.join( args.iterator(), " " ) + "\n" + getLogContents( logFile ) );
1278 }
1279 }
1280
1281 protected MavenLauncher getMavenLauncher( Map<String, String> envVars )
1282 throws LauncherException
1283 {
1284 boolean fork;
1285 if ( useWrapper )
1286 {
1287 fork = true;
1288 }
1289 else if ( forkJvm != null )
1290 {
1291 fork = forkJvm;
1292 }
1293 else if ( ( envVars.isEmpty() && "auto".equalsIgnoreCase( forkMode ) )
1294 || "embedded".equalsIgnoreCase( forkMode ) )
1295 {
1296 fork = false;
1297
1298 try
1299 {
1300 initEmbeddedLauncher();
1301 }
1302 catch ( Exception e )
1303 {
1304 fork = true;
1305 }
1306 }
1307 else
1308 {
1309 fork = true;
1310 }
1311
1312 if ( !fork )
1313 {
1314 if ( !envVars.isEmpty() )
1315 {
1316 throw new LauncherException( "Environment variables are not supported in embedded runtime" );
1317 }
1318
1319 initEmbeddedLauncher();
1320
1321 return embeddedLauncher;
1322 }
1323 else
1324 {
1325 return new ForkedLauncher( mavenHome, envVars, debugJvm, useWrapper );
1326 }
1327 }
1328
1329 private void initEmbeddedLauncher()
1330 throws LauncherException
1331 {
1332 if ( embeddedLauncher == null )
1333 {
1334 if ( StringUtils.isEmpty( mavenHome ) )
1335 {
1336 embeddedLauncher = Embedded3xLauncher.createFromClasspath();
1337 }
1338 else
1339 {
1340 String defaultClasspath = System.getProperty( "maven.bootclasspath" );
1341 String defaultClassworldConf = System.getProperty( "classworlds.conf" );
1342 embeddedLauncher = Embedded3xLauncher.createFromMavenHome( mavenHome, defaultClassworldConf,
1343 parseClasspath( defaultClasspath ) );
1344 }
1345 }
1346 }
1347
1348 private static List<URL> parseClasspath( String classpath )
1349 throws LauncherException
1350 {
1351 if ( classpath == null )
1352 {
1353 return null;
1354 }
1355 ArrayList<URL> classpathUrls = new ArrayList<>();
1356 StringTokenizer st = new StringTokenizer( classpath, File.pathSeparator );
1357 while ( st.hasMoreTokens() )
1358 {
1359 try
1360 {
1361 classpathUrls.add( new File( st.nextToken() ).toURI().toURL() );
1362 }
1363 catch ( MalformedURLException e )
1364 {
1365 throw new LauncherException( "Invalid launcher classpath " + classpath, e );
1366 }
1367 }
1368 return classpathUrls;
1369 }
1370
1371 public String getMavenVersion()
1372 throws VerificationException
1373 {
1374 try
1375 {
1376 return getMavenLauncher( Collections.emptyMap() ).getMavenVersion();
1377 }
1378 catch ( LauncherException | IOException e )
1379 {
1380 throw new VerificationException( e );
1381 }
1382 }
1383
1384 private static String getLogContents( File logFile )
1385 {
1386 try
1387 {
1388 return FileUtils.fileRead( logFile );
1389 }
1390 catch ( IOException e )
1391 {
1392
1393 return "(Error reading log contents: " + e.getMessage() + ")";
1394 }
1395 }
1396
1397 private void findLocalRepo( String settingsFile )
1398 throws VerificationException
1399 {
1400 if ( localRepo == null )
1401 {
1402 localRepo = System.getProperty( "maven.repo.local" );
1403 }
1404
1405 if ( localRepo == null )
1406 {
1407 localRepo = retrieveLocalRepo( settingsFile );
1408 }
1409
1410 if ( localRepo == null )
1411 {
1412 localRepo = System.getProperty( "user.home" ) + "/.m2/repository";
1413 }
1414
1415 File repoDir = new File( localRepo );
1416
1417 if ( !repoDir.exists() )
1418 {
1419
1420 repoDir.mkdirs();
1421 }
1422
1423
1424 localRepo = repoDir.getAbsolutePath();
1425
1426 localRepoLayout = System.getProperty( "maven.repo.local.layout", "default" );
1427 }
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 public void verifyArtifactContent( String groupId, String artifactId, String version, String ext, String content )
1441 throws IOException, VerificationException
1442 {
1443 String fileName = getArtifactPath( groupId, artifactId, version, ext );
1444 if ( !content.equals( FileUtils.fileRead( fileName ) ) )
1445 {
1446 throw new VerificationException( "Content of " + fileName + " does not equal " + content );
1447 }
1448 }
1449
1450 static class UserModelReader
1451 extends DefaultHandler
1452 {
1453 private String localRepository;
1454
1455 private StringBuilder currentBody = new StringBuilder();
1456
1457 public void parse( File file )
1458 throws VerificationException
1459 {
1460 try
1461 {
1462 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
1463
1464 SAXParser parser = saxFactory.newSAXParser();
1465
1466 InputSource is = new InputSource( new FileInputStream( file ) );
1467
1468 parser.parse( is, this );
1469 }
1470 catch ( FileNotFoundException e )
1471 {
1472 throw new VerificationException( "file not found path : " + file.getAbsolutePath(), e );
1473 }
1474 catch ( IOException e )
1475 {
1476 throw new VerificationException( " IOException path : " + file.getAbsolutePath(), e );
1477 }
1478 catch ( ParserConfigurationException e )
1479 {
1480 throw new VerificationException( e );
1481 }
1482 catch ( SAXException e )
1483 {
1484 throw new VerificationException( "Parsing exception for file " + file.getAbsolutePath(), e );
1485 }
1486 }
1487
1488 public void warning( SAXParseException spe )
1489 {
1490
1491 }
1492
1493 public void error( SAXParseException spe ) throws SAXException
1494 {
1495 throw new SAXException( spe );
1496 }
1497
1498 public void fatalError( SAXParseException spe ) throws SAXException
1499 {
1500 throw new SAXException( spe );
1501 }
1502
1503 public String getLocalRepository()
1504 {
1505 return localRepository;
1506 }
1507
1508 public void characters( char[] ch, int start, int length )
1509 throws SAXException
1510 {
1511 currentBody.append( ch, start, length );
1512 }
1513
1514 public void endElement( String uri, String localName, String rawName )
1515 throws SAXException
1516 {
1517 if ( "localRepository".equals( rawName ) )
1518 {
1519 if ( notEmpty( currentBody.toString() ) )
1520 {
1521 localRepository = currentBody.toString().trim();
1522 }
1523 else
1524 {
1525 throw new SAXException(
1526 "Invalid mavenProfile entry. Missing one or more " + "fields: {localRepository}." );
1527 }
1528 }
1529
1530 currentBody = new StringBuilder();
1531 }
1532
1533 private boolean notEmpty( String test )
1534 {
1535 return test != null && test.trim().length() > 0;
1536 }
1537
1538 public void reset()
1539 {
1540 currentBody = null;
1541 localRepository = null;
1542 }
1543 }
1544
1545
1546
1547
1548
1549 @Deprecated
1550 public List<String> getCliOptions()
1551 {
1552 return cliArguments;
1553 }
1554
1555
1556
1557
1558 @Deprecated
1559 public void setCliOptions( List<String> cliOptions )
1560 {
1561 this.cliArguments = cliOptions;
1562 }
1563
1564
1565
1566
1567
1568
1569
1570
1571 @Deprecated
1572 public void addCliOption( String option )
1573 {
1574 addCliArgument( option );
1575 }
1576
1577
1578
1579
1580
1581
1582
1583
1584 public void addCliArgument( String cliArgument )
1585 {
1586 cliArguments.add( cliArgument );
1587 }
1588
1589
1590
1591
1592
1593
1594
1595
1596 public void addCliArguments( String... cliArguments )
1597 {
1598 Collections.addAll( this.cliArguments, cliArguments );
1599 }
1600
1601
1602 public Properties getSystemProperties()
1603 {
1604 return systemProperties;
1605 }
1606
1607 public void setSystemProperties( Properties systemProperties )
1608 {
1609 this.systemProperties = systemProperties;
1610 }
1611
1612 public void setSystemProperty( String key, String value )
1613 {
1614 if ( value != null )
1615 {
1616 systemProperties.setProperty( key, value );
1617 }
1618 else
1619 {
1620 systemProperties.remove( key );
1621 }
1622 }
1623
1624 public Map<String, String> getEnvironmentVariables()
1625 {
1626 return environmentVariables;
1627 }
1628
1629 public void setEnvironmentVariables( Map<String, String> environmentVariables )
1630 {
1631 this.environmentVariables = environmentVariables;
1632 }
1633
1634 public void setEnvironmentVariable( String key, String value )
1635 {
1636 if ( value != null )
1637 {
1638 environmentVariables.put( key, value );
1639 }
1640 else
1641 {
1642 environmentVariables.remove( key );
1643 }
1644 }
1645
1646 public Properties getVerifierProperties()
1647 {
1648 return verifierProperties;
1649 }
1650
1651 public void setVerifierProperties( Properties verifierProperties )
1652 {
1653 this.verifierProperties = verifierProperties;
1654 }
1655
1656 public boolean isAutoclean()
1657 {
1658 return autoclean;
1659 }
1660
1661
1662
1663
1664
1665
1666
1667
1668 public void setAutoclean( boolean autoclean )
1669 {
1670 this.autoclean = autoclean;
1671 }
1672
1673 public String getBasedir()
1674 {
1675 return basedir;
1676 }
1677
1678
1679
1680
1681
1682
1683
1684 public String getLogFileName()
1685 {
1686 return this.logFileName;
1687 }
1688
1689
1690
1691
1692
1693
1694
1695
1696 public void setLogFileName( String logFileName )
1697 {
1698 if ( StringUtils.isEmpty( logFileName ) )
1699 {
1700 throw new IllegalArgumentException( "log file name unspecified" );
1701 }
1702 this.logFileName = logFileName;
1703 }
1704
1705
1706
1707
1708 @Deprecated
1709 public void setDebug( boolean debug )
1710 {
1711 }
1712
1713
1714
1715
1716 @Deprecated
1717 public boolean isMavenDebug()
1718 {
1719 return mavenDebug;
1720 }
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730 @Deprecated
1731 public void setMavenDebug( boolean mavenDebug )
1732 {
1733 this.mavenDebug = mavenDebug;
1734 }
1735
1736 public void setForkJvm( boolean forkJvm )
1737 {
1738 this.forkJvm = forkJvm;
1739 }
1740
1741 public boolean isDebugJvm()
1742 {
1743 return debugJvm;
1744 }
1745
1746 public void setDebugJvm( boolean debugJvm )
1747 {
1748 this.debugJvm = debugJvm;
1749 }
1750
1751 public String getLocalRepoLayout()
1752 {
1753 return localRepoLayout;
1754 }
1755
1756 public void setLocalRepoLayout( String localRepoLayout )
1757 {
1758 this.localRepoLayout = localRepoLayout;
1759 }
1760
1761 public String getLocalRepository()
1762 {
1763 return localRepo;
1764 }
1765 }