Coverage Report - org.apache.maven.wagon.providers.ssh.AbstractSshWagon
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractSshWagon
0% 
0% 
2.905
 
 1  
 package org.apache.maven.wagon.providers.ssh;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2006 The Apache Software 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.apache.maven.wagon.AbstractWagon;
 20  
 import org.apache.maven.wagon.CommandExecutionException;
 21  
 import org.apache.maven.wagon.CommandExecutor;
 22  
 import org.apache.maven.wagon.PathUtils;
 23  
 import org.apache.maven.wagon.PermissionModeUtils;
 24  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 25  
 import org.apache.maven.wagon.Streams;
 26  
 import org.apache.maven.wagon.TransferFailedException;
 27  
 import org.apache.maven.wagon.WagonConstants;
 28  
 import org.apache.maven.wagon.authentication.AuthenticationException;
 29  
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 30  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 31  
 import org.apache.maven.wagon.events.TransferEvent;
 32  
 import org.apache.maven.wagon.providers.ssh.interactive.InteractiveUserInfo;
 33  
 import org.apache.maven.wagon.providers.ssh.interactive.NullInteractiveUserInfo;
 34  
 import org.apache.maven.wagon.providers.ssh.knownhost.KnownHostsProvider;
 35  
 import org.apache.maven.wagon.repository.RepositoryPermissions;
 36  
 import org.apache.maven.wagon.resource.Resource;
 37  
 import org.codehaus.plexus.util.FileUtils;
 38  
 import org.codehaus.plexus.util.StringUtils;
 39  
 
 40  
 import java.io.File;
 41  
 import java.io.IOException;
 42  
 import java.util.List;
 43  
 
 44  
 /**
 45  
  * Common SSH operations.
 46  
  *
 47  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 48  
  * @version $Id: AbstractSshWagon.java 485738 2006-12-11 16:22:26Z joakime $
 49  
  * @todo cache pass[words|phases]
 50  
  * @todo move permissions tools to repositorypermissionsutils
 51  
  */
 52  0
 public abstract class AbstractSshWagon
 53  
     extends AbstractWagon
 54  
     implements CommandExecutor, SshWagon
 55  
 {
 56  
     protected KnownHostsProvider knownHostsProvider;
 57  
 
 58  
     protected InteractiveUserInfo interactiveUserInfo;
 59  
 
 60  
     protected static final char PATH_SEPARATOR = '/';
 61  
 
 62  
     protected static final int DEFAULT_SSH_PORT = 22;
 63  
 
 64  
     public boolean getIfNewer( String resourceName, File destination, long timestamp )
 65  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 66  
     {
 67  0
         fireSessionDebug( "getIfNewer in SCP wagon is not supported - performing an unconditional get" );
 68  0
         get( resourceName, destination );
 69  0
         return true;
 70  
     }
 71  
 
 72  
     protected String getOctalMode( RepositoryPermissions permissions )
 73  
     {
 74  0
         String mode = "0644";
 75  0
         if ( permissions != null && permissions.getFileMode() != null )
 76  
         {
 77  0
             if ( permissions.getFileMode().matches( "[0-9]{3,4}" ) )
 78  
             {
 79  0
                 mode = permissions.getFileMode();
 80  
 
 81  0
                 if ( mode.length() == 3 )
 82  
                 {
 83  0
                     mode = "0" + mode;
 84  
                 }
 85  
             }
 86  
             else
 87  
             {
 88  
                 // TODO: calculate?
 89  
                 // TODO: as warning
 90  0
                 fireSessionDebug( "Not using non-octal permissions: " + mode );
 91  
             }
 92  
         }
 93  0
         return mode;
 94  
     }
 95  
 
 96  
     /**
 97  
      * @param permissions repository's permissions
 98  
      * @return the directory mode for the repository or <code>-1</code> if it
 99  
      *         wasn't set
 100  
      */
 101  
     protected int getDirectoryMode( RepositoryPermissions permissions )
 102  
     {
 103  0
         int ret = -1;
 104  
 
 105  0
         if ( permissions != null )
 106  
         {
 107  0
             ret = getOctalMode( permissions.getDirectoryMode() );
 108  
         }
 109  
 
 110  0
         return ret;
 111  
     }
 112  
 
 113  
     protected int getOctalMode( String mode )
 114  
     {
 115  
         int ret;
 116  
         try
 117  
         {
 118  0
             ret = Integer.valueOf( mode, 8 ).intValue();
 119  
         }
 120  0
         catch ( NumberFormatException e )
 121  
         {
 122  
             // TODO: warning level
 123  0
             fireTransferDebug( "the file mode must be a numerical mode for SFTP" );
 124  0
             ret = -1;
 125  0
         }
 126  0
         return ret;
 127  
     }
 128  
 
 129  
     protected static String getResourceDirectory( String resourceName )
 130  
     {
 131  0
         String dir = PathUtils.dirname( resourceName );
 132  0
         dir = StringUtils.replace( dir, "\\", "/" );
 133  0
         return dir;
 134  
     }
 135  
 
 136  
     protected static String getResourceFilename( String r )
 137  
     {
 138  
         String filename;
 139  0
         if ( r.lastIndexOf( PATH_SEPARATOR ) > 0 )
 140  
         {
 141  0
             filename = r.substring( r.lastIndexOf( PATH_SEPARATOR ) + 1 );
 142  
         }
 143  
         else
 144  
         {
 145  0
             filename = r;
 146  
         }
 147  0
         return filename;
 148  
     }
 149  
 
 150  
     protected static Resource getResource( String resourceName )
 151  
     {
 152  0
         String r = StringUtils.replace( resourceName, "\\", "/" );
 153  0
         return new Resource( r );
 154  
     }
 155  
 
 156  
     public void openConnection()
 157  
         throws AuthenticationException
 158  
     {
 159  0
         if ( authenticationInfo == null )
 160  
         {
 161  0
             authenticationInfo = new AuthenticationInfo();
 162  
         }
 163  
 
 164  0
         if ( authenticationInfo.getUserName() == null )
 165  
         {
 166  0
             authenticationInfo.setUserName( System.getProperty( "user.name" ) );
 167  
         }
 168  
 
 169  0
         if ( !interactive )
 170  
         {
 171  0
             interactiveUserInfo = new NullInteractiveUserInfo();
 172  
         }
 173  0
     }
 174  
 
 175  
     protected File getPrivateKey()
 176  
     {
 177  
         // If user don't define a password, he want to use a private key
 178  0
         File privateKey = null;
 179  0
         if ( authenticationInfo.getPassword() == null )
 180  
         {
 181  
 
 182  0
             if ( authenticationInfo.getPrivateKey() != null )
 183  
             {
 184  0
                 privateKey = new File( authenticationInfo.getPrivateKey() );
 185  
             }
 186  
             else
 187  
             {
 188  0
                 privateKey = findPrivateKey();
 189  
             }
 190  
 
 191  0
             if ( privateKey.exists() )
 192  
             {
 193  0
                 if ( authenticationInfo.getPassphrase() == null )
 194  
                 {
 195  0
                     authenticationInfo.setPassphrase( "" );
 196  
                 }
 197  
 
 198  0
                 fireSessionDebug( "Using private key: " + privateKey );
 199  
             }
 200  
         }
 201  0
         return privateKey;
 202  
     }
 203  
 
 204  
     protected int getPort()
 205  
     {
 206  0
         int port = getRepository().getPort();
 207  
 
 208  0
         if ( port == WagonConstants.UNKNOWN_PORT )
 209  
         {
 210  0
             port = DEFAULT_SSH_PORT;
 211  
         }
 212  0
         return port;
 213  
     }
 214  
 
 215  
     private File findPrivateKey()
 216  
     {
 217  0
         String privateKeyDirectory = System.getProperty( "wagon.privateKeyDirectory" );
 218  
 
 219  0
         if ( privateKeyDirectory == null )
 220  
         {
 221  0
             privateKeyDirectory = System.getProperty( "user.home" );
 222  
         }
 223  
 
 224  0
         File privateKey = new File( privateKeyDirectory, ".ssh/id_dsa" );
 225  
 
 226  0
         if ( !privateKey.exists() )
 227  
         {
 228  0
             privateKey = new File( privateKeyDirectory, ".ssh/id_rsa" );
 229  
         }
 230  
 
 231  0
         return privateKey;
 232  
     }
 233  
 
 234  
     public void executeCommand( String command )
 235  
         throws CommandExecutionException
 236  
     {
 237  0
         fireTransferDebug( "Executing command: " + command );
 238  
 
 239  0
         executeCommand( command, false );
 240  0
     }
 241  
 
 242  
     public final KnownHostsProvider getKnownHostsProvider()
 243  
     {
 244  0
         return knownHostsProvider;
 245  
     }
 246  
 
 247  
     public final void setKnownHostsProvider( KnownHostsProvider knownHostsProvider )
 248  
     {
 249  0
         if ( knownHostsProvider == null )
 250  
         {
 251  0
             throw new IllegalArgumentException( "knownHostsProvider can't be null" );
 252  
         }
 253  0
         this.knownHostsProvider = knownHostsProvider;
 254  0
     }
 255  
 
 256  
     public InteractiveUserInfo getInteractiveUserInfo()
 257  
     {
 258  0
         return interactiveUserInfo;
 259  
     }
 260  
 
 261  
     public void setInteractiveUserInfo( InteractiveUserInfo interactiveUserInfo )
 262  
     {
 263  0
         if ( interactiveUserInfo == null )
 264  
         {
 265  0
             throw new IllegalArgumentException( "interactiveUserInfo can't be null" );
 266  
         }
 267  0
         this.interactiveUserInfo = interactiveUserInfo;
 268  0
     }
 269  
 
 270  
     public void putDirectory( File sourceDirectory, String destinationDirectory )
 271  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 272  
     {
 273  0
         String basedir = getRepository().getBasedir();
 274  
 
 275  0
         String destDir = StringUtils.replace( destinationDirectory, "\\", "/" );
 276  
 
 277  0
         String path = getPath( basedir, destDir );
 278  
         try
 279  
         {
 280  0
             if ( getRepository().getPermissions() != null )
 281  
             {
 282  0
                 String dirPerms = getRepository().getPermissions().getDirectoryMode();
 283  
 
 284  0
                 if ( dirPerms != null )
 285  
                 {
 286  0
                     String umaskCmd = "umask " + PermissionModeUtils.getUserMaskFor( dirPerms );
 287  0
                     executeCommand( umaskCmd );
 288  
                 }
 289  
             }
 290  
 
 291  0
             String mkdirCmd = "mkdir -p " + path;
 292  
 
 293  0
             executeCommand( mkdirCmd );
 294  
         }
 295  0
         catch ( CommandExecutionException e )
 296  
         {
 297  0
             throw new TransferFailedException( "Error performing commands for file transfer", e );
 298  0
         }
 299  
 
 300  
         File zipFile;
 301  
         try
 302  
         {
 303  0
             zipFile = File.createTempFile( "wagon", ".zip" );
 304  0
             zipFile.deleteOnExit();
 305  
 
 306  0
             List files = FileUtils.getFileNames( sourceDirectory, "**/**", "", false );
 307  
 
 308  0
             createZip( files, zipFile, sourceDirectory );
 309  
         }
 310  0
         catch ( IOException e )
 311  
         {
 312  0
             throw new TransferFailedException( "Unable to create ZIP archive of directory", e );
 313  0
         }
 314  
 
 315  0
         put( zipFile, getPath( destDir, zipFile.getName() ) );
 316  
 
 317  
         try
 318  
         {
 319  0
             executeCommand( "cd " + path + "; unzip -q -o " + zipFile.getName() + "; rm -f " + zipFile.getName() );
 320  
 
 321  0
             zipFile.delete();
 322  
 
 323  0
             RepositoryPermissions permissions = getRepository().getPermissions();
 324  
 
 325  0
             if ( permissions != null && permissions.getGroup() != null )
 326  
             {
 327  0
                 executeCommand( "chgrp -Rf " + permissions.getGroup() + " " + path );
 328  
             }
 329  
 
 330  0
             if ( permissions != null && permissions.getFileMode() != null )
 331  
             {
 332  0
                 executeCommand( "chmod -Rf " + permissions.getFileMode() + " " + path );
 333  
             }
 334  
         }
 335  0
         catch ( CommandExecutionException e )
 336  
         {
 337  0
             throw new TransferFailedException( "Error performing commands for file transfer", e );
 338  0
         }
 339  0
     }
 340  
 
 341  
     public boolean supportsDirectoryCopy()
 342  
     {
 343  0
         return true;
 344  
     }
 345  
 
 346  
     public List getFileList( String destinationDirectory )
 347  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 348  
     {
 349  
         try
 350  
         {
 351  0
             String path = getPath( getRepository().getBasedir(), destinationDirectory );
 352  0
             Streams streams = executeCommand( "ls -la " + path, false );
 353  
             
 354  0
             return new LSParser().parseFiles( streams.getOut() );
 355  
         }
 356  0
         catch ( CommandExecutionException e )
 357  
         {
 358  0
             if ( e.getMessage().trim().endsWith( "No such file or directory" ) )
 359  
             {
 360  0
                 throw new ResourceDoesNotExistException( e.getMessage().trim() );
 361  
             }
 362  
             else
 363  
             {
 364  0
                 throw new TransferFailedException( "Error performing file listing.", e );
 365  
             }
 366  
         }
 367  
     }
 368  
 
 369  
     public boolean resourceExists( String resourceName )
 370  
         throws TransferFailedException, AuthorizationException
 371  
     {
 372  
         try
 373  
         {
 374  0
             String path = getPath( getRepository().getBasedir(), resourceName );
 375  0
             executeCommand( "ls " + path );
 376  
 
 377  
             // Parsing of output not really needed.  As a failed ls results in a
 378  
             // CommandExectionException on the 'ls' command.
 379  
 
 380  0
             return true;
 381  
         }
 382  0
         catch ( CommandExecutionException e )
 383  
         {
 384  
             // Error?  Then the 'ls' command failed.  No such file found.
 385  0
             return false;
 386  
         }
 387  
     }
 388  
 
 389  
     protected void handleGetException( Resource resource, Exception e, File destination )
 390  
         throws TransferFailedException, ResourceDoesNotExistException
 391  
     {
 392  0
         fireTransferError( resource, e, TransferEvent.REQUEST_GET );
 393  
 
 394  0
         if ( destination.exists() )
 395  
         {
 396  0
             boolean deleted = destination.delete();
 397  
 
 398  0
             if ( !deleted )
 399  
             {
 400  0
                 destination.deleteOnExit();
 401  
             }
 402  
         }
 403  
 
 404  0
         String msg = "Error occured while downloading '" + resource + "' from the remote repository:" + getRepository();
 405  
 
 406  0
         throw new TransferFailedException( msg, e );
 407  
     }
 408  
 }