Coverage Report - org.apache.maven.shared.utils.cli.Commandline
 
Classes in this File Line Coverage Branch Coverage Complexity
Commandline
20%
21/102
12%
4/32
2.036
Commandline$Argument
35%
5/14
25%
1/4
2.036
 
 1  
 package org.apache.maven.shared.utils.cli;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collections;
 26  
 import java.util.LinkedHashMap;
 27  
 import java.util.List;
 28  
 import java.util.Map;
 29  
 import java.util.Properties;
 30  
 import java.util.Vector;
 31  
 
 32  
 import org.apache.maven.shared.utils.Os;
 33  
 import org.apache.maven.shared.utils.StringUtils;
 34  
 import org.apache.maven.shared.utils.cli.shell.BourneShell;
 35  
 import org.apache.maven.shared.utils.cli.shell.CmdShell;
 36  
 import org.apache.maven.shared.utils.cli.shell.CommandShell;
 37  
 import org.apache.maven.shared.utils.cli.shell.Shell;
 38  
 
 39  
 /**
 40  
  * <p/>
 41  
  * Commandline objects help handling command lines specifying processes to
 42  
  * execute.
 43  
  * </p>
 44  
  * <p/>
 45  
  * The class can be used to define a command line as nested elements or as a
 46  
  * helper to define a command line by an application.
 47  
  * </p>
 48  
  * <p/>
 49  
  * <code>
 50  
  * &lt;someelement&gt;<br>
 51  
  * &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
 52  
  * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
 53  
  * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
 54  
  * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
 55  
  * &nbsp;&nbsp;&lt;/acommandline&gt;<br>
 56  
  * &lt;/someelement&gt;<br>
 57  
  * </code>
 58  
  * </p>
 59  
  * <p/>
 60  
  * The element <code>someelement</code> must provide a method
 61  
  * <code>createAcommandline</code> which returns an instance of this class.
 62  
  * </p>
 63  
  *
 64  
  * @author thomas.haas@softwired-inc.com
 65  
  * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
 66  
  */
 67  
 public class Commandline
 68  
     implements Cloneable
 69  
 {
 70  4
     private final List<Arg> arguments = new Vector<Arg>();
 71  
 
 72  
     //protected Vector envVars = new Vector();
 73  
     // synchronized added to preserve synchronize of Vector class
 74  4
     private final Map<String,String> envVars = Collections.synchronizedMap( new LinkedHashMap<String,String>() );
 75  
 
 76  
     private Shell shell;
 77  
 
 78  
     /**
 79  
      * Create a new command line object.
 80  
      * Shell is autodetected from operating system
 81  
      */
 82  
     public Commandline( Shell shell )
 83  4
     {
 84  4
         this.shell = shell;
 85  4
     }
 86  
 
 87  
     /**
 88  
      * Create a new command line object.
 89  
      * Shell is autodetected from operating system
 90  
      *
 91  
      * @param toProcess  The command to process
 92  
      */
 93  
     public Commandline( String toProcess )
 94  0
     {
 95  0
         setDefaultShell();
 96  0
         String[] tmp = new String[0];
 97  
         try
 98  
         {
 99  0
             tmp = CommandLineUtils.translateCommandline( toProcess );
 100  
         }
 101  0
         catch ( Exception e )
 102  
         {
 103  0
             System.err.println( "Error translating Commandline." );
 104  0
         }
 105  0
         if ( ( tmp != null ) && ( tmp.length > 0 ) )
 106  
         {
 107  0
             setExecutable( tmp[0] );
 108  0
             for ( int i = 1; i < tmp.length; i++ )
 109  
             {
 110  0
                 createArg().setValue( tmp[i] );
 111  
             }
 112  
         }
 113  0
     }
 114  
 
 115  
     /**
 116  
      * Create a new command line object.
 117  
      * Shell is autodetected from operating system
 118  
      */
 119  
     public Commandline()
 120  0
     {
 121  0
         setDefaultShell();
 122  0
     }
 123  
 
 124  
     /**
 125  
      * <p>Sets the shell or command-line interpretor for the detected operating system,
 126  
      * and the shell arguments.</p>
 127  
      */
 128  
     private void setDefaultShell()
 129  
     {
 130  
         //If this is windows set the shell to command.com or cmd.exe with correct arguments.
 131  0
         if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
 132  
         {
 133  0
             if ( Os.isFamily( Os.FAMILY_WIN9X ) )
 134  
             {
 135  0
                 setShell( new CommandShell() );
 136  
             }
 137  
             else
 138  
             {
 139  0
                 setShell( new CmdShell() );
 140  
             }
 141  
         }
 142  
         else
 143  
         {
 144  0
             setShell( new BourneShell() );
 145  
         }
 146  0
     }
 147  
 
 148  
     /**
 149  
      * Creates an argument object.
 150  
      * <p/>
 151  
      * <p>Each commandline object has at most one instance of the
 152  
      * argument class.  This method calls
 153  
      * <code>this.createArgument(false)</code>.</p>
 154  
      *
 155  
      * @return the argument object.
 156  
      */
 157  
     public Arg createArg()
 158  
     {
 159  25
         return this.createArg( false );
 160  
     }
 161  
 
 162  
     /**
 163  
      * Creates an argument object and adds it to our list of args.
 164  
      * <p/>
 165  
      * <p>Each commandline object has at most one instance of the
 166  
      * argument class.</p>
 167  
      *
 168  
      * @param insertAtStart if true, the argument is inserted at the
 169  
      *                      beginning of the list of args, otherwise it is appended.
 170  
      */
 171  
     public Arg createArg( boolean insertAtStart )
 172  
     {
 173  25
         Arg argument = new Argument();
 174  25
         if ( insertAtStart )
 175  
         {
 176  0
             arguments.add( 0, argument );
 177  
         }
 178  
         else
 179  
         {
 180  25
             arguments.add( argument );
 181  
         }
 182  25
         return argument;
 183  
     }
 184  
 
 185  
     /**
 186  
      * Sets the executable to run.
 187  
      */
 188  
     public void setExecutable( String executable )
 189  
     {
 190  3
         shell.setExecutable( executable );
 191  3
     }
 192  
 
 193  
     public String getExecutable()
 194  
     {
 195  
 
 196  0
         return shell.getExecutable();
 197  
     }
 198  
 
 199  
     public void addArguments( String... line )
 200  
     {
 201  0
         for ( String aLine : line )
 202  
         {
 203  0
             createArg().setValue( aLine );
 204  
         }
 205  0
     }
 206  
 
 207  
     /**
 208  
      * Add an environment variable
 209  
      */
 210  
     public void addEnvironment( String name, String value )
 211  
     {
 212  
         //envVars.add( name + "=" + value );
 213  0
         envVars.put( name, value );
 214  0
     }
 215  
 
 216  
     /**
 217  
      * Add system environment variables
 218  
      */
 219  
     public void addSystemEnvironment()
 220  
         throws Exception
 221  
     {
 222  0
         Properties systemEnvVars = CommandLineUtils.getSystemEnvVars();
 223  
 
 224  0
         for ( Object o : systemEnvVars.keySet() )
 225  
         {
 226  0
             String key = (String) o;
 227  0
             if ( !envVars.containsKey( key ) )
 228  
             {
 229  0
                 addEnvironment( key, systemEnvVars.getProperty( key ) );
 230  
             }
 231  0
         }
 232  0
     }
 233  
 
 234  
     /**
 235  
      * Return the list of environment variables
 236  
      */
 237  
     public String[] getEnvironmentVariables()
 238  
         throws CommandLineException
 239  
     {
 240  
         try
 241  
         {
 242  0
             addSystemEnvironment();
 243  
         }
 244  0
         catch ( Exception e )
 245  
         {
 246  0
             throw new CommandLineException( "Error setting up environmental variables", e );
 247  0
         }
 248  0
         String[] environmentVars = new String[envVars.size()];
 249  0
         int i = 0;
 250  0
         for ( String name : envVars.keySet() )
 251  
         {
 252  0
             String value = envVars.get( name );
 253  0
             environmentVars[i] = name + "=" + value;
 254  0
             i++;
 255  0
         }
 256  0
         return environmentVars;
 257  
     }
 258  
 
 259  
     /**
 260  
      * Returns the executable and all defined arguments.
 261  
      */
 262  
     public String[] getCommandline()
 263  
     {
 264  0
         final String[] args = getArguments();
 265  0
         String executable = getExecutable();
 266  
 
 267  0
         if ( executable == null )
 268  
         {
 269  0
             return args;
 270  
         }
 271  0
         final String[] result = new String[args.length + 1];
 272  0
         result[0] = executable;
 273  0
         System.arraycopy( args, 0, result, 1, args.length );
 274  0
         return result;
 275  
     }
 276  
 
 277  
     /**
 278  
      * Returns the shell, executable and all defined arguments.
 279  
      */
 280  
     private String[] getShellCommandline()
 281  
     {
 282  0
         List<String> shellCommandLine = getShell().getShellCommandLine( getArguments() );
 283  0
         return shellCommandLine.toArray( new String[shellCommandLine.size()] );
 284  
     }
 285  
 
 286  
     /**
 287  
      * Returns all arguments defined by <code>addLine</code>,
 288  
      * <code>addValue</code> or the argument object.
 289  
      */
 290  
     public String[] getArguments()
 291  
     {
 292  4
         List<String> result = new ArrayList<String>( arguments.size() * 2 );
 293  4
         for ( Arg argument : arguments )
 294  
         {
 295  25
             Argument arg = (Argument) argument;
 296  25
             String[] s = arg.getParts();
 297  25
             if ( s != null )
 298  
             {
 299  25
                 Collections.addAll( result, s );
 300  
             }
 301  25
         }
 302  
 
 303  4
         return result.toArray( new String[result.size()] );
 304  
     }
 305  
 
 306  
     public String toString()
 307  
     {
 308  0
         return StringUtils.join( getShellCommandline(), " " );
 309  
     }
 310  
 
 311  
 
 312  
     public Object clone()
 313  
     {
 314  0
         throw new RuntimeException( "Do we ever clone a commandline?" );
 315  
 /*        Commandline c = new Commandline( (Shell) shell.clone() );
 316  
        c.addArguments( getArguments() );
 317  
         return c;*/
 318  
     }
 319  
 
 320  
     /**
 321  
      * Sets execution directory.
 322  
      */
 323  
     public void setWorkingDirectory( String path )
 324  
     {
 325  0
         shell.setWorkingDirectory( path );
 326  0
     }
 327  
 
 328  
     /**
 329  
      * Sets execution directory.
 330  
      */
 331  
     public void setWorkingDirectory( File workingDirectory )
 332  
     {
 333  0
         shell.setWorkingDirectory( workingDirectory );
 334  0
     }
 335  
 
 336  
     public File getWorkingDirectory()
 337  
     {
 338  0
         return shell.getWorkingDirectory();
 339  
     }
 340  
 
 341  
     /**
 342  
      * Clear out the arguments but leave the executable in place for another operation.
 343  
      */
 344  
     public void clearArgs()
 345  
     {
 346  0
         arguments.clear();
 347  0
     }
 348  
 
 349  
     /**
 350  
      * Executes the command.
 351  
      */
 352  
     public Process execute()
 353  
         throws CommandLineException
 354  
     {
 355  
         Process process;
 356  
 
 357  
         //addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" );
 358  
 
 359  0
         String[] environment = getEnvironmentVariables();
 360  
 
 361  0
         File workingDir = shell.getWorkingDirectory();
 362  
 
 363  
         try
 364  
         {
 365  0
             if ( workingDir == null )
 366  
             {
 367  0
                 process = Runtime.getRuntime().exec( getShellCommandline(), environment );
 368  
             }
 369  
             else
 370  
             {
 371  0
                 if ( !workingDir.exists() )
 372  
                 {
 373  0
                     throw new CommandLineException(
 374  
                         "Working directory \"" + workingDir.getPath() + "\" does not exist!" );
 375  
                 }
 376  0
                 else if ( !workingDir.isDirectory() )
 377  
                 {
 378  0
                     throw new CommandLineException(
 379  
                         "Path \"" + workingDir.getPath() + "\" does not specify a directory." );
 380  
                 }
 381  
 
 382  0
                 process = Runtime.getRuntime().exec( getShellCommandline(), environment, workingDir );
 383  
             }
 384  
         }
 385  0
         catch ( IOException ex )
 386  
         {
 387  0
             throw new CommandLineException( "Error while executing process.", ex );
 388  0
         }
 389  
 
 390  0
         return process;
 391  
     }
 392  
 
 393  
     /**
 394  
      * Allows to set the shell to be used in this command line.
 395  
      *
 396  
      * @param shell the shell
 397  
      * 
 398  
      */
 399  
     void setShell( Shell shell )
 400  
     {
 401  0
         this.shell = shell;
 402  0
     }
 403  
 
 404  
     /**
 405  
      * Get the shell to be used in this command line.
 406  
      *
 407  
      * 
 408  
      */
 409  
     public Shell getShell()
 410  
     {
 411  8
         return shell;
 412  
     }
 413  
 
 414  50
     public static class Argument
 415  
         implements Arg
 416  
     {
 417  
         private String[] parts;
 418  
 
 419  
         /* (non-Javadoc)
 420  
          * @see org.apache.maven.shared.utils.cli.Argumnt#setValue(java.lang.String)
 421  
          */
 422  
         public void setValue( String value )
 423  
         {
 424  25
             if ( value != null )
 425  
             {
 426  25
                 parts = new String[]{ value };
 427  
             }
 428  25
         }
 429  
 
 430  
         /* (non-Javadoc)
 431  
          * @see org.apache.maven.shared.utils.cli.Argumnt#setLine(java.lang.String)
 432  
          */
 433  
         public void setLine( String line )
 434  
         {
 435  0
             if ( line == null )
 436  
             {
 437  0
                 return;
 438  
             }
 439  
             try
 440  
             {
 441  0
                 parts = CommandLineUtils.translateCommandline( line );
 442  
             }
 443  0
             catch ( Exception e )
 444  
             {
 445  0
                 System.err.println( "Error translating Commandline." );
 446  0
             }
 447  0
         }
 448  
 
 449  
         /* (non-Javadoc)
 450  
          * @see org.apache.maven.shared.utils.cli.Argumnt#setFile(java.io.File)
 451  
          */
 452  
         public void setFile( File value )
 453  
         {
 454  0
             parts = new String[]{ value.getAbsolutePath() };
 455  0
         }
 456  
 
 457  
         /* (non-Javadoc)
 458  
          * @see org.apache.maven.shared.utils.cli.Argumnt#getParts()
 459  
          */
 460  
         private String[] getParts()
 461  
         {
 462  25
             return parts;
 463  
         }
 464  
     }
 465  
 }