Coverage Report - org.codehaus.plexus.util.cli.shell.Shell
 
Classes in this File Line Coverage Branch Coverage Complexity
Shell
80%
91/113
80%
29/36
1.476
 
 1  
 package org.codehaus.plexus.util.cli.shell;
 2  
 
 3  
 /*
 4  
  * Copyright The Codehaus Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import org.codehaus.plexus.util.StringUtils;
 20  
 
 21  
 import java.io.File;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Arrays;
 24  
 import java.util.List;
 25  
 
 26  
 /**
 27  
  * <p>
 28  
  * Class that abstracts the Shell functionality, with subclasses for shells that behave particularly, like
 29  
  * <ul>
 30  
  * <li><code>command.com</code></li>
 31  
  * <li><code>cmd.exe</code></li>
 32  
  * </ul>
 33  
  * </p>
 34  
  *
 35  
  * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
 36  
  * @since 1.2
 37  
  * @version $Id$
 38  
  */
 39  36
 public class Shell
 40  
     implements Cloneable
 41  
 {
 42  1
     private static final char[] DEFAULT_QUOTING_TRIGGER_CHARS = { ' ' };
 43  
 
 44  
     private String shellCommand;
 45  
 
 46  36
     private List<String> shellArgs = new ArrayList<String>();
 47  
 
 48  36
     private boolean quotedArgumentsEnabled = true;
 49  
 
 50  36
     private boolean unconditionallyQuote = false;
 51  
 
 52  
     private String executable;
 53  
 
 54  
     private String workingDir;
 55  
 
 56  36
     private boolean quotedExecutableEnabled = true;
 57  
 
 58  36
     private boolean doubleQuotedArgumentEscaped = false;
 59  
 
 60  36
     private boolean singleQuotedArgumentEscaped = false;
 61  
 
 62  36
     private boolean doubleQuotedExecutableEscaped = false;
 63  
 
 64  36
     private boolean singleQuotedExecutableEscaped = false;
 65  
 
 66  36
     private char argQuoteDelimiter = '\"';
 67  
 
 68  36
     private char exeQuoteDelimiter = '\"';
 69  
 
 70  36
     private String argumentEscapePattern = "\\%s";
 71  
 
 72  
     /**
 73  
      * Toggle unconditional quoting
 74  
      *
 75  
      * @param unconditionallyQuote
 76  
      */
 77  
     public void setUnconditionalQuoting( boolean unconditionallyQuote )
 78  
     {
 79  28
         this.unconditionallyQuote = unconditionallyQuote;
 80  28
     }
 81  
 
 82  
     /**
 83  
      * Set the command to execute the shell (eg. COMMAND.COM, /bin/bash,...)
 84  
      *
 85  
      * @param shellCommand
 86  
      */
 87  
     public void setShellCommand( String shellCommand )
 88  
     {
 89  31
         this.shellCommand = shellCommand;
 90  31
     }
 91  
 
 92  
     /**
 93  
      * Get the command to execute the shell
 94  
      *
 95  
      * @return
 96  
      */
 97  
     public String getShellCommand()
 98  
     {
 99  57
         return shellCommand;
 100  
     }
 101  
 
 102  
     /**
 103  
      * Set the shell arguments when calling a command line (not the executable arguments) (eg. /X /C for CMD.EXE)
 104  
      *
 105  
      * @param shellArgs
 106  
      */
 107  
     public void setShellArgs( String[] shellArgs )
 108  
     {
 109  3
         this.shellArgs.clear();
 110  3
         this.shellArgs.addAll( Arrays.asList( shellArgs ) );
 111  3
     }
 112  
 
 113  
     /**
 114  
      * Get the shell arguments
 115  
      *
 116  
      * @return
 117  
      */
 118  
     public String[] getShellArgs()
 119  
     {
 120  31
         if ( ( shellArgs == null ) || shellArgs.isEmpty() )
 121  
         {
 122  28
             return null;
 123  
         }
 124  
         else
 125  
         {
 126  3
             return (String[]) shellArgs.toArray( new String[shellArgs.size()] );
 127  
         }
 128  
     }
 129  
 
 130  
     /**
 131  
      * Get the command line for the provided executable and arguments in this shell
 132  
      *
 133  
      * @param executable executable that the shell has to call
 134  
      * @param arguments arguments for the executable, not the shell
 135  
      * @return List with one String object with executable and arguments quoted as needed
 136  
      */
 137  
     public List<String> getCommandLine( String executable, String[] arguments )
 138  
     {
 139  31
         return getRawCommandLine( executable, arguments );
 140  
     }
 141  
 
 142  
     protected String quoteOneItem( String inputString, boolean isExecutable )
 143  
     {
 144  18
         char[] escapeChars = getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
 145  18
         return StringUtils.quoteAndEscape( inputString,
 146  
                                            isExecutable ? getExecutableQuoteDelimiter() : getArgumentQuoteDelimiter(),
 147  
                                            escapeChars, getQuotingTriggerChars(), '\\', unconditionallyQuote );
 148  
     }
 149  
 
 150  
     protected List<String> getRawCommandLine( String executable, String[] arguments )
 151  
     {
 152  31
         List<String> commandLine = new ArrayList<String>();
 153  31
         StringBuilder sb = new StringBuilder();
 154  
 
 155  31
         if ( executable != null )
 156  
         {
 157  27
             String preamble = getExecutionPreamble();
 158  27
             if ( preamble != null )
 159  
             {
 160  17
                 sb.append( preamble );
 161  
             }
 162  
 
 163  27
             if ( isQuotedExecutableEnabled() )
 164  
             {
 165  27
                 sb.append( quoteOneItem( getOriginalExecutable(), true ) );
 166  
             }
 167  
             else
 168  
             {
 169  0
                 sb.append( getExecutable() );
 170  
             }
 171  
         }
 172  78
         for ( String argument : arguments )
 173  
         {
 174  47
             if ( sb.length() > 0 )
 175  
             {
 176  43
                 sb.append( " " );
 177  
             }
 178  
 
 179  47
             if ( isQuotedArgumentsEnabled() )
 180  
             {
 181  47
                 sb.append( quoteOneItem( argument, false ) );
 182  
             }
 183  
             else
 184  
             {
 185  0
                 sb.append( argument );
 186  
             }
 187  
         }
 188  
 
 189  31
         commandLine.add( sb.toString() );
 190  
 
 191  31
         return commandLine;
 192  
     }
 193  
 
 194  
     protected char[] getQuotingTriggerChars()
 195  
     {
 196  18
         return DEFAULT_QUOTING_TRIGGER_CHARS;
 197  
     }
 198  
 
 199  
     protected String getExecutionPreamble()
 200  
     {
 201  4
         return null;
 202  
     }
 203  
 
 204  
     protected char[] getEscapeChars( boolean includeSingleQuote, boolean includeDoubleQuote )
 205  
     {
 206  18
         StringBuilder buf = new StringBuilder( 2 );
 207  18
         if ( includeSingleQuote )
 208  
         {
 209  0
             buf.append( '\'' );
 210  
         }
 211  
 
 212  18
         if ( includeDoubleQuote )
 213  
         {
 214  0
             buf.append( '\"' );
 215  
         }
 216  
 
 217  18
         char[] result = new char[buf.length()];
 218  18
         buf.getChars( 0, buf.length(), result, 0 );
 219  
 
 220  18
         return result;
 221  
     }
 222  
 
 223  
     protected boolean isDoubleQuotedArgumentEscaped()
 224  
     {
 225  0
         return doubleQuotedArgumentEscaped;
 226  
     }
 227  
 
 228  
     protected boolean isSingleQuotedArgumentEscaped()
 229  
     {
 230  0
         return singleQuotedArgumentEscaped;
 231  
     }
 232  
 
 233  
     protected boolean isDoubleQuotedExecutableEscaped()
 234  
     {
 235  18
         return doubleQuotedExecutableEscaped;
 236  
     }
 237  
 
 238  
     protected boolean isSingleQuotedExecutableEscaped()
 239  
     {
 240  18
         return singleQuotedExecutableEscaped;
 241  
     }
 242  
 
 243  
     protected void setArgumentQuoteDelimiter( char argQuoteDelimiter )
 244  
     {
 245  28
         this.argQuoteDelimiter = argQuoteDelimiter;
 246  28
     }
 247  
 
 248  
     protected char getArgumentQuoteDelimiter()
 249  
     {
 250  14
         return argQuoteDelimiter;
 251  
     }
 252  
 
 253  
     protected void setExecutableQuoteDelimiter( char exeQuoteDelimiter )
 254  
     {
 255  28
         this.exeQuoteDelimiter = exeQuoteDelimiter;
 256  28
     }
 257  
 
 258  
     protected char getExecutableQuoteDelimiter()
 259  
     {
 260  4
         return exeQuoteDelimiter;
 261  
     }
 262  
 
 263  
     protected void setArgumentEscapePattern( String argumentEscapePattern )
 264  
     {
 265  28
         this.argumentEscapePattern = argumentEscapePattern;
 266  28
     }
 267  
 
 268  
     protected String getArgumentEscapePattern()
 269  
     {
 270  0
         return argumentEscapePattern;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Get the full command line to execute, including shell command, shell arguments, executable and executable
 275  
      * arguments
 276  
      *
 277  
      * @param arguments arguments for the executable, not the shell
 278  
      * @return List of String objects, whose array version is suitable to be used as argument of
 279  
      *         Runtime.getRuntime().exec()
 280  
      */
 281  
     public List<String> getShellCommandLine( String[] arguments )
 282  
     {
 283  
 
 284  31
         List<String> commandLine = new ArrayList<String>();
 285  
 
 286  31
         if ( getShellCommand() != null )
 287  
         {
 288  26
             commandLine.add( getShellCommand() );
 289  
         }
 290  
 
 291  31
         if ( getShellArgs() != null )
 292  
         {
 293  26
             commandLine.addAll( getShellArgsList() );
 294  
         }
 295  
 
 296  31
         commandLine.addAll( getCommandLine( getOriginalExecutable(), arguments ) );
 297  
 
 298  31
         return commandLine;
 299  
 
 300  
     }
 301  
 
 302  
     public List<String> getShellArgsList()
 303  
     {
 304  26
         return shellArgs;
 305  
     }
 306  
 
 307  
     public void addShellArg( String arg )
 308  
     {
 309  0
         shellArgs.add( arg );
 310  0
     }
 311  
 
 312  
     public void setQuotedArgumentsEnabled( boolean quotedArgumentsEnabled )
 313  
     {
 314  5
         this.quotedArgumentsEnabled = quotedArgumentsEnabled;
 315  5
     }
 316  
 
 317  
     public boolean isQuotedArgumentsEnabled()
 318  
     {
 319  47
         return quotedArgumentsEnabled;
 320  
     }
 321  
 
 322  
     public void setQuotedExecutableEnabled( boolean quotedExecutableEnabled )
 323  
     {
 324  31
         this.quotedExecutableEnabled = quotedExecutableEnabled;
 325  31
     }
 326  
 
 327  
     public boolean isQuotedExecutableEnabled()
 328  
     {
 329  27
         return quotedExecutableEnabled;
 330  
     }
 331  
 
 332  
     /**
 333  
      * Sets the executable to run.
 334  
      */
 335  
     public void setExecutable( String executable )
 336  
     {
 337  34
         if ( ( executable == null ) || ( executable.length() == 0 ) )
 338  
         {
 339  4
             return;
 340  
         }
 341  30
         this.executable = executable.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
 342  30
     }
 343  
 
 344  
     public String getExecutable()
 345  
     {
 346  0
         return executable;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Sets execution directory.
 351  
      */
 352  
     public void setWorkingDirectory( String path )
 353  
     {
 354  14
         if ( path != null )
 355  
         {
 356  14
             workingDir = path;
 357  
         }
 358  14
     }
 359  
 
 360  
     /**
 361  
      * Sets execution directory.
 362  
      */
 363  
     public void setWorkingDirectory( File workingDir )
 364  
     {
 365  20
         if ( workingDir != null )
 366  
         {
 367  10
             this.workingDir = workingDir.getAbsolutePath();
 368  
         }
 369  20
     }
 370  
 
 371  
     public File getWorkingDirectory()
 372  
     {
 373  48
         return workingDir == null ? null : new File( workingDir );
 374  
     }
 375  
 
 376  
     public String getWorkingDirectoryAsString()
 377  
     {
 378  40
         return workingDir;
 379  
     }
 380  
 
 381  
     public void clearArguments()
 382  
     {
 383  0
         shellArgs.clear();
 384  0
     }
 385  
 
 386  
     public Object clone()
 387  
     {
 388  0
         Shell shell = new Shell();
 389  0
         shell.setExecutable( getExecutable() );
 390  0
         shell.setWorkingDirectory( getWorkingDirectory() );
 391  0
         shell.setShellArgs( getShellArgs() );
 392  0
         return shell;
 393  
     }
 394  
 
 395  
     public String getOriginalExecutable()
 396  
     {
 397  96
         return executable;
 398  
     }
 399  
 
 400  
     public List<String> getOriginalCommandLine( String executable, String[] arguments )
 401  
     {
 402  0
         return getRawCommandLine( executable, arguments );
 403  
     }
 404  
 
 405  
     protected void setDoubleQuotedArgumentEscaped( boolean doubleQuotedArgumentEscaped )
 406  
     {
 407  0
         this.doubleQuotedArgumentEscaped = doubleQuotedArgumentEscaped;
 408  0
     }
 409  
 
 410  
     protected void setDoubleQuotedExecutableEscaped( boolean doubleQuotedExecutableEscaped )
 411  
     {
 412  0
         this.doubleQuotedExecutableEscaped = doubleQuotedExecutableEscaped;
 413  0
     }
 414  
 
 415  
     protected void setSingleQuotedArgumentEscaped( boolean singleQuotedArgumentEscaped )
 416  
     {
 417  28
         this.singleQuotedArgumentEscaped = singleQuotedArgumentEscaped;
 418  28
     }
 419  
 
 420  
     protected void setSingleQuotedExecutableEscaped( boolean singleQuotedExecutableEscaped )
 421  
     {
 422  28
         this.singleQuotedExecutableEscaped = singleQuotedExecutableEscaped;
 423  28
     }
 424  
 }