Using Trygve's cli stuff to execute m2 and capture the output so that it can be logged for subsequent perusal.

{issue: MNG-81}


git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@163236 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jason van Zyl 2004-12-05 04:11:07 +00:00
parent aa438b8137
commit fe59dcf689
10 changed files with 1601 additions and 35 deletions

View File

@ -1,29 +1,25 @@
package org.apache.maven.it;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.xpath.XPathAPI;
import org.apache.maven.it.cli.Commandline;
import org.apache.maven.it.cli.CommandLineUtils;
import org.apache.maven.it.cli.StreamConsumer;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xml.utils.DOMBuilder;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Writer;
import java.io.FileWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
@ -37,6 +33,7 @@ public class Verifier
private final String basedir;
private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
private final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
private final PrintStream originalOut;
@ -47,31 +44,38 @@ public class Verifier
this.basedir = basedir;
originalOut = System.out;
System.setOut( new PrintStream( outStream ) );
originalErr = System.err;
System.setErr( new PrintStream( errStream ) );
}
public void resetStreams()
{
System.setOut( originalOut );
System.setErr( originalErr );
}
public void displayStreamBuffers()
{
String out = outStream.toString();
if ( out != null && out.trim().length() > 0 )
{
System.out.println( "----- Standard Out -----" );
System.out.println( out );
}
String err = errStream.toString();
if ( err != null && err.trim().length() > 0 )
{
System.err.println( "----- Standard Error -----" );
System.err.println( err );
}
}
@ -83,9 +87,11 @@ public class Verifier
public void verify() throws VerificationException
{
List lines = loadFile( basedir, "expected-results.txt" );
for ( Iterator i = lines.iterator(); i.hasNext(); )
{
String line = ( String ) i.next();
verifyExpectedResult( line );
}
}
@ -108,12 +114,14 @@ public class Verifier
while ( (line = reader.readLine()) != null )
{
line = line.trim();
if ( line.startsWith( "#" ) || line.length() == 0 )
{
continue;
}
line = replace( line, "${localRepository}", localRepo );
lines.add( line );
}
}
@ -129,6 +137,7 @@ public class Verifier
try
{
File f = new File( basedir, filename );
if ( !f.exists() )
{
return;
@ -139,6 +148,7 @@ public class Verifier
for ( Iterator i = lines.iterator(); i.hasNext(); )
{
String line = ( String ) i.next();
executeCommand( line );
}
}
@ -155,11 +165,15 @@ public class Verifier
private static void executeCommand( String line ) throws VerificationException
{
int index = line.indexOf( " " );
String cmd;
String args = null;
if ( index >= 0 )
{
cmd = line.substring( 0, index );
args = line.substring( index + 1 );
}
else
@ -170,7 +184,9 @@ public class Verifier
if ( cmd.equals( "rm" ) )
{
System.out.println( "Removing file: " + args );
File f = new File( args );
if ( f.exists() && !f.delete() )
{
throw new VerificationException( "Error removing file - delete failed" );
@ -185,15 +201,18 @@ public class Verifier
private static String retrieveLocalRepo()
{
String repo = System.getProperty( "maven.repo.local" );
if ( repo == null )
{
try
{
// parse ~/.m2/override.xml for it...
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File pom = new File( System.getProperty( "user.home" ), ".m2/override.xml" );
Document dom = builder.parse( pom );
repo = XPathAPI.selectSingleNode( dom, "/project/local/repository/text()" ).getNodeValue();
@ -235,6 +254,7 @@ public class Verifier
else
{
File expectedFile = new File( line );
if ( !expectedFile.isAbsolute() && !line.startsWith( "/" ) )
{
expectedFile = new File( basedir, line );
@ -269,10 +289,13 @@ public class Verifier
}
StringBuffer buf = new StringBuffer( text.length() );
int start = 0, end = 0;
while ( (end = text.indexOf( repl, start )) != -1 )
{
buf.append( text.substring( start, end ) ).append( with );
start = end + repl.length();
if ( --max == 0 )
@ -280,40 +303,58 @@ public class Verifier
break;
}
}
buf.append( text.substring( start ) );
return buf.toString();
}
public void executeGoals( String filename ) throws VerificationException
{
String mavenHome = System.getProperty( "maven.home" );
if ( mavenHome == null )
{
throw new VerificationException( "maven.home has not been specified" );
}
List goals = loadFile( basedir, filename );
if ( goals.size() == 0 )
{
throw new VerificationException( "No goals specified" );
}
List allGoals = new ArrayList();
allGoals.add( "clean:clean" );
allGoals.addAll( goals );
int ret = 0;
try
try
{
String prevUserDir = System.getProperty( "user.dir" );
System.setProperty( "user.dir", basedir );
System.setProperty( "classworlds.conf", mavenHome + "/bin/classworlds.conf" );
URL classWorldsUrl = new URL( "file:" + mavenHome + "/core/boot/classworlds-1.1-SNAPSHOT.jar" );
ClassLoader cl = URLClassLoader.newInstance( new URL[] { classWorldsUrl } );
Class c = Class.forName( "org.codehaus.classworlds.Launcher", true, cl );
Method m = c.getMethod( "mainWithExitCode", new Class[] { String[].class } );
Object o = m.invoke( null, new Object[] { allGoals.toArray( new String[0] ) } );
System.setProperty( "user.dir", prevUserDir );
ret = ( ( Integer ) o ).intValue();
Commandline cli = new Commandline();
cli.setWorkingDirectory( basedir );
cli.setExecutable( "m2" );
for ( Iterator i = allGoals.iterator(); i.hasNext(); )
{
cli.createArgument().setValue( (String) i.next() );
}
Writer logWriter = new FileWriter( new File( basedir, "log.txt" ) );
StreamConsumer out = new WriterStreamConsumer( logWriter );
StreamConsumer err = new WriterStreamConsumer( logWriter );
ret = CommandLineUtils.executeCommandLine( cli, out, err );
logWriter.close();
}
catch ( Exception e )
{
@ -323,6 +364,7 @@ public class Verifier
if ( ret > 0 )
{
System.err.println( "Exit code: " + ret );
throw new VerificationException();
}
}
@ -334,17 +376,21 @@ public class Verifier
public static void main( String args[] )
{
String basedir = System.getProperty( "user.dir" );
localRepo = retrieveLocalRepo();
List tests = null;
try
try
{
tests = loadFile( basedir, "integration-tests.txt" );
}
catch ( VerificationException e )
{
System.err.println( "Unable to load integration tests file" );
System.err.println( e.getMessage() );
System.exit( 2 );
}
@ -357,7 +403,7 @@ public class Verifier
for ( Iterator i = tests.iterator(); i.hasNext(); )
{
String test = ( String ) i.next();
String test = ( String ) i.next();
System.out.print( test + "... " );
@ -366,9 +412,11 @@ public class Verifier
try
{
verifier.executeHook( "prebuild-hook.txt" );
verifier.executeGoals( "goals.txt" );
verifier.executeHook( "postbuild-hook.txt" );
verifier.verify();
verifier.resetStreams();
@ -384,9 +432,11 @@ public class Verifier
verifier.displayStreamBuffers();
e.printStackTrace();
exitCode = 1;
}
}
System.exit( exitCode );
}
}

View File

@ -0,0 +1,26 @@
package org.apache.maven.it;
import org.apache.maven.it.cli.StreamConsumer;
import java.io.Writer;
import java.io.PrintWriter;
/**
* @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
* @version $Id$
*/
public class WriterStreamConsumer
implements StreamConsumer
{
private PrintWriter writer;
public WriterStreamConsumer( Writer writer )
{
this.writer = new PrintWriter( writer );
}
public void consumeLine( String s )
{
writer.println( s );
}
}

View File

@ -0,0 +1,43 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
* @version $Id$
*/
public class CommandLineException
extends Exception
{
public CommandLineException( String message )
{
super( message );
}
public CommandLineException( String message, Throwable cause )
{
super( message, cause );
}
}

View File

@ -0,0 +1,146 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import java.io.InputStream;
/**
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l </a>
* @version $Id$
*/
public abstract class CommandLineUtils
{
public static class StringStreamConsumer
implements StreamConsumer
{
private StringBuffer string = new StringBuffer();
private String ls = System.getProperty( "line.separator" );
public void consumeLine( String line )
{
string.append( line + ls );
}
public String getOutput()
{
return string.toString();
}
}
public static int executeCommandLine( Commandline cl, StreamConsumer systemOut, StreamConsumer systemErr )
throws CommandLineException
{
return executeCommandLine( cl, null, systemOut, systemErr );
}
public static int executeCommandLine( Commandline cl, InputStream systemIn, StreamConsumer systemOut, StreamConsumer systemErr )
throws CommandLineException
{
if ( cl == null )
{
throw new IllegalArgumentException( "cl cannot be null." );
}
Process p;
p = cl.execute();
StreamFeeder inputFeeder = null;
if ( systemIn != null )
{
inputFeeder = new StreamFeeder( systemIn, p.getOutputStream() );
}
StreamPumper outputPumper = new StreamPumper( p.getInputStream(), systemOut );
StreamPumper errorPumper = new StreamPumper( p.getErrorStream(), systemErr );
if ( inputFeeder != null )
{
inputFeeder.start();
}
outputPumper.start();
errorPumper.start();
try
{
int returnValue = p.waitFor();
if ( inputFeeder != null )
{
synchronized ( inputFeeder )
{
if ( !inputFeeder.isDone() )
{
inputFeeder.wait();
}
}
}
if ( outputPumper != null)
{
synchronized ( outputPumper )
{
if ( !outputPumper.isDone() )
{
outputPumper.wait();
}
}
}
if ( errorPumper != null )
{
synchronized ( errorPumper )
{
if ( !errorPumper.isDone() )
{
errorPumper.wait();
}
}
}
return returnValue;
}
catch ( InterruptedException ex )
{
throw new CommandLineException( "Error while executing external command.", ex );
}
finally
{
if ( inputFeeder != null )
{
inputFeeder.close();
}
outputPumper.close();
errorPumper.close();
}
}
}

View File

@ -0,0 +1,650 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001-2003, ThoughtWorks, Inc.
* 651 W Washington Ave. Suite 500
* Chicago, IL 60661 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
/* ====================================================================
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
import java.io.File;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Commandline objects help handling command lines specifying processes to
* execute.
*
* The class can be used to define a command line as nested elements or as a
* helper to define a command line by an application.
* <p>
* <code>
* &lt;someelement&gt;<br>
* &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
* &nbsp;&nbsp;&lt;/acommandline&gt;<br>
* &lt;/someelement&gt;<br>
* </code>
* The element <code>someelement</code> must provide a method
* <code>createAcommandline</code> which returns an instance of this class.
*
* @author thomas.haas@softwired-inc.com
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/
public class Commandline
implements Cloneable
{
protected static final String OS_NAME = "os.name";
protected static final String WINDOWS = "Windows";
private String shell = null;
private Vector shellArgs = new Vector();
protected String executable = null;
protected Vector arguments = new Vector();
private File workingDir = null;
public Commandline( String toProcess )
{
super();
setDefaultShell();
String[] tmp = new String[0];
try
{
tmp = translateCommandline( toProcess );
}
catch ( Exception e )
{
System.err.println( "Error translating Commandline." );
}
if ( tmp != null && tmp.length > 0 )
{
setExecutable( tmp[0] );
for ( int i = 1; i < tmp.length; i++ )
{
createArgument().setValue( tmp[i] );
}
}
}
public Commandline()
{
super();
setDefaultShell();
}
/**
* Used for nested xml command line definitions.
*/
public static class Argument
{
private String[] parts;
/**
* Sets a single commandline argument.
*
* @param value a single commandline argument.
*/
public void setValue( String value )
{
parts = new String[]{value};
}
/**
* Line to split into several commandline arguments.
*
* @param line line to split into several commandline arguments
*/
public void setLine( String line )
{
if ( line == null )
{
return;
}
try
{
parts = translateCommandline( line );
}
catch ( Exception e )
{
System.err.println( "Error translating Commandline." );
}
}
/**
* Sets a single commandline argument to the absolute filename
* of the given file.
*
* @param value a single commandline argument.
*/
public void setFile( File value )
{
parts = new String[]{value.getAbsolutePath()};
}
/**
* Returns the parts this Argument consists of.
*/
public String[] getParts()
{
return parts;
}
}
/**
* Class to keep track of the position of an Argument.
*/
// <p>This class is there to support the srcfile and targetfile
// elements of &lt;execon&gt; and &lt;transform&gt; - don't know
// whether there might be additional use cases.</p> --SB
public class Marker
{
private int position;
private int realPos = -1;
Marker( int position )
{
this.position = position;
}
/**
* Return the number of arguments that preceeded this marker.
*
* <p>The name of the executable - if set - is counted as the
* very first argument.</p>
*/
public int getPosition()
{
if ( realPos == -1 )
{
realPos = ( executable == null ? 0 : 1 );
for ( int i = 0; i < position; i++ )
{
Argument arg = (Argument) arguments.elementAt( i );
realPos += arg.getParts().length;
}
}
return realPos;
}
}
/**
* <p>Sets the shell or command-line interpretor for the detected operating system,
* and the shell arguments.</p>
*/
private void setDefaultShell() {
String os = System.getProperty(OS_NAME);
//If this is windows set the shell to command.com or cmd.exe with correct arguments.
if ( os.indexOf(WINDOWS) != -1 )
{
if (os.indexOf("95") != -1 || os.indexOf("98") != -1 || os.indexOf("Me") != -1)
{
shell = "COMMAND.COM";
shellArgs.add("/C");
}
else
{
shell = "CMD.EXE";
shellArgs.add("/X");
shellArgs.add("/C");
}
}
}
/**
* Creates an argument object.
*
* <p>Each commandline object has at most one instance of the
* argument class. This method calls
* <code>this.createArgument(false)</code>.</p>
*
* @see #createArgument(boolean)
* @return the argument object.
*/
public Argument createArgument()
{
return this.createArgument( false );
}
/**
* Creates an argument object and adds it to our list of args.
*
* <p>Each commandline object has at most one instance of the
* argument class.</p>
*
* @param insertAtStart if true, the argument is inserted at the
* beginning of the list of args, otherwise it is appended.
*/
public Argument createArgument( boolean insertAtStart )
{
Argument argument = new Argument();
if ( insertAtStart )
{
arguments.insertElementAt( argument, 0 );
}
else
{
arguments.addElement( argument );
}
return argument;
}
/**
* Sets the executable to run.
*/
public void setExecutable( String executable )
{
if ( executable == null || executable.length() == 0 )
{
return;
}
this.executable =
executable.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
}
public String getExecutable()
{
return executable;
}
public void addArguments( String[] line )
{
for ( int i = 0; i < line.length; i++ )
{
createArgument().setValue( line[i] );
}
}
/**
* Returns the executable and all defined arguments.
*/
public String[] getCommandline()
{
final String[] args = getArguments();
if ( executable == null )
{
return args;
}
final String[] result = new String[args.length + 1];
result[0] = executable;
System.arraycopy( args, 0, result, 1, args.length );
return result;
}
/**
* Returns the shell, executable and all defined arguments.
*/
public String[] getShellCommandline()
{
int shellCount = 0;
int arrayPos = 0;
if ( shell != null )
{
shellCount = 1;
}
shellCount += shellArgs.size();
final String[] args = getArguments();
String[] result = new String[shellCount + args.length + (( executable == null )? 0:1)];
//Build shell and arguments into result
if ( shell != null )
{
result[0] = shell;
arrayPos++;
}
System.arraycopy( shellArgs.toArray(), 0, result, arrayPos, shellArgs.size() );
arrayPos += shellArgs.size();
//Build excutable and arguments into result
if ( executable != null )
{
result[arrayPos] = executable;
arrayPos++;
}
System.arraycopy( args, 0, result, arrayPos, args.length );
return result;
}
/**
* Returns all arguments defined by <code>addLine</code>,
* <code>addValue</code> or the argument object.
*/
public String[] getArguments()
{
Vector result = new Vector( arguments.size() * 2 );
for ( int i = 0; i < arguments.size(); i++ )
{
Argument arg = (Argument) arguments.elementAt( i );
String[] s = arg.getParts();
if ( s != null )
{
for ( int j = 0; j < s.length; j++ )
{
result.addElement( s[j] );
}
}
}
String[] res = new String[result.size()];
result.copyInto( res );
return res;
}
public String toString()
{
return toString( getCommandline() );
}
/**
* Put quotes around the given String if necessary.
*
* <p>If the argument doesn't include spaces or quotes, return it
* as is. If it contains double quotes, use single quotes - else
* surround the argument by double quotes.</p>
*
* @exception CommandLineException if the argument contains both, single
* and double quotes.
*/
public static String quoteArgument( String argument ) throws CommandLineException
{
if ( argument.indexOf( "\"" ) > -1 )
{
if ( argument.indexOf( "\'" ) > -1 )
{
throw new CommandLineException( "Can't handle single and double quotes in same argument" );
}
else
{
return '\'' + argument + '\'';
}
}
else if ( argument.indexOf( "\'" ) > -1 || argument.indexOf( " " ) > -1 )
{
return '\"' + argument + '\"';
}
else
{
return argument;
}
}
public static String toString( String[] line )
{
// empty path return empty string
if ( line == null || line.length == 0 )
{
return "";
}
// path containing one or more elements
final StringBuffer result = new StringBuffer();
for ( int i = 0; i < line.length; i++ )
{
if ( i > 0 )
{
result.append( ' ' );
}
try
{
result.append( quoteArgument( line[i] ) );
}
catch ( Exception e )
{
System.err.println( "Error quoting argument." );
}
}
return result.toString();
}
public static String[] translateCommandline( String toProcess ) throws Exception
{
if ( toProcess == null || toProcess.length() == 0 )
{
return new String[0];
}
// parse with a simple finite state machine
final int normal = 0;
final int inQuote = 1;
final int inDoubleQuote = 2;
int state = normal;
StringTokenizer tok = new StringTokenizer( toProcess, "\"\' ", true );
Vector v = new Vector();
StringBuffer current = new StringBuffer();
while ( tok.hasMoreTokens() )
{
String nextTok = tok.nextToken();
switch ( state )
{
case inQuote:
if ( "\'".equals( nextTok ) )
{
state = normal;
}
else
{
current.append( nextTok );
}
break;
case inDoubleQuote:
if ( "\"".equals( nextTok ) )
{
state = normal;
}
else
{
current.append( nextTok );
}
break;
default :
if ( "\'".equals( nextTok ) )
{
state = inQuote;
}
else if ( "\"".equals( nextTok ) )
{
state = inDoubleQuote;
}
else if ( " ".equals( nextTok ) )
{
if ( current.length() != 0 )
{
v.addElement( current.toString() );
current.setLength( 0 );
}
}
else
{
current.append( nextTok );
}
break;
}
}
if ( current.length() != 0 )
{
v.addElement( current.toString() );
}
if ( state == inQuote || state == inDoubleQuote )
{
throw new CommandLineException( "unbalanced quotes in " + toProcess );
}
String[] args = new String[v.size()];
v.copyInto( args );
return args;
}
public int size()
{
return getCommandline().length;
}
public Object clone()
{
Commandline c = new Commandline();
c.setExecutable( executable );
c.addArguments( getArguments() );
return c;
}
/**
* Clear out the whole command line. */
public void clear()
{
executable = null;
arguments.removeAllElements();
}
/**
* Clear out the arguments but leave the executable in place for another operation.
*/
public void clearArgs()
{
arguments.removeAllElements();
}
/**
* Return a marker.
*
* <p>This marker can be used to locate a position on the
* commandline - to insert something for example - when all
* parameters have been set.</p>
*/
public Marker createMarker()
{
return new Marker( arguments.size() );
}
/**
* Sets execution directory.
*/
public void setWorkingDirectory( String path )
{
if ( path != null )
{
workingDir = new File( path );
}
}
public File getWorkingDirectory()
{
return workingDir;
}
/**
* Executes the command.
*/
public Process execute()
throws CommandLineException
{
Process process = null;
try
{
if ( workingDir == null )
{
process = Runtime.getRuntime().exec( getShellCommandline() );
}
else
{
if ( !workingDir.exists() )
{
throw new CommandLineException( "Working directory \"" + workingDir.getPath() + "\" does not exist!" );
}
else if ( !workingDir.isDirectory() )
{
throw new CommandLineException( "Path \"" + workingDir.getPath() + "\" does not specify a directory." );
}
process = Runtime.getRuntime().exec( getShellCommandline(), null, workingDir );
}
}
catch( IOException ex )
{
throw new CommandLineException( "Error while executing process.", ex );
}
return process;
}
}

View File

@ -0,0 +1,55 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* ====================================================================
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
/**
* @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
* @version $Id$
*/
public class DefaultConsumer
implements StreamConsumer
{
public void consumeLine(String line)
{
System.out.println(line);
}
}

View File

@ -0,0 +1,150 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* ====================================================================
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
import java.util.StringTokenizer;
/**
* The java.util.StringTokenizer is horribly broken.
* Given the string 1,,,3,,4 (, delim)
* It will return 1,3,4
* Which is clearly wrong - 1,EMPTY,EMPTY,3,EMPTY,4 is what it should return
*/
public final class EnhancedStringTokenizer
{
private StringTokenizer cst = null;
String cdelim;
final boolean cdelimSingleChar;
final char cdelimChar;
boolean creturnDelims;
String lastToken = null;
boolean delimLast = true;
public EnhancedStringTokenizer(String str)
{
this(str, " \t\n\r\f", false);
}
public EnhancedStringTokenizer(String str, String delim)
{
this(str, delim, false);
}
public EnhancedStringTokenizer(String str, String delim, boolean returnDelims)
{
cst = new StringTokenizer(str, delim, true);
cdelim = delim;
creturnDelims = returnDelims;
cdelimSingleChar = (delim.length() == 1);
cdelimChar = delim.charAt(0);
}
public boolean hasMoreTokens()
{
return cst.hasMoreTokens();
}
private String internalNextToken()
{
if (lastToken != null)
{
String last = lastToken;
lastToken = null;
return last;
}
String token = cst.nextToken();
if (isDelim(token))
{
if (delimLast)
{
lastToken = token;
return "";
}
else
{
delimLast = true;
return token;
}
}
else
{
delimLast = false;
return token;
}
}
public String nextToken()
{
String token = internalNextToken();
if (creturnDelims)
return token;
if (isDelim(token))
return hasMoreTokens() ? internalNextToken() : "";
else
return token;
}
private boolean isDelim(String str)
{
if (str.length() == 1)
{
char ch = str.charAt(0);
if (cdelimSingleChar)
{
if (cdelimChar == ch)
{
return true;
}
}
else
{
if (cdelim.indexOf(ch) >= 0)
{
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,78 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2003, ThoughtWorks, Inc.
* 651 W Washington Ave. Suite 500
* Chicago, IL 60661 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
/**
* Works in concert with the StreamPumper class to
* allow implementations to gain access to the lines being
* "Pumped".
*
* @author <a href="mailto:fvancea@maxiq.com">Florin Vancea</a>
* @author <a href="mailto:pj@thoughtworks.com">Paul Julius</a>
*/
public interface StreamConsumer
{
/**
* Called when the StreamPumper pumps a line from the Stream.
*/
public void consumeLine( String line );
}

View File

@ -0,0 +1,143 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
* @version $Id$
*/
public class StreamFeeder
extends Thread
{
private InputStream input;
private OutputStream output;
private boolean done;
public StreamFeeder( InputStream input, OutputStream output )
{
this.input = input;
this.output = output;
}
// ----------------------------------------------------------------------
// Runnable implementation
// ----------------------------------------------------------------------
public void run()
{
try
{
feed();
}
catch ( Throwable ex )
{
// Catched everything so the streams will be closed and flagged as done.
}
finally
{
close();
done = true;
synchronized ( this )
{
this.notifyAll();
}
}
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
public void close()
{
if ( input != null )
{
synchronized ( input )
{
try
{
input.close();
}
catch ( IOException ex )
{
// ignore
}
input = null;
}
}
if ( output != null )
{
synchronized ( output )
{
try
{
output.close();
}
catch ( IOException ex )
{
// ignore
}
output = null;
}
}
}
public boolean isDone()
{
return done;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
private void feed()
throws IOException
{
int data = input.read();
while ( !done && data != -1 )
{
synchronized ( output )
{
output.write( data );
data = input.read();
}
}
}
}

View File

@ -0,0 +1,225 @@
package org.apache.maven.it.cli;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001-2003, ThoughtWorks, Inc.
* 651 W Washington Ave. Suite 500
* Chicago, IL 60661 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
/* ====================================================================
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
/**
* Class to pump the error stream during Process's runtime. Copied from the Ant
* built-in task.
*
* @author <a href="mailto:fvancea@maxiq.com">Florin Vancea </a>
* @author <a href="mailto:pj@thoughtworks.com">Paul Julius </a>
* @since June 11, 2001
*/
public class StreamPumper
extends Thread
{
private BufferedReader in;
private StreamConsumer consumer = null;
private PrintWriter out = null;
private static final int SIZE = 1024;
boolean done;
public StreamPumper( InputStream in )
{
this.in = new BufferedReader( new InputStreamReader( in ), SIZE );
}
public StreamPumper( InputStream in, StreamConsumer consumer )
{
this( in );
this.consumer = consumer;
}
public StreamPumper( InputStream in, PrintWriter writer )
{
this( in );
out = writer;
}
public StreamPumper( InputStream in, PrintWriter writer, StreamConsumer consumer )
{
this( in );
this.out = writer;
this.consumer = consumer;
}
public void run()
{
try
{
String s = in.readLine();
while ( s != null )
{
consumeLine( s );
if ( out != null )
{
out.println( s );
out.flush();
}
s = in.readLine();
}
}
catch ( Throwable e )
{
// Catched everything so the streams will be closed and flagged as done.
}
finally
{
closeInputStream( in );
done = true;
synchronized ( this )
{
this.notifyAll();
}
}
}
public void flush()
{
if ( out != null )
{
out.flush();
}
}
public void close()
{
closeOutputStream( out );
}
protected void closeInputStream( Reader in )
{
if ( in == null )
{
return;
}
try
{
in.close();
}
catch ( IOException e )
{
// do nothing
}
}
protected void closeOutputStream( PrintWriter out )
{
if ( out == null )
{
return;
}
out.close();
}
public boolean isDone()
{
return done;
}
private void consumeLine( String line )
{
if ( consumer != null )
{
consumer.consumeLine( line );
}
}
}