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