org.apache.maven.shared.utils.cli.Commandline Maven / Gradle / Ivy
The newest version!
package org.apache.maven.shared.utils.cli;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import org.apache.maven.shared.utils.Os;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.shell.BourneShell;
import org.apache.maven.shared.utils.cli.shell.CmdShell;
import org.apache.maven.shared.utils.cli.shell.CommandShell;
import org.apache.maven.shared.utils.cli.shell.Shell;
/**
*
* 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.
*
*
*
* <someelement>
* <acommandline executable="/executable/to/run">
* <argument value="argument 1" />
* <argument line="argument_1 argument_2 argument_3" />
* <argument value="argument 4" />
* </acommandline>
* </someelement>
*
*
*
* The element someelement
must provide a method
* createAcommandline
which returns an instance of this class.
*
*
* @author [email protected]
* @author Stefan Bodewig
*/
public class Commandline
implements Cloneable
{
private final List arguments = new Vector();
//protected Vector envVars = new Vector();
// synchronized added to preserve synchronize of Vector class
private final Map envVars = Collections.synchronizedMap( new LinkedHashMap() );
private Shell shell;
/**
* Create a new command line object.
* Shell is autodetected from operating system
*/
public Commandline( Shell shell )
{
this.shell = shell;
}
/**
* Create a new command line object.
* Shell is autodetected from operating system
*
* @param toProcess The command to process
*/
public Commandline( String toProcess )
{
setDefaultShell();
String[] tmp = new String[0];
try
{
tmp = CommandLineUtils.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++ )
{
createArg().setValue( tmp[i] );
}
}
}
/**
* Create a new command line object.
* Shell is autodetected from operating system
*/
public Commandline()
{
setDefaultShell();
}
/**
* Sets the shell or command-line interpretor for the detected operating system,
* and the shell arguments.
*/
private void setDefaultShell()
{
//If this is windows set the shell to command.com or cmd.exe with correct arguments.
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
{
if ( Os.isFamily( Os.FAMILY_WIN9X ) )
{
setShell( new CommandShell() );
}
else
{
setShell( new CmdShell() );
}
}
else
{
setShell( new BourneShell() );
}
}
/**
* Creates an argument object.
*
* Each commandline object has at most one instance of the
* argument class. This method calls
* this.createArgument(false)
.
*
* @return the argument object.
*/
public Arg createArg()
{
return this.createArg( false );
}
/**
* Creates an argument object and adds it to our list of args.
*
* Each commandline object has at most one instance of the
* argument class.
*
* @param insertAtStart if true, the argument is inserted at the
* beginning of the list of args, otherwise it is appended.
*/
public Arg createArg( boolean insertAtStart )
{
Arg argument = new Argument();
if ( insertAtStart )
{
arguments.add( 0, argument );
}
else
{
arguments.add( argument );
}
return argument;
}
/**
* Sets the executable to run.
*/
public void setExecutable( String executable )
{
shell.setExecutable( executable );
}
public String getExecutable()
{
return shell.getExecutable();
}
public void addArguments( String... line )
{
for ( String aLine : line )
{
createArg().setValue( aLine );
}
}
/**
* Add an environment variable
*/
public void addEnvironment( String name, String value )
{
//envVars.add( name + "=" + value );
envVars.put( name, value );
}
/**
* Add system environment variables
*/
public void addSystemEnvironment()
{
Properties systemEnvVars = CommandLineUtils.getSystemEnvVars();
for ( Object o : systemEnvVars.keySet() )
{
String key = (String) o;
if ( !envVars.containsKey( key ) )
{
addEnvironment( key, systemEnvVars.getProperty( key ) );
}
}
}
/**
* Return the list of environment variables
*/
public String[] getEnvironmentVariables()
{
addSystemEnvironment();
String[] environmentVars = new String[envVars.size()];
int i = 0;
for ( String name : envVars.keySet() )
{
String value = envVars.get( name );
environmentVars[i] = name + "=" + value;
i++;
}
return environmentVars;
}
/**
* Returns the executable and all defined arguments.
*/
public String[] getCommandline()
{
final String[] args = getArguments();
String executable = getExecutable();
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;
}
/**
* @return the shell, executable and all defined arguments without masking any arguments.
*/
private String[] getShellCommandline()
{
return getShellCommandline( false ) ;
}
/**
* @param mask flag to mask any arguments (having his {@code mask} field to {@code true}).
* @return the shell, executable and all defined arguments with masking some arguments if
* {@code mask} parameter is on
*/
private String[] getShellCommandline( boolean mask )
{
List shellCommandLine = getShell().getShellCommandLine( getArguments( mask ) );
return shellCommandLine.toArray( new String[shellCommandLine.size()] );
}
/**
* Returns all arguments defined by addLine
,
* addValue
or the argument object.
*/
public String[] getArguments()
{
return getArguments( false );
}
/**
* Returns all arguments defined by addLine
,
* addValue
or the argument object.
*
* @param mask flag to mask any arguments (having his {@code mask} field to {@code true}).
*/
public String[] getArguments( boolean mask )
{
List result = new ArrayList( arguments.size() * 2 );
for ( Arg argument : arguments )
{
Argument arg = (Argument) argument;
String[] s = arg.getParts();
if ( s != null )
{
if ( mask && ( arg.isMask() ) )
{
// should be a key-pair argument
if ( s.length > 0 )
{
// use a masked copy
String[] copy = new String[s.length];
Arrays.fill( copy, "*****" );
s = copy;
}
}
Collections.addAll( result, s );
}
}
return result.toArray( new String[result.size()] );
}
public String toString()
{
return StringUtils.join( getShellCommandline( true ), " " );
}
public Object clone()
{
throw new RuntimeException( "Do we ever clone a commandline?" );
/* Commandline c = new Commandline( (Shell) shell.clone() );
c.addArguments( getArguments() );
return c;*/
}
/**
* Sets execution directory.
*/
public void setWorkingDirectory( String path )
{
shell.setWorkingDirectory( path );
}
/**
* Sets execution directory.
*/
public void setWorkingDirectory( File workingDirectory )
{
shell.setWorkingDirectory( workingDirectory );
}
public File getWorkingDirectory()
{
return shell.getWorkingDirectory();
}
/**
* Clear out the arguments but leave the executable in place for another operation.
*/
public void clearArgs()
{
arguments.clear();
}
/**
* Executes the command.
*/
public Process execute()
throws CommandLineException
{
Process process;
//addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" );
String[] environment = getEnvironmentVariables();
File workingDir = shell.getWorkingDirectory();
try
{
if ( workingDir == null )
{
process = Runtime.getRuntime().exec( getShellCommandline(), environment );
}
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(), environment, workingDir );
}
}
catch ( IOException ex )
{
throw new CommandLineException( "Error while executing process.", ex );
}
return process;
}
/**
* Allows to set the shell to be used in this command line.
*
* @param shell the shell
*/
void setShell( Shell shell )
{
this.shell = shell;
}
/**
* Get the shell to be used in this command line.
*/
public Shell getShell()
{
return shell;
}
/**
*
*/
public static class Argument
implements Arg
{
private String[] parts;
private boolean mask;
/**
* {@inheritDoc}
*/
public void setValue( String value )
{
if ( value != null )
{
parts = new String[]{ value };
}
}
/**
* {@inheritDoc}
*/
public void setLine( String line )
{
if ( line == null )
{
return;
}
try
{
parts = CommandLineUtils.translateCommandline( line );
}
catch ( Exception e )
{
System.err.println( "Error translating Commandline." );
}
}
/**
* {@inheritDoc}
*/
public void setFile( File value )
{
parts = new String[]{ value.getAbsolutePath() };
}
/**
* {@inheritDoc}
*/
public void setMask( boolean mask )
{
this.mask = mask;
}
private String[] getParts()
{
return parts;
}
public boolean isMask()
{
return mask;
}
}
}