| 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 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; |
| |
| /** |
| * <p/> |
| * Commandline objects help handling command lines specifying processes to |
| * execute. |
| * </p> |
| * <p/> |
| * 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> |
| * <p/> |
| * <code> |
| * <someelement><br> |
| * <acommandline executable="/executable/to/run"><br> |
| * <argument value="argument 1" /><br> |
| * <argument line="argument_1 argument_2 argument_3" /><br> |
| * <argument value="argument 4" /><br> |
| * </acommandline><br> |
| * </someelement><br> |
| * </code> |
| * </p> |
| * <p/> |
| * The element <code>someelement</code> must provide a method |
| * <code>createAcommandline</code> which returns an instance of this class. |
| * </p> |
| * |
| * @author thomas.haas@softwired-inc.com |
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> |
| */ |
| public class Commandline |
| implements Cloneable |
| { |
| private final List<Argument> arguments = new ArrayList<>(); |
| |
| //protected Vector envVars = new Vector(); |
| // synchronized added to preserve synchronize of Vector class |
| private final Map<String, String> envVars = Collections.synchronizedMap( new LinkedHashMap<String, String>() ); |
| |
| private Shell shell; |
| |
| /** |
| * Create a new command line object. |
| * Shell is autodetected from operating system |
| * @param shell The shell instance. |
| */ |
| 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 ) throws CommandLineException |
| { |
| setDefaultShell(); |
| String[] tmp = CommandLineUtils.translateCommandline( toProcess ); |
| if ( 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(); |
| } |
| |
| /** |
| * <p>Sets the shell or command-line interpretor for the detected operating system, |
| * and the shell arguments.</p> |
| */ |
| 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. |
| * <p/> |
| * <p>Each commandline object has at most one instance of the |
| * argument class. This method calls |
| * <code>this.createArgument(false)</code>.</p> |
| * |
| * @return the argument object. |
| */ |
| public Arg createArg() |
| { |
| return this.createArg( false ); |
| } |
| |
| /** |
| * Creates an argument object and adds it to our list of args. |
| * <p/> |
| * <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. |
| * @return The arguments. |
| */ |
| public Arg createArg( boolean insertAtStart ) |
| { |
| Argument argument = new Argument(); |
| if ( insertAtStart ) |
| { |
| arguments.add( 0, argument ); |
| } |
| else |
| { |
| arguments.add( argument ); |
| } |
| return argument; |
| } |
| |
| /** |
| * Sets the executable to run. |
| * @param executable The executable. |
| */ |
| public void setExecutable( String executable ) |
| { |
| shell.setExecutable( executable ); |
| } |
| |
| /** |
| * @return The executable. |
| */ |
| public String getExecutable() |
| { |
| |
| return shell.getExecutable(); |
| } |
| |
| /** |
| * @param line The arguments. |
| */ |
| public void addArguments( String... line ) |
| { |
| for ( String aLine : line ) |
| { |
| createArg().setValue( aLine ); |
| } |
| } |
| |
| /** |
| * Add an environment variable |
| * @param name The name of the environment variable. |
| * @param value The appropriate value. |
| */ |
| 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 |
| * @return an array of all 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. |
| * @return an array of all arguments incl. executable. |
| */ |
| 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<String> shellCommandLine = getShell().getShellCommandLine( getArguments( mask ) ); |
| return shellCommandLine.toArray( new String[shellCommandLine.size()] ); |
| } |
| |
| /** |
| * Returns all arguments defined by <code>addLine</code>, |
| * <code>addValue</code> or the argument object. |
| * @return an array of arguments. |
| */ |
| public String[] getArguments() |
| { |
| return getArguments( false ); |
| } |
| |
| /** |
| * Returns all arguments defined by <code>addLine</code>, |
| * <code>addValue</code> or the argument object. |
| * |
| * @param mask flag to mask any arguments (having his {@code mask} field to {@code true}). |
| * @return an array of arguments. |
| */ |
| public String[] getArguments( boolean mask ) |
| { |
| List<String> result = new ArrayList<>( arguments.size() * 2 ); |
| for ( Argument arg : arguments ) |
| { |
| 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()] ); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return StringUtils.join( getShellCommandline( true ), " " ); |
| } |
| |
| @Override |
| 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 working directory. |
| * @param path The to be set as working directory. |
| */ |
| public void setWorkingDirectory( String path ) |
| { |
| shell.setWorkingDirectory( path ); |
| } |
| |
| /** |
| * Sets execution directory. |
| * @param workingDirectory The working directory. |
| */ |
| public void setWorkingDirectory( File workingDirectory ) |
| { |
| shell.setWorkingDirectory( workingDirectory ); |
| } |
| |
| /** |
| * @return The working directory. |
| */ |
| 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. |
| * @return The process. |
| * @throws CommandLineException in case of errors. |
| */ |
| 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. |
| * @return the shell. |
| */ |
| public Shell getShell() |
| { |
| return shell; |
| } |
| |
| /** |
| * |
| */ |
| public static class Argument |
| implements Arg |
| { |
| private String[] parts; |
| |
| private boolean mask; |
| |
| @Override |
| public void setValue( String value ) |
| { |
| if ( value != null ) |
| { |
| parts = new String[]{ value }; |
| } |
| } |
| |
| @Override |
| public void setLine( String line ) throws CommandLineException |
| { |
| if ( line == null ) |
| { |
| return; |
| } |
| try |
| { |
| parts = CommandLineUtils.translateCommandline( line ); |
| } |
| catch ( CommandLineException e ) |
| { |
| System.err.println( "Error translating Commandline." ); |
| throw( e ); |
| } |
| } |
| |
| @Override |
| public void setFile( File value ) |
| { |
| parts = new String[]{ value.getAbsolutePath() }; |
| } |
| |
| @Override |
| public void setMask( boolean mask ) |
| { |
| this.mask = mask; |
| } |
| |
| /** |
| * @return The parts. |
| */ |
| private String[] getParts() |
| { |
| return parts; |
| } |
| |
| /** |
| * @return true/false |
| */ |
| public boolean isMask() |
| { |
| return mask; |
| } |
| } |
| } |