Coverage Report - org.apache.maven.scm.provider.jazz.command.JazzScmCommand
 
Classes in this File Line Coverage Branch Coverage Complexity
JazzScmCommand
58 %
46/79
42 %
16/38
2,75
 
 1  
 package org.apache.maven.scm.provider.jazz.command;
 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 org.apache.maven.scm.ScmException;
 23  
 import org.apache.maven.scm.ScmFileSet;
 24  
 import org.apache.maven.scm.log.ScmLogger;
 25  
 import org.apache.maven.scm.provider.ScmProviderRepository;
 26  
 import org.apache.maven.scm.provider.jazz.command.consumer.ErrorConsumer;
 27  
 import org.apache.maven.scm.provider.jazz.repository.JazzScmProviderRepository;
 28  
 import org.codehaus.plexus.util.Os;
 29  
 import org.codehaus.plexus.util.StringUtils;
 30  
 import org.codehaus.plexus.util.cli.CommandLineException;
 31  
 import org.codehaus.plexus.util.cli.CommandLineUtils;
 32  
 import org.codehaus.plexus.util.cli.Commandline;
 33  
 import org.codehaus.plexus.util.cli.StreamConsumer;
 34  
 
 35  
 import java.io.File;
 36  
 import java.util.Iterator;
 37  
 
 38  
 /**
 39  
  * The base class for the underlying jazz "scm.sh"/"scm.exe" command.
 40  
  * <p/>
 41  
  * The SCM command is documented here:
 42  
  * <p/>
 43  
  * V2.0.2: http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_scm.html
 44  
  * V3.0:   http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_scm.html
 45  
  * V3.0.1: http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_scm.html
 46  
  *
 47  
  * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a>
 48  
  */
 49  
 public class JazzScmCommand
 50  
 {
 51  
     // The logger to use.
 52  
     private ScmLogger fLogger;
 53  
 
 54  
     // The Commandline that we build up and execute.
 55  
     private Commandline fCommand;
 56  
 
 57  
     /**
 58  
      * Create a JazzScmCommand when no sub-command is needed.
 59  
      *
 60  
      * @throws ScmException
 61  
      */
 62  
     public JazzScmCommand( String cmd, ScmProviderRepository repo, ScmFileSet fileSet, ScmLogger logger )
 63  
     {
 64  6
         this( cmd, null, repo, true, fileSet, logger );
 65  6
     }
 66  
 
 67  
     /**
 68  
      * Create a JazzScmCommand when a sub-command is needed.
 69  
      * eg: "create snapshot ..."
 70  
      */
 71  
     public JazzScmCommand( String cmd, String subCmd, ScmProviderRepository repo, ScmFileSet fileSet, ScmLogger logger )
 72  
     {
 73  10
         this( cmd, subCmd, repo, true, fileSet, logger );
 74  10
     }
 75  
 
 76  
     /**
 77  
      * Create a JazzScmCommand, adding the repository-uri as needed.
 78  
      */
 79  
     public JazzScmCommand( String cmd, String subCmd, ScmProviderRepository repo, boolean addRepositoryWorkspaceArg,
 80  
                            ScmFileSet fileSet, ScmLogger logger )
 81  22
     {
 82  22
         fLogger = logger;
 83  22
         fCommand = new Commandline();
 84  
 
 85  
         // TODO This was developed and tested in Windows (in which scm (scm.exe) was the valid executable)
 86  
         // Verify that the executable is valid in other operating systems.
 87  22
         fCommand.setExecutable( JazzConstants.SCM_EXECUTABLE );
 88  
 
 89  22
         if ( fileSet != null )
 90  
         {
 91  21
             fCommand.setWorkingDirectory( fileSet.getBasedir().getAbsolutePath() );
 92  
 
 93  
             // Make the directory, if need be.
 94  21
             if ( !fCommand.getWorkingDirectory().exists() )
 95  
             {
 96  19
                 boolean success = fCommand.getWorkingDirectory().mkdirs();
 97  19
                 if ( !success )
 98  
                 {
 99  
                     // Just log the error, don't throw an error, as it is going to fail anyway.
 100  0
                     logErrorMessage( "Working directory did not exist" + " and it couldn't be created: "
 101  
                                          + fCommand.getWorkingDirectory() );
 102  
                 }
 103  
             }
 104  
         }
 105  
 
 106  
         // Add the main command
 107  22
         if ( !StringUtils.isEmpty( cmd ) )
 108  
         {
 109  22
             addArgument( cmd );
 110  
         }
 111  
 
 112  
         // Add the sub-command if present
 113  22
         if ( !StringUtils.isEmpty( subCmd ) )
 114  
         {
 115  11
             addArgument( subCmd );
 116  
         }
 117  
 
 118  22
         JazzScmProviderRepository jazzRepo = (JazzScmProviderRepository) repo;
 119  
 
 120  
         // Add the repository argument if needed (most commands need this, but not all)
 121  22
         if ( addRepositoryWorkspaceArg )
 122  
         {
 123  16
             String repositoryWorkspace = jazzRepo.getRepositoryURI();
 124  16
             if ( !StringUtils.isEmpty( repositoryWorkspace ) )
 125  
             {
 126  16
                 addArgument( JazzConstants.ARG_REPOSITORY_URI );
 127  16
                 addArgument( jazzRepo.getRepositoryURI() );
 128  
             }
 129  
         }
 130  
 
 131  
         // Add the username argument
 132  
         // TODO Figure out how we would use the login command / username caching so this is not required on each
 133  
         // command.
 134  22
         String user = jazzRepo.getUser();
 135  22
         if ( !StringUtils.isEmpty( user ) )
 136  
         {
 137  22
             addArgument( JazzConstants.ARG_USER_NAME );
 138  22
             addArgument( jazzRepo.getUser() );
 139  
         }
 140  
 
 141  
         // Add the password argument
 142  
         // TODO Figure out how we would use the login command / password caching so this is not required on each
 143  
         // command.
 144  22
         String password = jazzRepo.getPassword();
 145  22
         if ( !StringUtils.isEmpty( password ) )
 146  
         {
 147  22
             addArgument( JazzConstants.ARG_USER_PASSWORD );
 148  22
             addArgument( jazzRepo.getPassword() );
 149  
         }
 150  22
     }
 151  
 
 152  
     public void addArgument( ScmFileSet fileSet )
 153  
     {
 154  0
         logInfoMessage( "files: " + fileSet.getBasedir().getAbsolutePath() );
 155  0
         Iterator<File> iter = fileSet.getFileList().iterator();
 156  0
         while ( iter.hasNext() )
 157  
         {
 158  0
             fCommand.createArg().setValue(  iter.next().getPath() );
 159  
         }
 160  0
     }
 161  
 
 162  
     public void addArgument( String arg )
 163  
     {
 164  195
         fCommand.createArg().setValue( arg );
 165  195
     }
 166  
 
 167  
     public int execute( StreamConsumer out, ErrorConsumer err )
 168  
         throws ScmException
 169  
     {
 170  0
         logInfoMessage( "Executing: " + cryptPassword( fCommand ) );
 171  0
         if ( fCommand.getWorkingDirectory() != null )
 172  
         {
 173  0
             logInfoMessage( "Working directory: " + fCommand.getWorkingDirectory().getAbsolutePath() );
 174  
         }
 175  
 
 176  0
         int status = 0;
 177  
         try
 178  
         {
 179  0
             status = CommandLineUtils.executeCommandLine( fCommand, out, err );
 180  
         }
 181  0
         catch ( CommandLineException e )
 182  
         {
 183  0
             String errorOutput = err.getOutput();
 184  0
             if ( errorOutput.length() > 0 )
 185  
             {
 186  0
                 logErrorMessage( "Error: " + err.getOutput() );
 187  
             }
 188  0
             throw new ScmException( "Error while executing Jazz SCM command line - " + getCommandString(), e );
 189  0
         }
 190  0
         String errorOutput = err.getOutput();
 191  0
         if ( errorOutput.length() > 0 )
 192  
         {
 193  0
             logErrorMessage( "Error: " + err.getOutput() );
 194  
         }
 195  0
         return status;
 196  
     }
 197  
 
 198  
     public String getCommandString()
 199  
     {
 200  0
         return fCommand.toString();
 201  
     }
 202  
 
 203  
     public Commandline getCommandline()
 204  
     {
 205  22
         return fCommand;
 206  
     }
 207  
 
 208  
     private void logErrorMessage( String message )
 209  
     {
 210  0
         if ( fLogger != null )
 211  
         {
 212  0
             fLogger.error( message );
 213  
         }
 214  0
     }
 215  
 
 216  
     private void logInfoMessage( String message )
 217  
     {
 218  0
         if ( fLogger != null )
 219  
         {
 220  0
             fLogger.info( message );
 221  
         }
 222  0
     }
 223  
 
 224  
     private void logDebugMessage( String message )
 225  
     {
 226  0
         if ( fLogger != null )
 227  
         {
 228  0
             fLogger.debug( message );
 229  
         }
 230  0
     }
 231  
 
 232  
     // Unashamedly 'borrowed' from SvnCommandLineUtils
 233  
     // (but fixed for cases where the line ends in the password (no trailing space or further input).
 234  
     public static String cryptPassword( Commandline cl )
 235  
     {
 236  1
         String clString = cl.toString();
 237  
 
 238  1
         int pos = clString.indexOf( "--password" );
 239  
 
 240  1
         if ( pos > 0 )
 241  
         {
 242  1
             String beforePassword = clString.substring( 0, pos + "--password ".length() );
 243  1
             String afterPassword = clString.substring( pos + "--password ".length() );
 244  1
             pos = afterPassword.indexOf( ' ' );
 245  1
             if ( pos > 0 )
 246  
             {
 247  0
                 afterPassword = afterPassword.substring( pos );
 248  
             }
 249  
             else
 250  
             {
 251  1
                 afterPassword = "\"";
 252  
             }
 253  1
             if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
 254  
             {
 255  0
                 clString = beforePassword + "*****" + afterPassword;
 256  
             }
 257  
             else
 258  
             {
 259  1
                 clString = beforePassword + "'*****'";
 260  
             }
 261  
         }
 262  
 
 263  1
         return clString;
 264  
     }
 265  
 
 266  
 }