1 package org.apache.maven.it;
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.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.FileReader;
28 import java.io.FileWriter;
29 import java.io.FilenameFilter;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.PrintStream;
34 import java.io.Writer;
35 import java.net.MalformedURLException;
36 import java.net.URL;
37 import java.text.DecimalFormat;
38 import java.text.NumberFormat;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collections;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Properties;
46 import java.util.StringTokenizer;
47 import java.util.regex.Matcher;
48 import java.util.regex.Pattern;
49
50 import org.apache.maven.shared.utils.StringUtils;
51 import org.apache.maven.shared.utils.cli.CommandLineException;
52 import org.apache.maven.shared.utils.cli.CommandLineUtils;
53 import org.apache.maven.shared.utils.cli.Commandline;
54 import org.apache.maven.shared.utils.cli.StreamConsumer;
55 import org.apache.maven.shared.utils.cli.WriterStreamConsumer;
56 import org.apache.maven.shared.utils.io.FileUtils;
57 import org.apache.maven.shared.utils.io.IOUtil;
58
59 import javax.xml.parsers.ParserConfigurationException;
60 import javax.xml.parsers.SAXParser;
61 import javax.xml.parsers.SAXParserFactory;
62
63 import junit.framework.Assert;
64 import org.xml.sax.InputSource;
65 import org.xml.sax.SAXException;
66 import org.xml.sax.SAXParseException;
67 import org.xml.sax.helpers.DefaultHandler;
68
69
70
71
72
73
74
75 public class Verifier
76 {
77 private static final String LOG_FILENAME = "log.txt";
78
79 public String localRepo;
80
81 private final String basedir;
82
83 private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
84
85 private final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
86
87 private PrintStream originalOut;
88
89 private PrintStream originalErr;
90
91 private List<String> cliOptions = new ArrayList<String>();
92
93 private Properties systemProperties = new Properties();
94
95 private Properties environmentVariables = new Properties();
96
97 private Properties verifierProperties = new Properties();
98
99 private boolean autoclean = true;
100
101 private String localRepoLayout = "default";
102
103 private boolean debug;
104
105 private Boolean forkJvm;
106
107 private String logFileName = LOG_FILENAME;
108
109 private String defaultMavenHome;
110
111
112 private boolean mavenDebug = false;
113
114 private String forkMode;
115
116 private boolean debugJvm = false;
117
118 private static MavenLauncher embeddedLauncher;
119
120 public Verifier( String basedir )
121 throws VerificationException
122 {
123 this( basedir, null );
124 }
125
126 public Verifier( String basedir, boolean debug )
127 throws VerificationException
128 {
129 this( basedir, null, debug );
130 }
131
132 public Verifier( String basedir, String settingsFile )
133 throws VerificationException
134 {
135 this( basedir, settingsFile, false );
136 }
137
138 public Verifier( String basedir, String settingsFile, boolean debug )
139 throws VerificationException
140 {
141 this( basedir, settingsFile, debug, null );
142 }
143
144 public Verifier( String basedir, String settingsFile, boolean debug, boolean forkJvm )
145 throws VerificationException
146 {
147 this( basedir, settingsFile, debug, Boolean.valueOf( forkJvm ) );
148 }
149
150 private Verifier( String basedir, String settingsFile, boolean debug, Boolean forkJvm )
151 throws VerificationException
152 {
153 this.basedir = basedir;
154
155 this.forkJvm = forkJvm;
156 this.
157
158 forkMode = System.getProperty( "verifier.forkMode" );
159
160 if ( !debug )
161 {
162 originalOut = System.out;
163
164 originalErr = System.err;
165 }
166
167 setDebug( debug );
168
169 findLocalRepo( settingsFile );
170 findDefaultMavenHome();
171
172 if ( StringUtils.isEmpty( defaultMavenHome ) && StringUtils.isEmpty( forkMode ) )
173 {
174 forkMode = "auto";
175 }
176 }
177
178 private void findDefaultMavenHome()
179 throws VerificationException
180 {
181 defaultMavenHome = System.getProperty( "maven.home" );
182
183 if ( defaultMavenHome == null )
184 {
185 try
186 {
187 Properties envVars = CommandLineUtils.getSystemEnvVars();
188 defaultMavenHome = envVars.getProperty( "M2_HOME" );
189 }
190 catch ( IOException e )
191 {
192 throw new VerificationException( "Cannot read system environment variables.", e );
193 }
194 }
195
196 if ( defaultMavenHome == null )
197 {
198 File f = new File( System.getProperty( "user.home" ), "m2" );
199 if ( new File( f, "bin/mvn" ).isFile() )
200 {
201 defaultMavenHome = f.getAbsolutePath();
202 }
203 }
204 }
205
206 public void setLocalRepo( String localRepo )
207 {
208 this.localRepo = localRepo;
209 }
210
211 public void resetStreams()
212 {
213 if ( !debug )
214 {
215 System.setOut( originalOut );
216
217 System.setErr( originalErr );
218 }
219 }
220
221 public void displayStreamBuffers()
222 {
223 String out = outStream.toString();
224
225 if ( out != null && out.trim().length() > 0 )
226 {
227 System.out.println( "----- Standard Out -----" );
228
229 System.out.println( out );
230 }
231
232 String err = errStream.toString();
233
234 if ( err != null && err.trim().length() > 0 )
235 {
236 System.err.println( "----- Standard Error -----" );
237
238 System.err.println( err );
239 }
240 }
241
242
243
244
245
246 public void verify( boolean chokeOnErrorOutput )
247 throws VerificationException
248 {
249 List lines = loadFile( getBasedir(), "expected-results.txt", false );
250
251 for ( Object line1 : lines )
252 {
253 String line = (String) line1;
254
255 verifyExpectedResult( line );
256 }
257
258 if ( chokeOnErrorOutput )
259 {
260 verifyErrorFreeLog();
261 }
262 }
263
264 public void verifyErrorFreeLog()
265 throws VerificationException
266 {
267 List<String> lines = loadFile( getBasedir(), getLogFileName(), false );
268
269 for ( String line : lines )
270 {
271
272 if ( line.contains( "[ERROR]" ) && !isVelocityError( line ) )
273 {
274 throw new VerificationException( "Error in execution: " + line );
275 }
276 }
277 }
278
279
280
281
282
283
284
285
286 private static boolean isVelocityError( String line )
287 {
288 return line.contains( "VM_global_library.vm" ) || line.contains( "VM #" ) && line.contains( "macro" );
289 }
290
291
292
293
294
295
296
297 public void verifyTextInLog( String text )
298 throws VerificationException
299 {
300 List<String> lines = loadFile( getBasedir(), getLogFileName(), false );
301
302 boolean result = false;
303 for ( String line : lines )
304 {
305 if ( line.contains( text ) )
306 {
307 result = true;
308 break;
309 }
310 }
311 if ( !result )
312 {
313 throw new VerificationException( "Text not found in log: " + text );
314 }
315 }
316
317 public Properties loadProperties( String filename )
318 throws VerificationException
319 {
320 Properties properties = new Properties();
321
322 try
323 {
324 File propertiesFile = new File( getBasedir(), filename );
325 if ( propertiesFile.exists() )
326 {
327 FileInputStream fis = new FileInputStream( propertiesFile );
328 try
329 {
330 properties.load( fis );
331 }
332 finally
333 {
334 fis.close();
335 }
336 }
337 }
338 catch ( FileNotFoundException e )
339 {
340 throw new VerificationException( "Error reading properties file", e );
341 }
342 catch ( IOException e )
343 {
344 throw new VerificationException( "Error reading properties file", e );
345 }
346
347 return properties;
348 }
349
350
351
352
353
354
355
356
357
358
359
360 public List<String> loadLines( String filename, String encoding )
361 throws IOException
362 {
363 List<String> lines = new ArrayList<String>();
364
365 File file = new File( getBasedir(), filename );
366
367 BufferedReader reader = null;
368 try
369 {
370 if ( StringUtils.isNotEmpty( encoding ) )
371 {
372 reader = new BufferedReader( new InputStreamReader( new FileInputStream( file ), encoding ) );
373 }
374 else
375 {
376 reader = new BufferedReader( new FileReader( file ) );
377 }
378
379 String line;
380 while ( ( line = reader.readLine() ) != null )
381 {
382 if ( line.length() > 0 )
383 {
384 lines.add( line );
385 }
386 }
387 }
388 finally
389 {
390 IOUtil.close( reader );
391 }
392
393 return lines;
394 }
395
396 public List<String> loadFile( String basedir, String filename, boolean hasCommand )
397 throws VerificationException
398 {
399 return loadFile( new File( basedir, filename ), hasCommand );
400 }
401
402 public List<String> loadFile( File file, boolean hasCommand )
403 throws VerificationException
404 {
405 List<String> lines = new ArrayList<String>();
406
407 BufferedReader reader = null;
408
409 if ( file.exists() )
410 {
411 try
412 {
413 reader = new BufferedReader( new FileReader( file ) );
414
415 String line = reader.readLine();
416
417 while ( line != null )
418 {
419 line = line.trim();
420
421 if ( !line.startsWith( "#" ) && line.length() != 0 )
422 {
423 lines.addAll( replaceArtifacts( line, hasCommand ) );
424 }
425 line = reader.readLine();
426 }
427
428 reader.close();
429 }
430 catch ( FileNotFoundException e )
431 {
432 throw new VerificationException( e );
433 }
434 catch ( IOException e )
435 {
436 throw new VerificationException( e );
437 }
438 finally
439 {
440 IOUtil.close( reader );
441 }
442 }
443
444 return lines;
445 }
446
447 private List<String> replaceArtifacts( String line, boolean hasCommand )
448 {
449 String MARKER = "${artifact:";
450 int index = line.indexOf( MARKER );
451 if ( index >= 0 )
452 {
453 String newLine = line.substring( 0, index );
454 index = line.indexOf( "}", index );
455 if ( index < 0 )
456 {
457 throw new IllegalArgumentException( "line does not contain ending artifact marker: '" + line + "'" );
458 }
459 String artifact = line.substring( newLine.length() + MARKER.length(), index );
460
461 newLine += getArtifactPath( artifact );
462 newLine += line.substring( index + 1 );
463
464 List<String> l = new ArrayList<String>();
465 l.add( newLine );
466
467 int endIndex = newLine.lastIndexOf( '/' );
468
469 String command = null;
470 String filespec;
471 if ( hasCommand )
472 {
473 int startIndex = newLine.indexOf( ' ' );
474
475 command = newLine.substring( 0, startIndex );
476
477 filespec = newLine.substring( startIndex + 1, endIndex );
478 }
479 else
480 {
481 filespec = newLine;
482 }
483
484 File dir = new File( filespec );
485 addMetadataToList( dir, hasCommand, l, command );
486 addMetadataToList( dir.getParentFile(), hasCommand, l, command );
487
488 return l;
489 }
490 else
491 {
492 return Collections.singletonList( line );
493 }
494 }
495
496 private static void addMetadataToList( File dir, boolean hasCommand, List<String> l, String command )
497 {
498 if ( dir.exists() && dir.isDirectory() )
499 {
500 String[] files = dir.list( new FilenameFilter()
501 {
502 public boolean accept( File dir, String name )
503 {
504 return name.startsWith( "maven-metadata" ) && name.endsWith( ".xml" );
505
506 }
507 } );
508
509 for ( String file : files )
510 {
511 if ( hasCommand )
512 {
513 l.add( command + " " + new File( dir, file ).getPath() );
514 }
515 else
516 {
517 l.add( new File( dir, file ).getPath() );
518 }
519 }
520 }
521 }
522
523 private String getArtifactPath( String artifact )
524 {
525 StringTokenizer tok = new StringTokenizer( artifact, ":" );
526 if ( tok.countTokens() != 4 )
527 {
528 throw new IllegalArgumentException( "Artifact must have 4 tokens: '" + artifact + "'" );
529 }
530
531 String[] a = new String[4];
532 for ( int i = 0; i < 4; i++ )
533 {
534 a[i] = tok.nextToken();
535 }
536
537 String org = a[0];
538 String name = a[1];
539 String version = a[2];
540 String ext = a[3];
541 return getArtifactPath( org, name, version, ext );
542 }
543
544 public String getArtifactPath( String org, String name, String version, String ext )
545 {
546 return getArtifactPath( org, name, version, ext, null );
547 }
548
549
550
551
552
553
554
555
556
557
558
559
560 public String getArtifactPath( String gid, String aid, String version, String ext, String classifier )
561 {
562 if ( classifier != null && classifier.length() == 0 )
563 {
564 classifier = null;
565 }
566 if ( "maven-plugin".equals( ext ) )
567 {
568 ext = "jar";
569 }
570 if ( "coreit-artifact".equals( ext ) )
571 {
572 ext = "jar";
573 classifier = "it";
574 }
575 if ( "test-jar".equals( ext ) )
576 {
577 ext = "jar";
578 classifier = "tests";
579 }
580
581 String repositoryPath;
582 if ( "legacy".equals( localRepoLayout ) )
583 {
584 repositoryPath = gid + "/" + ext + "s/" + aid + "-" + version + "." + ext;
585 }
586 else if ( "default".equals( localRepoLayout ) )
587 {
588 repositoryPath = gid.replace( '.', '/' );
589 repositoryPath = repositoryPath + "/" + aid + "/" + version;
590 repositoryPath = repositoryPath + "/" + aid + "-" + version;
591 if ( classifier != null )
592 {
593 repositoryPath = repositoryPath + "-" + classifier;
594 }
595 repositoryPath = repositoryPath + "." + ext;
596 }
597 else
598 {
599 throw new IllegalStateException( "Unknown layout: " + localRepoLayout );
600 }
601
602 return localRepo + "/" + repositoryPath;
603 }
604
605 public List<String> getArtifactFileNameList( String org, String name, String version, String ext )
606 {
607 List<String> files = new ArrayList<String>();
608 String artifactPath = getArtifactPath( org, name, version, ext );
609 File dir = new File( artifactPath );
610 files.add( artifactPath );
611 addMetadataToList( dir, false, files, null );
612 addMetadataToList( dir.getParentFile(), false, files, null );
613 return files;
614 }
615
616
617
618
619
620
621
622
623
624
625 public String getArtifactMetadataPath( String gid, String aid, String version )
626 {
627 return getArtifactMetadataPath( gid, aid, version, "maven-metadata-local.xml" );
628 }
629
630
631
632
633
634
635
636
637
638
639
640 public String getArtifactMetadataPath( String gid, String aid, String version, String filename )
641 {
642 StringBuilder buffer = new StringBuilder( 256 );
643
644 buffer.append( localRepo );
645 buffer.append( '/' );
646
647 if ( "default".equals( localRepoLayout ) )
648 {
649 buffer.append( gid.replace( '.', '/' ) );
650 buffer.append( '/' );
651
652 if ( aid != null )
653 {
654 buffer.append( aid );
655 buffer.append( '/' );
656
657 if ( version != null )
658 {
659 buffer.append( version );
660 buffer.append( '/' );
661 }
662 }
663
664 buffer.append( filename );
665 }
666 else
667 {
668 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
669 }
670
671 return buffer.toString();
672 }
673
674
675
676
677
678
679
680
681
682 public String getArtifactMetadataPath( String gid, String aid )
683 {
684 return getArtifactMetadataPath( gid, aid, null );
685 }
686
687 public void executeHook( String filename )
688 throws VerificationException
689 {
690 try
691 {
692 File f = new File( getBasedir(), filename );
693
694 if ( !f.exists() )
695 {
696 return;
697 }
698
699 List<String> lines = loadFile( f, true );
700
701 for ( String line1 : lines )
702 {
703 String line = resolveCommandLineArg( line1 );
704
705 executeCommand( line );
706 }
707 }
708 catch ( VerificationException e )
709 {
710 throw e;
711 }
712 catch ( Exception e )
713 {
714 throw new VerificationException( e );
715 }
716 }
717
718 private void executeCommand( String line )
719 throws VerificationException
720 {
721 int index = line.indexOf( " " );
722
723 String cmd;
724
725 String args = null;
726
727 if ( index >= 0 )
728 {
729 cmd = line.substring( 0, index );
730
731 args = line.substring( index + 1 );
732 }
733 else
734 {
735 cmd = line;
736 }
737
738 if ( "rm".equals( cmd ) )
739 {
740 System.out.println( "Removing file: " + args );
741
742 File f = new File( args );
743
744 if ( f.exists() && !f.delete() )
745 {
746 throw new VerificationException( "Error removing file - delete failed" );
747 }
748 }
749 else if ( "rmdir".equals( cmd ) )
750 {
751 System.out.println( "Removing directory: " + args );
752
753 try
754 {
755 File f = new File( args );
756
757 FileUtils.deleteDirectory( f );
758 }
759 catch ( IOException e )
760 {
761 throw new VerificationException( "Error removing directory - delete failed" );
762 }
763 }
764 else if ( "svn".equals( cmd ) )
765 {
766 launchSubversion( line, getBasedir() );
767 }
768 else
769 {
770 throw new VerificationException( "unknown command: " + cmd );
771 }
772 }
773
774 public static void launchSubversion( String line, String basedir )
775 throws VerificationException
776 {
777 try
778 {
779 Commandline cli = new Commandline( line );
780
781 cli.setWorkingDirectory( basedir );
782
783 Writer logWriter = new FileWriter( new File( basedir, LOG_FILENAME ) );
784
785 StreamConsumer out = new WriterStreamConsumer( logWriter );
786
787 StreamConsumer err = new WriterStreamConsumer( logWriter );
788
789 System.out.println( "Command: " + CommandLineUtils.toString( cli.getCommandline() ) );
790
791 int ret = CommandLineUtils.executeCommandLine( cli, out, err );
792
793 logWriter.close();
794
795 if ( ret > 0 )
796 {
797 System.err.println( "Exit code: " + ret );
798
799 throw new VerificationException();
800 }
801 }
802 catch ( CommandLineException e )
803 {
804 throw new VerificationException( e );
805 }
806 catch ( IOException e )
807 {
808 throw new VerificationException( e );
809 }
810 }
811
812 private static String retrieveLocalRepo( String settingsXmlPath )
813 throws VerificationException
814 {
815 UserModelReader userModelReader = new UserModelReader();
816
817 String userHome = System.getProperty( "user.home" );
818
819 File userXml;
820
821 String repo = null;
822
823 if ( settingsXmlPath != null )
824 {
825 System.out.println( "Using settings from " + settingsXmlPath );
826 userXml = new File( settingsXmlPath );
827 }
828 else
829 {
830 userXml = new File( userHome, ".m2/settings.xml" );
831 }
832
833 if ( userXml.exists() )
834 {
835 userModelReader.parse( userXml );
836
837 String localRepository = userModelReader.getLocalRepository();
838 if ( localRepository != null )
839 {
840 repo = new File( localRepository ).getAbsolutePath();
841 }
842 }
843
844 return repo;
845 }
846
847 public void deleteArtifact( String org, String name, String version, String ext )
848 throws IOException
849 {
850 List<String> files = getArtifactFileNameList( org, name, version, ext );
851 for ( String fileName : files )
852 {
853 FileUtils.forceDelete( new File( fileName ) );
854 }
855 }
856
857
858
859
860
861
862
863
864 public void deleteArtifacts( String gid )
865 throws IOException
866 {
867 String path;
868 if ( "default".equals( localRepoLayout ) )
869 {
870 path = gid.replace( '.', '/' );
871 }
872 else if ( "legacy".equals( localRepoLayout ) )
873 {
874 path = gid;
875 }
876 else
877 {
878 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
879 }
880
881 FileUtils.deleteDirectory( new File( localRepo, path ) );
882 }
883
884
885
886
887
888
889
890
891
892
893 public void deleteArtifacts( String gid, String aid, String version )
894 throws IOException
895 {
896 String path;
897 if ( "default".equals( localRepoLayout ) )
898 {
899 path = gid.replace( '.', '/' ) + '/' + aid + '/' + version;
900 }
901 else
902 {
903 throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout );
904 }
905
906 FileUtils.deleteDirectory( new File( localRepo, path ) );
907 }
908
909
910
911
912
913
914
915
916 public void deleteDirectory( String path )
917 throws IOException
918 {
919 FileUtils.deleteDirectory( new File( getBasedir(), path ) );
920 }
921
922
923
924
925
926
927
928
929
930 public void writeFile( String path, String contents )
931 throws IOException
932 {
933 FileUtils.fileWrite( new File( getBasedir(), path ).getAbsolutePath(), "UTF-8", contents );
934 }
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949 public File filterFile( String srcPath, String dstPath, String fileEncoding, Map filterProperties )
950 throws IOException
951 {
952 File srcFile = new File( getBasedir(), srcPath );
953 String data = FileUtils.fileRead( srcFile, fileEncoding );
954
955 for ( Iterator it = filterProperties.keySet().iterator(); it.hasNext(); )
956 {
957 String token = (String) it.next();
958 String value = String.valueOf( filterProperties.get( token ) );
959 data = StringUtils.replace( data, token, value );
960 }
961
962 File dstFile = new File( getBasedir(), dstPath );
963
964 dstFile.getParentFile().mkdirs();
965 FileUtils.fileWrite( dstFile.getPath(), fileEncoding, data );
966
967 return dstFile;
968 }
969
970
971
972
973
974
975
976
977 public Properties newDefaultFilterProperties()
978 {
979 Properties filterProperties = new Properties();
980
981 String basedir = new File( getBasedir() ).getAbsolutePath();
982 filterProperties.put( "@basedir@", basedir );
983
984
985
986
987
988 String baseurl = basedir;
989 if ( !baseurl.startsWith( "/" ) )
990 {
991 baseurl = '/' + baseurl;
992 }
993 baseurl = "file://" + baseurl.replace( '\\', '/' );
994 filterProperties.put( "@baseurl@", baseurl );
995
996 return filterProperties;
997 }
998
999 public void assertFilePresent( String file )
1000 {
1001 try
1002 {
1003 verifyExpectedResult( file, true );
1004 }
1005 catch ( VerificationException e )
1006 {
1007 Assert.fail( e.getMessage() );
1008 }
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 public void assertFileMatches( String file, String regex )
1020 {
1021 assertFilePresent( file );
1022 try
1023 {
1024 String content = FileUtils.fileRead( file );
1025 if ( !Pattern.matches( regex, content ) )
1026 {
1027 Assert.fail( "Content of " + file + " does not match " + regex );
1028 }
1029 }
1030 catch ( IOException e )
1031 {
1032 Assert.fail( e.getMessage() );
1033 }
1034 }
1035
1036 public void assertFileNotPresent( String file )
1037 {
1038 try
1039 {
1040 verifyExpectedResult( file, false );
1041 }
1042 catch ( VerificationException e )
1043 {
1044 Assert.fail( e.getMessage() );
1045 }
1046 }
1047
1048 private void verifyArtifactPresence( boolean wanted, String org, String name, String version, String ext )
1049 {
1050 List<String> files = getArtifactFileNameList( org, name, version, ext );
1051 for ( String fileName : files )
1052 {
1053 try
1054 {
1055 verifyExpectedResult( fileName, wanted );
1056 }
1057 catch ( VerificationException e )
1058 {
1059 Assert.fail( e.getMessage() );
1060 }
1061 }
1062 }
1063
1064 public void assertArtifactPresent( String org, String name, String version, String ext )
1065 {
1066 verifyArtifactPresence( true, org, name, version, ext );
1067 }
1068
1069 public void assertArtifactNotPresent( String org, String name, String version, String ext )
1070 {
1071 verifyArtifactPresence( false, org, name, version, ext );
1072 }
1073
1074 private void verifyExpectedResult( String line )
1075 throws VerificationException
1076 {
1077 boolean wanted = true;
1078 if ( line.startsWith( "!" ) )
1079 {
1080 line = line.substring( 1 );
1081 wanted = false;
1082 }
1083
1084 verifyExpectedResult( line, wanted );
1085 }
1086
1087 private void verifyExpectedResult( String line, boolean wanted )
1088 throws VerificationException
1089 {
1090 if ( line.indexOf( "!/" ) > 0 )
1091 {
1092 String urlString = "jar:file:" + getBasedir() + "/" + line;
1093
1094 InputStream is = null;
1095 try
1096 {
1097 URL url = new URL( urlString );
1098
1099 is = url.openStream();
1100
1101 if ( is == null )
1102 {
1103 if ( wanted )
1104 {
1105 throw new VerificationException( "Expected JAR resource was not found: " + line );
1106 }
1107 }
1108 else
1109 {
1110 if ( !wanted )
1111 {
1112 throw new VerificationException( "Unwanted JAR resource was found: " + line );
1113 }
1114 }
1115 }
1116 catch ( MalformedURLException e )
1117 {
1118 throw new VerificationException( "Error looking for JAR resource", e );
1119 }
1120 catch ( IOException e )
1121 {
1122 if ( wanted )
1123 {
1124 throw new VerificationException( "Error looking for JAR resource: " + line );
1125 }
1126 }
1127 finally
1128 {
1129 if ( is != null )
1130 {
1131 try
1132 {
1133 is.close();
1134 }
1135 catch ( IOException e )
1136 {
1137 System.err.println( "WARN: error closing stream: " + e );
1138 }
1139 }
1140 }
1141 }
1142 else
1143 {
1144 File expectedFile = new File( line );
1145
1146
1147 if ( !expectedFile.isAbsolute() && !expectedFile.getPath().startsWith( File.separator ) )
1148 {
1149 expectedFile = new File( getBasedir(), line );
1150 }
1151
1152 if ( line.indexOf( '*' ) > -1 )
1153 {
1154 File parent = expectedFile.getParentFile();
1155
1156 if ( !parent.exists() )
1157 {
1158 if ( wanted )
1159 {
1160 throw new VerificationException(
1161 "Expected file pattern was not found: " + expectedFile.getPath() );
1162 }
1163 }
1164 else
1165 {
1166 String shortNamePattern = expectedFile.getName().replaceAll( "\\*", ".*" );
1167
1168 String[] candidates = parent.list();
1169
1170 boolean found = false;
1171
1172 if ( candidates != null )
1173 {
1174 for ( String candidate : candidates )
1175 {
1176 if ( candidate.matches( shortNamePattern ) )
1177 {
1178 found = true;
1179 break;
1180 }
1181 }
1182 }
1183
1184 if ( !found && wanted )
1185 {
1186 throw new VerificationException(
1187 "Expected file pattern was not found: " + expectedFile.getPath() );
1188 }
1189 else if ( found && !wanted )
1190 {
1191 throw new VerificationException( "Unwanted file pattern was found: " + expectedFile.getPath() );
1192 }
1193 }
1194 }
1195 else
1196 {
1197 if ( !expectedFile.exists() )
1198 {
1199 if ( wanted )
1200 {
1201 throw new VerificationException( "Expected file was not found: " + expectedFile.getPath() );
1202 }
1203 }
1204 else
1205 {
1206 if ( !wanted )
1207 {
1208 throw new VerificationException( "Unwanted file was found: " + expectedFile.getPath() );
1209 }
1210 }
1211 }
1212 }
1213 }
1214
1215
1216
1217
1218
1219 public void executeGoal( String goal )
1220 throws VerificationException
1221 {
1222 executeGoal( goal, environmentVariables );
1223 }
1224
1225 public void executeGoal( String goal, Map envVars )
1226 throws VerificationException
1227 {
1228 executeGoals( Arrays.asList( goal ), envVars );
1229 }
1230
1231 public void executeGoals( List<String> goals )
1232 throws VerificationException
1233 {
1234 executeGoals( goals, environmentVariables );
1235 }
1236
1237 public String getExecutable()
1238 {
1239
1240
1241
1242 String mavenHome = defaultMavenHome;
1243
1244 if ( mavenHome != null )
1245 {
1246 return mavenHome + "/bin/mvn";
1247 }
1248 else
1249 {
1250 File f = new File( System.getProperty( "user.home" ), "m2/bin/mvn" );
1251
1252 if ( f.exists() )
1253 {
1254 return f.getAbsolutePath();
1255 }
1256 else
1257 {
1258 return "mvn";
1259 }
1260 }
1261 }
1262
1263 public void executeGoals( List<String> goals, Map envVars )
1264 throws VerificationException
1265 {
1266 List<String> allGoals = new ArrayList<String>();
1267
1268 if ( autoclean )
1269 {
1270
1271
1272
1273 allGoals.add( "org.apache.maven.plugins:maven-clean-plugin:clean" );
1274 }
1275
1276 allGoals.addAll( goals );
1277
1278 List<String> args = new ArrayList<String>();
1279
1280 int ret;
1281
1282 File logFile = new File( getBasedir(), getLogFileName() );
1283
1284 for ( Object cliOption : cliOptions )
1285 {
1286 String key = String.valueOf( cliOption );
1287
1288 String resolvedArg = resolveCommandLineArg( key );
1289
1290 try
1291 {
1292 args.addAll( Arrays.asList( CommandLineUtils.translateCommandline( resolvedArg ) ) );
1293 }
1294 catch ( Exception e )
1295 {
1296 e.printStackTrace();
1297 }
1298 }
1299
1300 args.add( "-e" );
1301
1302 args.add( "--batch-mode" );
1303
1304 if ( this.mavenDebug )
1305 {
1306 args.add( "--debug" );
1307 }
1308
1309 for ( Object o : systemProperties.keySet() )
1310 {
1311 String key = (String) o;
1312 String value = systemProperties.getProperty( key );
1313 args.add( "-D" + key + "=" + value );
1314 }
1315
1316
1317
1318
1319
1320
1321
1322 boolean useMavenRepoLocal = Boolean.valueOf( verifierProperties.getProperty( "use.mavenRepoLocal", "true" ) );
1323
1324 if ( useMavenRepoLocal )
1325 {
1326 args.add( "-Dmaven.repo.local=" + localRepo );
1327 }
1328
1329 args.addAll( allGoals );
1330
1331 try
1332 {
1333 String[] cliArgs = args.toArray( new String[args.size()] );
1334
1335 boolean fork;
1336 if ( forkJvm != null )
1337 {
1338 fork = forkJvm;
1339 }
1340 else if ( envVars.isEmpty() && "auto".equalsIgnoreCase( forkMode ) )
1341 {
1342 fork = false;
1343
1344 try
1345 {
1346 initEmbeddedLauncher();
1347 }
1348 catch ( Exception e )
1349 {
1350 fork = true;
1351 }
1352 }
1353 else
1354 {
1355 fork = true;
1356 }
1357
1358 if ( !fork )
1359 {
1360 initEmbeddedLauncher();
1361
1362 ret = embeddedLauncher.run( cliArgs, getBasedir(), logFile );
1363 }
1364 else
1365 {
1366 ForkedLauncher launcher = new ForkedLauncher( defaultMavenHome, debugJvm );
1367
1368 ret = launcher.run( cliArgs, envVars, getBasedir(), logFile );
1369 }
1370 }
1371 catch ( LauncherException e )
1372 {
1373 throw new VerificationException( "Failed to execute Maven: " + e.getMessage(), e );
1374 }
1375 catch ( IOException e )
1376 {
1377 throw new VerificationException( e );
1378 }
1379
1380 if ( ret > 0 )
1381 {
1382 System.err.println( "Exit code: " + ret );
1383
1384 throw new VerificationException(
1385 "Exit code was non-zero: " + ret + "; command line and log = \n" + new File( defaultMavenHome,
1386 "bin/mvn" ) + " "
1387 + StringUtils.join( args.iterator(), " " ) + "\n" + getLogContents( logFile ) );
1388 }
1389 }
1390
1391 private void initEmbeddedLauncher()
1392 throws LauncherException
1393 {
1394 if ( embeddedLauncher == null )
1395 {
1396 if ( StringUtils.isEmpty( defaultMavenHome ) )
1397 {
1398 embeddedLauncher = new Classpath3xLauncher();
1399 }
1400 else
1401 {
1402 embeddedLauncher = new Embedded3xLauncher( defaultMavenHome );
1403 }
1404 }
1405 }
1406
1407 public String getMavenVersion()
1408 throws VerificationException
1409 {
1410 ForkedLauncher launcher = new ForkedLauncher( defaultMavenHome );
1411
1412 File logFile;
1413 try
1414 {
1415 logFile = File.createTempFile( "maven", "log" );
1416 }
1417 catch ( IOException e )
1418 {
1419 throw new VerificationException( "Error creating temp file", e );
1420 }
1421
1422 try
1423 {
1424
1425 Map envVars = Collections.singletonMap( "MAVEN_OPTS", "-Demma.rt.control=false" );
1426 launcher.run( new String[]{ "--version" }, envVars, null, logFile );
1427 }
1428 catch ( LauncherException e )
1429 {
1430 throw new VerificationException( "Error running commandline " + e.toString(), e );
1431 }
1432 catch ( IOException e )
1433 {
1434 throw new VerificationException( "IO Error communicating with commandline " + e.toString(), e );
1435 }
1436
1437 List logLines = loadFile( logFile, false );
1438
1439 logFile.delete();
1440
1441 String version = extractMavenVersion( logLines );
1442
1443 if ( version == null )
1444 {
1445 throw new VerificationException(
1446 "Illegal maven output: String 'Maven version: ' not found in the following output:\n"
1447 + StringUtils.join( logLines.iterator(), "\n" ) );
1448 }
1449 else
1450 {
1451 return version;
1452 }
1453 }
1454
1455 static String extractMavenVersion( List logLines )
1456 {
1457 String version = null;
1458
1459 final Pattern MAVEN_VERSION = Pattern.compile( "(?i).*Maven [^0-9]*([0-9]\\S*).*" );
1460
1461 for ( Iterator it = logLines.iterator(); version == null && it.hasNext(); )
1462 {
1463 String line = (String) it.next();
1464
1465 Matcher m = MAVEN_VERSION.matcher( line );
1466 if ( m.matches() )
1467 {
1468 version = m.group( 1 );
1469 }
1470 }
1471
1472 return version;
1473 }
1474
1475 private static String getLogContents( File logFile )
1476 {
1477 try
1478 {
1479 return FileUtils.fileRead( logFile );
1480 }
1481 catch ( IOException e )
1482 {
1483
1484 return "(Error reading log contents: " + e.getMessage() + ")";
1485 }
1486 }
1487
1488 private String resolveCommandLineArg( String key )
1489 {
1490 String result = key.replaceAll( "\\$\\{basedir\\}", getBasedir() );
1491 if ( result.contains( "\\\\" ) )
1492 {
1493 result = result.replaceAll( "\\\\", "\\" );
1494 }
1495 result = result.replaceAll( "\\/\\/", "\\/" );
1496
1497 return result;
1498 }
1499
1500 private static List<String> discoverIntegrationTests( String directory )
1501 throws VerificationException
1502 {
1503 try
1504 {
1505 ArrayList<String> tests = new ArrayList<String>();
1506
1507 List<File> subTests = FileUtils.getFiles( new File( directory ), "**/goals.txt", null );
1508
1509 for ( File testCase : subTests )
1510 {
1511 tests.add( testCase.getParent() );
1512 }
1513
1514 return tests;
1515 }
1516 catch ( IOException e )
1517 {
1518 throw new VerificationException( directory + " is not a valid test case container", e );
1519 }
1520 }
1521
1522 private void displayLogFile()
1523 {
1524 System.out.println( "Log file contents:" );
1525 BufferedReader reader = null;
1526 try
1527 {
1528 reader = new BufferedReader( new FileReader( new File( getBasedir(), getLogFileName() ) ) );
1529 String line = reader.readLine();
1530 while ( line != null )
1531 {
1532 System.out.println( line );
1533 line = reader.readLine();
1534 }
1535 reader.close();
1536 }
1537 catch ( FileNotFoundException e )
1538 {
1539 System.err.println( "Error: " + e );
1540 }
1541 catch ( IOException e )
1542 {
1543 System.err.println( "Error: " + e );
1544 }
1545 finally
1546 {
1547 IOUtil.close( reader );
1548 }
1549 }
1550
1551
1552
1553
1554
1555 public static void main( String args[] )
1556 throws VerificationException
1557 {
1558 String basedir = System.getProperty( "user.dir" );
1559
1560 List<String> tests = null;
1561
1562 List<String> argsList = new ArrayList<String>();
1563
1564 String settingsFile = null;
1565
1566
1567 for ( int i = 0; i < args.length; i++ )
1568 {
1569 if ( args[i].startsWith( "-D" ) )
1570 {
1571 int index = args[i].indexOf( "=" );
1572 if ( index >= 0 )
1573 {
1574 System.setProperty( args[i].substring( 2, index ), args[i].substring( index + 1 ) );
1575 }
1576 else
1577 {
1578 System.setProperty( args[i].substring( 2 ), "true" );
1579 }
1580 }
1581 else if ( "-s".equals( args[i] ) || "--settings".equals( args[i] ) )
1582 {
1583 if ( i == args.length - 1 )
1584 {
1585
1586 throw new IllegalStateException( "missing argument to -s" );
1587 }
1588 i += 1;
1589
1590 settingsFile = args[i];
1591 }
1592 else if ( args[i].startsWith( "-" ) )
1593 {
1594 System.out.println( "skipping unrecognised argument: " + args[i] );
1595 }
1596 else
1597 {
1598 argsList.add( args[i] );
1599 }
1600 }
1601
1602 if ( argsList.size() == 0 )
1603 {
1604 if ( FileUtils.fileExists( basedir + File.separator + "integration-tests.txt" ) )
1605 {
1606 try
1607 {
1608 tests = FileUtils.loadFile( new File( basedir, "integration-tests.txt" ) );
1609 }
1610 catch ( IOException e )
1611 {
1612 System.err.println( "Unable to load integration tests file" );
1613
1614 System.err.println( e.getMessage() );
1615
1616 System.exit( 2 );
1617 }
1618 }
1619 else
1620 {
1621 tests = discoverIntegrationTests( "." );
1622 }
1623 }
1624 else
1625 {
1626 tests = new ArrayList<String>( argsList.size() );
1627 NumberFormat fmt = new DecimalFormat( "0000" );
1628 for ( String test : argsList )
1629 {
1630 if ( test.endsWith( "," ) )
1631 {
1632 test = test.substring( 0, test.length() - 1 );
1633 }
1634
1635 if ( StringUtils.isNumeric( test ) )
1636 {
1637
1638 test = "it" + fmt.format( Integer.valueOf( test ) );
1639 tests.add( test.trim() );
1640 }
1641 else if ( "it".startsWith( test ) )
1642 {
1643 test = test.trim();
1644 if ( test.length() > 0 )
1645 {
1646 tests.add( test );
1647 }
1648 }
1649 else if ( FileUtils.fileExists( test ) && new File( test ).isDirectory() )
1650 {
1651 tests.addAll( discoverIntegrationTests( test ) );
1652 }
1653 else
1654 {
1655 System.err.println(
1656 "[WARNING] rejecting " + test + " as an invalid test or test source directory" );
1657 }
1658 }
1659 }
1660
1661 if ( tests.size() == 0 )
1662 {
1663 System.out.println( "No tests to run" );
1664 }
1665
1666 int exitCode = 0;
1667
1668 List<String> failed = new ArrayList<String>();
1669 for ( String test : tests )
1670 {
1671 System.out.print( test + "... " );
1672
1673 String dir = basedir + "/" + test;
1674
1675 if ( !new File( dir, "goals.txt" ).exists() )
1676 {
1677 System.err.println( "Test " + test + " in " + dir + " does not exist" );
1678
1679 System.exit( 2 );
1680 }
1681
1682 Verifier verifier = new Verifier( dir );
1683 verifier.findLocalRepo( settingsFile );
1684
1685 System.out.println( "Using default local repository: " + verifier.localRepo );
1686
1687 try
1688 {
1689 runIntegrationTest( verifier );
1690 }
1691 catch ( Throwable e )
1692 {
1693 verifier.resetStreams();
1694
1695 System.out.println( "FAILED" );
1696
1697 verifier.displayStreamBuffers();
1698
1699 System.out.println( ">>>>>> Error Stacktrace:" );
1700 e.printStackTrace( System.out );
1701 System.out.println( "<<<<<< Error Stacktrace" );
1702
1703 verifier.displayLogFile();
1704
1705 exitCode = 1;
1706
1707 failed.add( test );
1708 }
1709 }
1710
1711 System.out.println( tests.size() - failed.size() + "/" + tests.size() + " passed" );
1712 if ( !failed.isEmpty() )
1713 {
1714 System.out.println( "Failed tests: " + failed );
1715 }
1716
1717 System.exit( exitCode );
1718 }
1719
1720 private void findLocalRepo( String settingsFile )
1721 throws VerificationException
1722 {
1723 if ( localRepo == null )
1724 {
1725 localRepo = System.getProperty( "maven.repo.local" );
1726 }
1727
1728 if ( localRepo == null )
1729 {
1730 localRepo = retrieveLocalRepo( settingsFile );
1731 }
1732
1733 if ( localRepo == null )
1734 {
1735 localRepo = System.getProperty( "user.home" ) + "/.m2/repository";
1736 }
1737
1738 File repoDir = new File( localRepo );
1739
1740 if ( !repoDir.exists() )
1741 {
1742
1743 repoDir.mkdirs();
1744 }
1745
1746
1747 localRepo = repoDir.getAbsolutePath();
1748
1749 localRepoLayout = System.getProperty( "maven.repo.local.layout", "default" );
1750 }
1751
1752 private static void runIntegrationTest( Verifier verifier )
1753 throws VerificationException
1754 {
1755 verifier.executeHook( "prebuild-hook.txt" );
1756
1757 Properties properties = verifier.loadProperties( "system.properties" );
1758
1759 Properties controlProperties = verifier.loadProperties( "verifier.properties" );
1760
1761 boolean chokeOnErrorOutput = Boolean.valueOf( controlProperties.getProperty( "failOnErrorOutput", "true" ) );
1762
1763 List<String> goals = verifier.loadFile( verifier.getBasedir(), "goals.txt", false );
1764
1765 List<String> cliOptions = verifier.loadFile( verifier.getBasedir(), "cli-options.txt", false );
1766
1767 verifier.setCliOptions( cliOptions );
1768
1769 verifier.setSystemProperties( properties );
1770
1771 verifier.setVerifierProperties( controlProperties );
1772
1773 verifier.executeGoals( goals );
1774
1775 verifier.executeHook( "postbuild-hook.txt" );
1776
1777 System.out.println( "*** Verifying: fail when [ERROR] detected? " + chokeOnErrorOutput + " ***" );
1778
1779 verifier.verify( chokeOnErrorOutput );
1780
1781 verifier.resetStreams();
1782
1783 System.out.println( "OK" );
1784 }
1785
1786 public void assertArtifactContents( String org, String artifact, String version, String type, String contents )
1787 throws IOException
1788 {
1789 String fileName = getArtifactPath( org, artifact, version, type );
1790 Assert.assertEquals( contents, FileUtils.fileRead( fileName ) );
1791 }
1792
1793 static class UserModelReader
1794 extends DefaultHandler
1795 {
1796 private String localRepository;
1797
1798 private StringBuffer currentBody = new StringBuffer();
1799
1800 public void parse( File file )
1801 throws VerificationException
1802 {
1803 try
1804 {
1805 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
1806
1807 SAXParser parser = saxFactory.newSAXParser();
1808
1809 InputSource is = new InputSource( new FileInputStream( file ) );
1810
1811 parser.parse( is, this );
1812 }
1813 catch ( FileNotFoundException e )
1814 {
1815 throw new VerificationException( "file not found path : " + file.getAbsolutePath(), e );
1816 }
1817 catch ( IOException e )
1818 {
1819 throw new VerificationException( " IOException path : " + file.getAbsolutePath(), e );
1820 }
1821 catch ( ParserConfigurationException e )
1822 {
1823 throw new VerificationException( e );
1824 }
1825 catch ( SAXException e )
1826 {
1827 throw new VerificationException( "Parsing exception for file " + file.getAbsolutePath(), e );
1828 }
1829 }
1830
1831 public void warning( SAXParseException spe )
1832 {
1833 printParseError( "Warning", spe );
1834 }
1835
1836 public void error( SAXParseException spe )
1837 {
1838 printParseError( "Error", spe );
1839 }
1840
1841 public void fatalError( SAXParseException spe )
1842 {
1843 printParseError( "Fatal Error", spe );
1844 }
1845
1846 private void printParseError( String type, SAXParseException spe )
1847 {
1848 System.err.println(
1849 type + " [line " + spe.getLineNumber() + ", row " + spe.getColumnNumber() + "]: " + spe.getMessage() );
1850 }
1851
1852 public String getLocalRepository()
1853 {
1854 return localRepository;
1855 }
1856
1857 public void characters( char[] ch, int start, int length )
1858 throws SAXException
1859 {
1860 currentBody.append( ch, start, length );
1861 }
1862
1863 public void endElement( String uri, String localName, String rawName )
1864 throws SAXException
1865 {
1866 if ( "localRepository".equals( rawName ) )
1867 {
1868 if ( notEmpty( currentBody.toString() ) )
1869 {
1870 localRepository = currentBody.toString().trim();
1871 }
1872 else
1873 {
1874 throw new SAXException(
1875 "Invalid mavenProfile entry. Missing one or more " + "fields: {localRepository}." );
1876 }
1877 }
1878
1879 currentBody = new StringBuffer();
1880 }
1881
1882 private boolean notEmpty( String test )
1883 {
1884 return test != null && test.trim().length() > 0;
1885 }
1886
1887 public void reset()
1888 {
1889 currentBody = null;
1890 localRepository = null;
1891 }
1892 }
1893
1894 public List getCliOptions()
1895 {
1896 return cliOptions;
1897 }
1898
1899 public void setCliOptions( List<String> cliOptions )
1900 {
1901 this.cliOptions = cliOptions;
1902 }
1903
1904 public void addCliOption( String option )
1905 {
1906 cliOptions.add( option );
1907 }
1908
1909 public Properties getSystemProperties()
1910 {
1911 return systemProperties;
1912 }
1913
1914 public void setSystemProperties( Properties systemProperties )
1915 {
1916 this.systemProperties = systemProperties;
1917 }
1918
1919 public void setSystemProperty( String key, String value )
1920 {
1921 if ( value != null )
1922 {
1923 systemProperties.setProperty( key, value );
1924 }
1925 else
1926 {
1927 systemProperties.remove( key );
1928 }
1929 }
1930
1931 public Properties getEnvironmentVariables()
1932 {
1933 return environmentVariables;
1934 }
1935
1936 public void setEnvironmentVariables( Properties environmentVariables )
1937 {
1938 this.environmentVariables = environmentVariables;
1939 }
1940
1941 public void setEnvironmentVariable( String key, String value )
1942 {
1943 if ( value != null )
1944 {
1945 environmentVariables.setProperty( key, value );
1946 }
1947 else
1948 {
1949 environmentVariables.remove( key );
1950 }
1951 }
1952
1953 public Properties getVerifierProperties()
1954 {
1955 return verifierProperties;
1956 }
1957
1958 public void setVerifierProperties( Properties verifierProperties )
1959 {
1960 this.verifierProperties = verifierProperties;
1961 }
1962
1963 public boolean isAutoclean()
1964 {
1965 return autoclean;
1966 }
1967
1968 public void setAutoclean( boolean autoclean )
1969 {
1970 this.autoclean = autoclean;
1971 }
1972
1973 public String getBasedir()
1974 {
1975 return basedir;
1976 }
1977
1978
1979
1980
1981
1982
1983
1984 public String getLogFileName()
1985 {
1986 return this.logFileName;
1987 }
1988
1989
1990
1991
1992
1993
1994
1995
1996 public void setLogFileName( String logFileName )
1997 {
1998 if ( StringUtils.isEmpty( logFileName ) )
1999 {
2000 throw new IllegalArgumentException( "log file name unspecified" );
2001 }
2002 this.logFileName = logFileName;
2003 }
2004
2005 public void setDebug( boolean debug )
2006 {
2007 this.debug = debug;
2008
2009 if ( !debug )
2010 {
2011 System.setOut( new PrintStream( outStream ) );
2012
2013 System.setErr( new PrintStream( errStream ) );
2014 }
2015 }
2016
2017 public boolean isMavenDebug()
2018 {
2019 return mavenDebug;
2020 }
2021
2022 public void setMavenDebug( boolean mavenDebug )
2023 {
2024 this.mavenDebug = mavenDebug;
2025 }
2026
2027 public void setForkJvm( boolean forkJvm )
2028 {
2029 this.forkJvm = forkJvm;
2030 }
2031
2032 public boolean isDebugJvm()
2033 {
2034 return debugJvm;
2035 }
2036
2037 public void setDebugJvm( boolean debugJvm )
2038 {
2039 this.debugJvm = debugJvm;
2040 }
2041
2042 public String getLocalRepoLayout()
2043 {
2044 return localRepoLayout;
2045 }
2046
2047 public void setLocalRepoLayout( String localRepoLayout )
2048 {
2049 this.localRepoLayout = localRepoLayout;
2050 }
2051
2052 }