Coverage Report - org.apache.maven.wagon.providers.ssh.SftpWagon
 
Classes in this File Line Coverage Branch Coverage Complexity
SftpWagon
0% 
0% 
5,714
 
 1  
 package org.apache.maven.wagon.providers.ssh;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 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 com.jcraft.jsch.ChannelSftp;
 20  
 import com.jcraft.jsch.JSchException;
 21  
 import com.jcraft.jsch.SftpATTRS;
 22  
 import com.jcraft.jsch.SftpException;
 23  
 import org.apache.maven.wagon.PathUtils;
 24  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 25  
 import org.apache.maven.wagon.TransferFailedException;
 26  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 27  
 import org.apache.maven.wagon.events.TransferEvent;
 28  
 import org.apache.maven.wagon.repository.RepositoryPermissions;
 29  
 import org.apache.maven.wagon.resource.Resource;
 30  
 import org.codehaus.plexus.util.StringUtils;
 31  
 
 32  
 import java.io.File;
 33  
 
 34  
 /**
 35  
  * SFTP protocol wagon.
 36  
  *
 37  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 38  
  * @version $Id: SftpWagon.java 396016 2006-04-21 21:53:52Z carlos $
 39  
  * @todo [BP] add compression flag
 40  
  */
 41  0
 public class SftpWagon
 42  
     extends AbstractSshWagon
 43  
 {
 44  
     private static final String SFTP_CHANNEL = "sftp";
 45  
 
 46  
     private static final int S_IFDIR = 0x4000;
 47  
 
 48  
     private static final char PATH_SEPARATOR = '/';
 49  
 
 50  
     private static final long MILLIS_PER_SEC = 1000L;
 51  
 
 52  
     // ----------------------------------------------------------------------
 53  
     //
 54  
     // ----------------------------------------------------------------------
 55  
 
 56  
     public void put( File source, String resourceName )
 57  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 58  
     {
 59  0
         String basedir = getRepository().getBasedir();
 60  
 
 61  0
         resourceName = StringUtils.replace( resourceName, "\\", "/" );
 62  0
         String dir = PathUtils.dirname( resourceName );
 63  0
         dir = StringUtils.replace( dir, "\\", "/" );
 64  
 
 65  0
         Resource resource = new Resource( resourceName );
 66  
 
 67  0
         firePutInitiated( resource, source );
 68  
 
 69  
         ChannelSftp channel;
 70  
 
 71  
         String filename;
 72  
 
 73  0
         if ( resourceName.lastIndexOf( PATH_SEPARATOR ) > 0 )
 74  
         {
 75  0
             filename = resourceName.substring( resourceName.lastIndexOf( PATH_SEPARATOR ) + 1 );
 76  0
         }
 77  
         else
 78  
         {
 79  0
             filename = resourceName;
 80  
         }
 81  
 
 82  
         try
 83  
         {
 84  0
             channel = (ChannelSftp) session.openChannel( SFTP_CHANNEL );
 85  
 
 86  0
             channel.connect();
 87  
 
 88  0
             RepositoryPermissions permissions = getRepository().getPermissions();
 89  
 
 90  0
             int directoryMode = getDirectoryMode( permissions );
 91  
             
 92  0
             mkdirs( channel, basedir, directoryMode );
 93  
 
 94  0
             channel.cd( basedir );
 95  
             
 96  0
             mkdirs( channel, resourceName, directoryMode );
 97  
 
 98  0
             firePutStarted( resource, source );
 99  
 
 100  0
             channel.put( source.getAbsolutePath(), filename );
 101  
 
 102  0
             postProcessListeners( resource, source, TransferEvent.REQUEST_PUT );
 103  
 
 104  0
             if ( permissions != null && permissions.getGroup() != null )
 105  
             {
 106  
                 try
 107  
                 {
 108  0
                     int group = Integer.valueOf( permissions.getGroup() ).intValue();
 109  0
                     channel.chgrp( group, filename );
 110  
                 }
 111  0
                 catch ( NumberFormatException e )
 112  
                 {
 113  
                     // TODO: warning level
 114  0
                     fireTransferDebug( "Not setting group: must be a numerical GID for SFTP" );
 115  0
                 }
 116  
             }
 117  
 
 118  0
             if ( permissions != null && permissions.getFileMode() != null )
 119  
             {
 120  
                 try
 121  
                 {
 122  0
                     int mode = getOctalMode( permissions.getFileMode() );
 123  0
                     channel.chmod( mode, filename );
 124  
                 }
 125  0
                 catch ( NumberFormatException e )
 126  
                 {
 127  
                     // TODO: warning level
 128  0
                     fireTransferDebug( "Not setting mode: must be a numerical mode for SFTP" );
 129  0
                 }
 130  
             }
 131  
 
 132  0
             firePutCompleted( resource, source );
 133  
 
 134  0
             String[] dirs = PathUtils.dirnames( dir );
 135  0
             for ( int i = 0; i < dirs.length; i++ )
 136  
             {
 137  0
                 channel.cd( ".." );
 138  
             }
 139  
         }
 140  0
         catch ( SftpException e )
 141  
         {
 142  0
             String msg = "Error occured while deploying '" + resourceName + "' " + "to remote repository: " +
 143  
                 getRepository().getUrl();
 144  
 
 145  0
             throw new TransferFailedException( msg, e );
 146  
         }
 147  0
         catch ( JSchException e )
 148  
         {
 149  0
             String msg = "Error occured while deploying '" + resourceName + "' " + "to remote repository: " +
 150  
                 getRepository().getUrl();
 151  
 
 152  0
             throw new TransferFailedException( msg, e );
 153  0
         }
 154  
 
 155  0
         if ( channel != null )
 156  
         {
 157  0
             channel.disconnect();
 158  
         }
 159  0
     }
 160  
 
 161  
     /**
 162  
      * @param permissions repository's permissions
 163  
      * @return the directory mode for the repository or <code>-1</code> if it
 164  
      *         wasn't set
 165  
      */
 166  
     private int getDirectoryMode( RepositoryPermissions permissions )
 167  
     {
 168  0
         int ret = -1;
 169  
 
 170  0
         if ( permissions != null )
 171  
         {
 172  0
             ret = getOctalMode( permissions.getDirectoryMode() );
 173  
         }
 174  
 
 175  0
         return ret;
 176  
     }
 177  
 
 178  
     private int getOctalMode( String mode )
 179  
     {
 180  
         int ret;
 181  
         try
 182  
         {
 183  0
             ret = Integer.valueOf( mode, 8 ).intValue();
 184  
         }
 185  0
         catch ( NumberFormatException e )
 186  
         {
 187  
             // TODO: warning level
 188  0
             fireTransferDebug( "the file mode must be a numerical mode for SFTP" );
 189  0
             ret = -1;
 190  0
         }
 191  0
         return ret;
 192  
     }
 193  
 
 194  
     private void mkdirs( ChannelSftp channel, String resourceName, int mode )
 195  
         throws TransferFailedException, SftpException
 196  
     {
 197  0
         String[] dirs = PathUtils.dirnames( resourceName );
 198  0
         for ( int i = 0; i < dirs.length; i++ )
 199  
         {
 200  0
             mkdir( channel, dirs[i], mode );
 201  
 
 202  0
             channel.cd( dirs[i] );
 203  
         }
 204  0
     }
 205  
 
 206  
     private void mkdir( ChannelSftp channel, String dir, int mode )
 207  
         throws TransferFailedException, SftpException
 208  
     {
 209  
         try
 210  
         {
 211  0
             SftpATTRS attrs = channel.stat( dir );
 212  0
             if ( ( attrs.getPermissions() & S_IFDIR ) == 0 )
 213  
             {
 214  0
                 throw new TransferFailedException( "Remote path is not a directory:" + dir );
 215  
             }
 216  
         }
 217  0
         catch ( SftpException e )
 218  
         {
 219  
             // doesn't exist, make it and try again
 220  0
             channel.mkdir( dir );
 221  0
             if ( mode != -1 )
 222  
             {
 223  
                 try
 224  
                 {
 225  0
                     channel.chmod( mode, dir );
 226  
                 }
 227  0
                 catch ( final SftpException e1 )
 228  
                 {
 229  
                     // for some extrange reason we recive this exception,
 230  
                     // even when chmod success
 231  0
                 }
 232  
             }
 233  0
         }
 234  0
     }
 235  
 
 236  
     public boolean getIfNewer( String resourceName, File destination, long timestamp )
 237  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 238  
     {
 239  0
         boolean bDownloaded = true;
 240  0
         createParentDirectories( destination );
 241  
 
 242  
         ChannelSftp channel;
 243  
 
 244  0
         resourceName = StringUtils.replace( resourceName, "\\", "/" );
 245  0
         String dir = PathUtils.dirname( resourceName );
 246  0
         dir = StringUtils.replace( dir, "\\", "/" );
 247  
 
 248  
         // we already setuped the root directory. Ignore beginning /
 249  0
         if ( dir.length() > 0 && dir.charAt( 0 ) == PATH_SEPARATOR )
 250  
         {
 251  0
             dir = dir.substring( 1 );
 252  
         }
 253  
 
 254  0
         Resource resource = new Resource( resourceName );
 255  
 
 256  0
         fireGetInitiated( resource, destination );
 257  
 
 258  
         String filename;
 259  0
         if ( resourceName.lastIndexOf( PATH_SEPARATOR ) > 0 )
 260  
         {
 261  0
             filename = resourceName.substring( resourceName.lastIndexOf( PATH_SEPARATOR ) + 1 );
 262  0
         }
 263  
         else
 264  
         {
 265  0
             filename = resourceName;
 266  
         }
 267  
 
 268  
         try
 269  
         {
 270  0
             channel = (ChannelSftp) session.openChannel( SFTP_CHANNEL );
 271  
 
 272  0
             channel.connect();
 273  
 
 274  
             try
 275  
             {
 276  0
                 channel.cd( repository.getBasedir() );
 277  
             }
 278  0
             catch ( SftpException e )
 279  
             {
 280  0
                 if ( "No such file".equals( e.toString() ) )
 281  
                 {
 282  0
                     throw new ResourceDoesNotExistException( "Repository base directory is missing for: " + repository.getId(), e );
 283  
                 }
 284  
                 else
 285  
                 {
 286  0
                     throw e;
 287  
                 }
 288  0
             }
 289  
             
 290  
             // This must be called first to ensure that if the file doesn't exist it throws an exception
 291  
             SftpATTRS attrs;
 292  
             try
 293  
             {
 294  0
                 channel.cd( repository.getBasedir() );
 295  
                 
 296  0
                 channel.cd( dir );
 297  
                 
 298  0
                 attrs = channel.stat( filename );
 299  
             }
 300  0
             catch ( SftpException e )
 301  
             {
 302  0
                 if ( "No such file".equals( e.toString() ) )
 303  
                 {
 304  0
                     throw new ResourceDoesNotExistException( e.toString(), e );
 305  
                 }
 306  
                 else
 307  
                 {
 308  0
                     throw e;
 309  
                 }
 310  0
             }
 311  
 
 312  0
             if ( timestamp <= 0 || attrs.getMTime() * MILLIS_PER_SEC > timestamp )
 313  
             {
 314  0
                 fireGetStarted( resource, destination );
 315  
 
 316  0
                 channel.get( filename, destination.getAbsolutePath() );
 317  
 
 318  0
                 postProcessListeners( resource, destination, TransferEvent.REQUEST_GET );
 319  
 
 320  0
                 fireGetCompleted( resource, destination );
 321  
 
 322  0
                 String[] dirs = PathUtils.dirnames( dir );
 323  
 
 324  0
                 for ( int i = 0; i < dirs.length; i++ )
 325  
                 {
 326  0
                     channel.cd( ".." );
 327  
                 }
 328  
 
 329  0
                 bDownloaded = true;
 330  0
             }
 331  
             else
 332  
             {
 333  0
                 bDownloaded = false;
 334  
             }
 335  
         }
 336  0
         catch ( SftpException e )
 337  
         {
 338  0
             handleGetException( resource, e, destination );
 339  
         }
 340  0
         catch ( JSchException e )
 341  
         {
 342  0
             handleGetException( resource, e, destination );
 343  0
         }
 344  
 
 345  0
         return bDownloaded;
 346  
     }
 347  
 
 348  
 
 349  
     public void get( String resourceName, File destination )
 350  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 351  
     {
 352  0
         getIfNewer( resourceName, destination, 0 );
 353  0
     }
 354  
 }