Coverage Report - org.apache.maven.wagon.providers.ftp.FtpWagon
 
Classes in this File Line Coverage Branch Coverage Complexity
FtpWagon
76 %
194/255
64 %
94/146
6,591
FtpWagon$PrintCommandListener
100 %
7/7
N/A
6,591
 
 1  
 package org.apache.maven.wagon.providers.ftp;
 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.commons.net.ProtocolCommandEvent;
 23  
 import org.apache.commons.net.ProtocolCommandListener;
 24  
 import org.apache.commons.net.ftp.FTP;
 25  
 import org.apache.commons.net.ftp.FTPClient;
 26  
 import org.apache.commons.net.ftp.FTPFile;
 27  
 import org.apache.commons.net.ftp.FTPReply;
 28  
 import org.apache.maven.wagon.ConnectionException;
 29  
 import org.apache.maven.wagon.InputData;
 30  
 import org.apache.maven.wagon.OutputData;
 31  
 import org.apache.maven.wagon.PathUtils;
 32  
 import org.apache.maven.wagon.ResourceDoesNotExistException;
 33  
 import org.apache.maven.wagon.StreamWagon;
 34  
 import org.apache.maven.wagon.TransferFailedException;
 35  
 import org.apache.maven.wagon.WagonConstants;
 36  
 import org.apache.maven.wagon.authentication.AuthenticationException;
 37  
 import org.apache.maven.wagon.authentication.AuthenticationInfo;
 38  
 import org.apache.maven.wagon.authorization.AuthorizationException;
 39  
 import org.apache.maven.wagon.repository.RepositoryPermissions;
 40  
 import org.apache.maven.wagon.resource.Resource;
 41  
 import org.codehaus.plexus.util.IOUtil;
 42  
 
 43  
 import java.io.File;
 44  
 import java.io.FileInputStream;
 45  
 import java.io.IOException;
 46  
 import java.io.InputStream;
 47  
 import java.io.OutputStream;
 48  
 import java.util.ArrayList;
 49  
 import java.util.Calendar;
 50  
 import java.util.List;
 51  
 
 52  
 /**
 53  
  * FtpWagon
 54  
  *
 55  
  * @version $Id: FtpWagon.java 1174106 2011-09-22 13:04:11Z olamy $
 56  
  * @plexus.component role="org.apache.maven.wagon.Wagon"
 57  
  * role-hint="ftp"
 58  
  * instantiation-strategy="per-lookup"
 59  
  */
 60  37
 public class FtpWagon
 61  
     extends StreamWagon
 62  
 {
 63  
     private FTPClient ftp;
 64  
 
 65  
     /**
 66  
      * @plexus.configuration default-value="true"
 67  
      */
 68  37
     private boolean passiveMode = true;
 69  
 
 70  
     /**
 71  
      * @plexus.configuration default-value="ISO-8859-1"
 72  
      */
 73  37
     private String controlEncoding = FTP.DEFAULT_CONTROL_ENCODING;
 74  
 
 75  
     public boolean isPassiveMode()
 76  
     {
 77  35
         return passiveMode;
 78  
     }
 79  
 
 80  
     public void setPassiveMode( boolean passiveMode )
 81  
     {
 82  37
         this.passiveMode = passiveMode;
 83  37
     }
 84  
 
 85  
     protected void openConnectionInternal()
 86  
         throws ConnectionException, AuthenticationException
 87  
     {
 88  37
         AuthenticationInfo authInfo = getAuthenticationInfo();
 89  
 
 90  37
         if ( authInfo == null )
 91  
         {
 92  0
             throw new IllegalArgumentException( "Authentication Credentials cannot be null for FTP protocol" );
 93  
         }
 94  
 
 95  37
         if ( authInfo.getUserName() == null )
 96  
         {
 97  1
             authInfo.setUserName( System.getProperty( "user.name" ) );
 98  
         }
 99  
 
 100  37
         String username = authInfo.getUserName();
 101  
 
 102  37
         String password = authInfo.getPassword();
 103  
 
 104  37
         if ( username == null )
 105  
         {
 106  0
             throw new AuthenticationException( "Username not specified for repository " + getRepository().getId() );
 107  
         }
 108  37
         if ( password == null )
 109  
         {
 110  1
             throw new AuthenticationException( "Password not specified for repository " + getRepository().getId() );
 111  
         }
 112  
 
 113  36
         String host = getRepository().getHost();
 114  
 
 115  36
         ftp = new FTPClient();
 116  36
         ftp.setDefaultTimeout( getTimeout() );
 117  36
         ftp.setDataTimeout( getTimeout() );
 118  36
         ftp.setControlEncoding( getControlEncoding() );
 119  
 
 120  36
         ftp.addProtocolCommandListener( new PrintCommandListener( this ) );
 121  
 
 122  
         try
 123  
         {
 124  36
             if ( getRepository().getPort() != WagonConstants.UNKNOWN_PORT )
 125  
             {
 126  36
                 ftp.connect( host, getRepository().getPort() );
 127  
             }
 128  
             else
 129  
             {
 130  0
                 ftp.connect( host );
 131  
             }
 132  
 
 133  
             // After connection attempt, you should check the reply code to
 134  
             // verify
 135  
             // success.
 136  35
             int reply = ftp.getReplyCode();
 137  
 
 138  35
             if ( !FTPReply.isPositiveCompletion( reply ) )
 139  
             {
 140  0
                 ftp.disconnect();
 141  
 
 142  0
                 throw new AuthenticationException( "FTP server refused connection." );
 143  
             }
 144  
         }
 145  1
         catch ( IOException e )
 146  
         {
 147  1
             if ( ftp.isConnected() )
 148  
             {
 149  
                 try
 150  
                 {
 151  0
                     fireSessionError( e );
 152  
 
 153  0
                     ftp.disconnect();
 154  
                 }
 155  0
                 catch ( IOException f )
 156  
                 {
 157  
                     // do nothing
 158  0
                 }
 159  
             }
 160  
 
 161  1
             throw new AuthenticationException( "Could not connect to server.", e );
 162  35
         }
 163  
 
 164  
         try
 165  
         {
 166  35
             if ( !ftp.login( username, password ) )
 167  
             {
 168  0
                 throw new AuthenticationException( "Cannot login to remote system" );
 169  
             }
 170  
 
 171  35
             fireSessionDebug( "Remote system is " + ftp.getSystemName() );
 172  
 
 173  
             // Set to binary mode.
 174  35
             ftp.setFileType( FTP.BINARY_FILE_TYPE );
 175  35
             ftp.setListHiddenFiles( true );
 176  
 
 177  
             // Use passive mode as default because most of us are
 178  
             // behind firewalls these days.
 179  35
             if ( isPassiveMode() )
 180  
             {
 181  35
                 ftp.enterLocalPassiveMode();
 182  
             }
 183  
         }
 184  0
         catch ( IOException e )
 185  
         {
 186  0
             throw new ConnectionException( "Cannot login to remote system", e );
 187  35
         }
 188  35
     }
 189  
 
 190  
     protected void firePutCompleted( Resource resource, File file )
 191  
     {
 192  
         try
 193  
         {
 194  
             // TODO [BP]: verify the order is correct
 195  14
             ftp.completePendingCommand();
 196  
 
 197  14
             RepositoryPermissions permissions = repository.getPermissions();
 198  
 
 199  14
             if ( permissions != null && permissions.getGroup() != null )
 200  
             {
 201  
                 // ignore failures
 202  0
                 ftp.sendSiteCommand( "CHGRP " + permissions.getGroup() + " " + resource.getName() );
 203  
             }
 204  
 
 205  14
             if ( permissions != null && permissions.getFileMode() != null )
 206  
             {
 207  
                 // ignore failures
 208  0
                 ftp.sendSiteCommand( "CHMOD " + permissions.getFileMode() + " " + resource.getName() );
 209  
             }
 210  
         }
 211  0
         catch ( IOException e )
 212  
         {
 213  
             // TODO: handle
 214  
             // michal I am not sure  what error means in that context
 215  
             // I think that we will be able to recover or simply we will fail later on
 216  14
         }
 217  
 
 218  14
         super.firePutCompleted( resource, file );
 219  14
     }
 220  
 
 221  
     protected void fireGetCompleted( Resource resource, File localFile )
 222  
     {
 223  
         try
 224  
         {
 225  23
             ftp.completePendingCommand();
 226  
         }
 227  0
         catch ( IOException e )
 228  
         {
 229  
             // TODO: handle
 230  
             // michal I am not sure  what error means in that context
 231  
             // actually I am not even sure why we have to invoke that command
 232  
             // I think that we will be able to recover or simply we will fail later on
 233  23
         }
 234  23
         super.fireGetCompleted( resource, localFile );
 235  23
     }
 236  
 
 237  
     public void closeConnection()
 238  
         throws ConnectionException
 239  
     {
 240  35
         if ( ftp != null && ftp.isConnected() )
 241  
         {
 242  
             try
 243  
             {
 244  
                 // This is a NPE rethink shutting down the streams
 245  35
                 ftp.disconnect();
 246  
             }
 247  0
             catch ( IOException e )
 248  
             {
 249  0
                 throw new ConnectionException( "Failed to close connection to FTP repository", e );
 250  35
             }
 251  
         }
 252  35
     }
 253  
 
 254  
     public void fillOutputData( OutputData outputData )
 255  
         throws TransferFailedException
 256  
     {
 257  
         OutputStream os;
 258  
 
 259  14
         Resource resource = outputData.getResource();
 260  
 
 261  14
         RepositoryPermissions permissions = repository.getPermissions();
 262  
 
 263  
         try
 264  
         {
 265  14
             if ( !ftp.changeWorkingDirectory( getRepository().getBasedir() ) )
 266  
             {
 267  0
                 throw new TransferFailedException(
 268  
                     "Required directory: '" + getRepository().getBasedir() + "' " + "is missing" );
 269  
             }
 270  
 
 271  14
             String[] dirs = PathUtils.dirnames( resource.getName() );
 272  
 
 273  19
             for ( int i = 0; i < dirs.length; i++ )
 274  
             {
 275  5
                 boolean dirChanged = ftp.changeWorkingDirectory( dirs[i] );
 276  
 
 277  5
                 if ( !dirChanged )
 278  
                 {
 279  
                     // first, try to create it
 280  1
                     boolean success = ftp.makeDirectory( dirs[i] );
 281  
 
 282  1
                     if ( success )
 283  
                     {
 284  1
                         if ( permissions != null && permissions.getGroup() != null )
 285  
                         {
 286  
                             // ignore failures
 287  0
                             ftp.sendSiteCommand( "CHGRP " + permissions.getGroup() + " " + dirs[i] );
 288  
                         }
 289  
 
 290  1
                         if ( permissions != null && permissions.getDirectoryMode() != null )
 291  
                         {
 292  
                             // ignore failures
 293  0
                             ftp.sendSiteCommand( "CHMOD " + permissions.getDirectoryMode() + " " + dirs[i] );
 294  
                         }
 295  
 
 296  1
                         dirChanged = ftp.changeWorkingDirectory( dirs[i] );
 297  
                     }
 298  
                 }
 299  
 
 300  5
                 if ( !dirChanged )
 301  
                 {
 302  0
                     throw new TransferFailedException( "Unable to create directory " + dirs[i] );
 303  
                 }
 304  
             }
 305  
 
 306  
             // we come back to original basedir so
 307  
             // FTP wagon is ready for next requests
 308  14
             if ( !ftp.changeWorkingDirectory( getRepository().getBasedir() ) )
 309  
             {
 310  0
                 throw new TransferFailedException( "Unable to return to the base directory" );
 311  
             }
 312  
 
 313  14
             os = ftp.storeFileStream( resource.getName() );
 314  
 
 315  14
             if ( os == null )
 316  
             {
 317  0
                 String msg =
 318  
                     "Cannot transfer resource:  '" + resource + "'. Output stream is null. FTP Server response: "
 319  
                         + ftp.getReplyString();
 320  
 
 321  0
                 throw new TransferFailedException( msg );
 322  
 
 323  
             }
 324  
 
 325  14
             fireTransferDebug( "resource = " + resource );
 326  
 
 327  
         }
 328  0
         catch ( IOException e )
 329  
         {
 330  0
             throw new TransferFailedException( "Error transferring over FTP", e );
 331  14
         }
 332  
 
 333  14
         outputData.setOutputStream( os );
 334  
 
 335  14
     }
 336  
 
 337  
     // ----------------------------------------------------------------------
 338  
     //
 339  
     // ----------------------------------------------------------------------
 340  
 
 341  
     public void fillInputData( InputData inputData )
 342  
         throws TransferFailedException, ResourceDoesNotExistException
 343  
     {
 344  
         InputStream is;
 345  
 
 346  31
         Resource resource = inputData.getResource();
 347  
 
 348  
         try
 349  
         {
 350  31
             ftpChangeDirectory( resource );
 351  
 
 352  31
             String filename = PathUtils.filename( resource.getName() );
 353  31
             FTPFile[] ftpFiles = ftp.listFiles( filename );
 354  
 
 355  31
             if ( ftpFiles == null || ftpFiles.length <= 0 )
 356  
             {
 357  4
                 throw new ResourceDoesNotExistException( "Could not find file: '" + resource + "'" );
 358  
             }
 359  
 
 360  27
             long contentLength = ftpFiles[0].getSize();
 361  
 
 362  
             //@todo check how it works! javadoc of common login says:
 363  
             // Returns the file timestamp. This usually the last modification time.
 364  
             //
 365  27
             Calendar timestamp = ftpFiles[0].getTimestamp();
 366  27
             long lastModified = timestamp != null ? timestamp.getTimeInMillis() : 0;
 367  
 
 368  27
             resource.setContentLength( contentLength );
 369  
 
 370  27
             resource.setLastModified( lastModified );
 371  
 
 372  27
             is = ftp.retrieveFileStream( filename );
 373  
         }
 374  0
         catch ( IOException e )
 375  
         {
 376  0
             throw new TransferFailedException( "Error transferring file via FTP", e );
 377  27
         }
 378  
 
 379  27
         inputData.setInputStream( is );
 380  27
     }
 381  
 
 382  
     private void ftpChangeDirectory( Resource resource )
 383  
         throws IOException, TransferFailedException, ResourceDoesNotExistException
 384  
     {
 385  36
         if ( !ftp.changeWorkingDirectory( getRepository().getBasedir() ) )
 386  
         {
 387  0
             throw new ResourceDoesNotExistException(
 388  
                 "Required directory: '" + getRepository().getBasedir() + "' " + "is missing" );
 389  
         }
 390  
 
 391  36
         String[] dirs = PathUtils.dirnames( resource.getName() );
 392  
 
 393  83
         for ( int i = 0; i < dirs.length; i++ )
 394  
         {
 395  48
             boolean dirChanged = ftp.changeWorkingDirectory( dirs[i] );
 396  
 
 397  48
             if ( !dirChanged )
 398  
             {
 399  1
                 String msg = "Resource " + resource + " not found. Directory " + dirs[i] + " does not exist";
 400  
 
 401  1
                 throw new ResourceDoesNotExistException( msg );
 402  
             }
 403  
         }
 404  35
     }
 405  
 
 406  37
     public class PrintCommandListener
 407  
         implements ProtocolCommandListener
 408  
     {
 409  
         private FtpWagon wagon;
 410  
 
 411  
         public PrintCommandListener( FtpWagon wagon )
 412  36
         {
 413  36
             this.wagon = wagon;
 414  36
         }
 415  
 
 416  
         public void protocolCommandSent( ProtocolCommandEvent event )
 417  
         {
 418  564
             wagon.fireSessionDebug( "Command sent: " + event.getMessage() );
 419  
 
 420  564
         }
 421  
 
 422  
         public void protocolReplyReceived( ProtocolCommandEvent event )
 423  
         {
 424  684
             wagon.fireSessionDebug( "Reply received: " + event.getMessage() );
 425  684
         }
 426  
     }
 427  
 
 428  
     protected void fireSessionDebug( String msg )
 429  
     {
 430  1283
         super.fireSessionDebug( msg );
 431  1283
     }
 432  
 
 433  
     public List<String> getFileList( String destinationDirectory )
 434  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 435  
     {
 436  3
         Resource resource = new Resource( destinationDirectory );
 437  
 
 438  
         try
 439  
         {
 440  3
             ftpChangeDirectory( resource );
 441  
 
 442  3
             String filename = PathUtils.filename( resource.getName() );
 443  3
             FTPFile[] ftpFiles = ftp.listFiles( filename );
 444  
 
 445  3
             if ( ftpFiles == null || ftpFiles.length <= 0 )
 446  
             {
 447  1
                 throw new ResourceDoesNotExistException( "Could not find file: '" + resource + "'" );
 448  
             }
 449  
 
 450  2
             List<String> ret = new ArrayList<String>();
 451  8
             for ( int i = 0; i < ftpFiles.length; i++ )
 452  
             {
 453  6
                 String name = ftpFiles[i].getName();
 454  
 
 455  6
                 if ( ftpFiles[i].isDirectory() && !name.endsWith( "/" ) )
 456  
                 {
 457  1
                     name += "/";
 458  
                 }
 459  
 
 460  6
                 ret.add( name );
 461  
             }
 462  
 
 463  2
             return ret;
 464  
         }
 465  0
         catch ( IOException e )
 466  
         {
 467  0
             throw new TransferFailedException( "Error transferring file via FTP", e );
 468  
         }
 469  
     }
 470  
 
 471  
     public boolean resourceExists( String resourceName )
 472  
         throws TransferFailedException, AuthorizationException
 473  
     {
 474  2
         Resource resource = new Resource( resourceName );
 475  
 
 476  
         try
 477  
         {
 478  2
             ftpChangeDirectory( resource );
 479  
 
 480  1
             String filename = PathUtils.filename( resource.getName() );
 481  1
             int status = ftp.stat( filename );
 482  
 
 483  1
             return ( ( status == FTPReply.FILE_STATUS ) || ( status == FTPReply.DIRECTORY_STATUS ) || ( status
 484  
                 == FTPReply.FILE_STATUS_OK ) // not in the RFC but used by some FTP servers
 485  
                 || ( status == FTPReply.COMMAND_OK )     // not in the RFC but used by some FTP servers
 486  
                 || ( status == FTPReply.SYSTEM_STATUS ) );
 487  
         }
 488  0
         catch ( IOException e )
 489  
         {
 490  0
             throw new TransferFailedException( "Error transferring file via FTP", e );
 491  
         }
 492  1
         catch ( ResourceDoesNotExistException e )
 493  
         {
 494  1
             return false;
 495  
         }
 496  
     }
 497  
 
 498  
     public boolean supportsDirectoryCopy()
 499  
     {
 500  5
         return true;
 501  
     }
 502  
 
 503  
     public void putDirectory( File sourceDirectory, String destinationDirectory )
 504  
         throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
 505  
     {
 506  
 
 507  
         // Change to root.
 508  
         try
 509  
         {
 510  5
             if ( !ftp.changeWorkingDirectory( getRepository().getBasedir() ) )
 511  
             {
 512  1
                 RepositoryPermissions permissions = getRepository().getPermissions();
 513  1
                 if ( !makeFtpDirectoryRecursive( getRepository().getBasedir(), permissions ) )
 514  
                 {
 515  0
                     throw new TransferFailedException(
 516  
                         "Required directory: '" + getRepository().getBasedir() + "' " + "could not get created" );
 517  
                 }
 518  
 
 519  
                 // try it again sam ...
 520  1
                 if ( !ftp.changeWorkingDirectory( getRepository().getBasedir() ) )
 521  
                 {
 522  0
                     throw new TransferFailedException( "Required directory: '" + getRepository().getBasedir() + "' "
 523  
                                                            + "is missing and could not get created" );
 524  
                 }
 525  
             }
 526  
         }
 527  0
         catch ( IOException e )
 528  
         {
 529  0
             throw new TransferFailedException( "Cannot change to root path " + getRepository().getBasedir(), e );
 530  5
         }
 531  
 
 532  5
         fireTransferDebug(
 533  
             "Recursively uploading directory " + sourceDirectory.getAbsolutePath() + " as " + destinationDirectory );
 534  5
         ftpRecursivePut( sourceDirectory, destinationDirectory );
 535  5
     }
 536  
 
 537  
     private void ftpRecursivePut( File sourceFile, String fileName )
 538  
         throws TransferFailedException
 539  
     {
 540  42
         final RepositoryPermissions permissions = repository.getPermissions();
 541  
 
 542  42
         fireTransferDebug( "processing = " + sourceFile.getAbsolutePath() + " as " + fileName );
 543  
 
 544  42
         if ( sourceFile.isDirectory() )
 545  
         {
 546  23
             if ( !fileName.equals( "." ) )
 547  
             {
 548  
                 try
 549  
                 {
 550  
                     // change directory if it already exists.
 551  22
                     if ( !ftp.changeWorkingDirectory( fileName ) )
 552  
                     {
 553  
                         // first, try to create it
 554  22
                         if ( makeFtpDirectoryRecursive( fileName, permissions ) )
 555  
                         {
 556  22
                             if ( !ftp.changeWorkingDirectory( fileName ) )
 557  
                             {
 558  0
                                 throw new TransferFailedException(
 559  
                                     "Unable to change cwd on ftp server to " + fileName + " when processing "
 560  
                                         + sourceFile.getAbsolutePath() );
 561  
                             }
 562  
                         }
 563  
                         else
 564  
                         {
 565  0
                             throw new TransferFailedException(
 566  
                                 "Unable to create directory " + fileName + " when processing "
 567  
                                     + sourceFile.getAbsolutePath() );
 568  
                         }
 569  
                     }
 570  
                 }
 571  0
                 catch ( IOException e )
 572  
                 {
 573  0
                     throw new TransferFailedException(
 574  
                         "IOException caught while processing path at " + sourceFile.getAbsolutePath(), e );
 575  22
                 }
 576  
             }
 577  
 
 578  23
             File[] files = sourceFile.listFiles();
 579  23
             if ( files != null && files.length > 0 )
 580  
             {
 581  23
                 fireTransferDebug( "listing children of = " + sourceFile.getAbsolutePath() + " found " + files.length );
 582  
 
 583  
                 // Directories first, then files. Let's go deep early.
 584  60
                 for ( int i = 0; i < files.length; i++ )
 585  
                 {
 586  37
                     if ( files[i].isDirectory() )
 587  
                     {
 588  18
                         ftpRecursivePut( files[i], files[i].getName() );
 589  
                     }
 590  
                 }
 591  60
                 for ( int i = 0; i < files.length; i++ )
 592  
                 {
 593  37
                     if ( !files[i].isDirectory() )
 594  
                     {
 595  19
                         ftpRecursivePut( files[i], files[i].getName() );
 596  
                     }
 597  
                 }
 598  
             }
 599  
 
 600  
             // Step back up a directory once we're done with the contents of this one.
 601  
             try
 602  
             {
 603  23
                 ftp.changeToParentDirectory();
 604  
             }
 605  0
             catch ( IOException e )
 606  
             {
 607  0
                 throw new TransferFailedException( "IOException caught while attempting to step up to parent directory"
 608  
                                                        + " after successfully processing "
 609  
                                                        + sourceFile.getAbsolutePath(), e );
 610  23
             }
 611  23
         }
 612  
         else
 613  
         {
 614  
             // Oh how I hope and pray, in denial, but today I am still just a file.
 615  
 
 616  19
             FileInputStream sourceFileStream = null;
 617  
             try
 618  
             {
 619  19
                 sourceFileStream = new FileInputStream( sourceFile );
 620  
 
 621  
                 // It's a file. Upload it in the current directory.
 622  19
                 if ( ftp.storeFile( fileName, sourceFileStream ) )
 623  
                 {
 624  19
                     if ( permissions != null )
 625  
                     {
 626  
                         // Process permissions; note that if we get errors or exceptions here, they are ignored.
 627  
                         // This appears to be a conscious decision, based on other parts of this code.
 628  19
                         String group = permissions.getGroup();
 629  19
                         if ( group != null )
 630  
                         {
 631  
                             try
 632  
                             {
 633  0
                                 ftp.sendSiteCommand( "CHGRP " + permissions.getGroup() );
 634  
                             }
 635  0
                             catch ( IOException e )
 636  
                             {
 637  0
                             }
 638  
                         }
 639  19
                         String mode = permissions.getFileMode();
 640  19
                         if ( mode != null )
 641  
                         {
 642  
                             try
 643  
                             {
 644  0
                                 ftp.sendSiteCommand( "CHMOD " + permissions.getDirectoryMode() );
 645  
                             }
 646  0
                             catch ( IOException e )
 647  
                             {
 648  0
                             }
 649  
                         }
 650  19
                     }
 651  
                 }
 652  
                 else
 653  
                 {
 654  0
                     String msg =
 655  
                         "Cannot transfer resource:  '" + sourceFile.getAbsolutePath() + "' FTP Server response: "
 656  
                             + ftp.getReplyString();
 657  0
                     throw new TransferFailedException( msg );
 658  
                 }
 659  
             }
 660  0
             catch ( IOException e )
 661  
             {
 662  0
                 throw new TransferFailedException(
 663  
                     "IOException caught while attempting to upload " + sourceFile.getAbsolutePath(), e );
 664  
             }
 665  
             finally
 666  
             {
 667  19
                 IOUtil.close( sourceFileStream );
 668  19
             }
 669  
 
 670  
         }
 671  
 
 672  42
         fireTransferDebug( "completed = " + sourceFile.getAbsolutePath() );
 673  42
     }
 674  
 
 675  
     /**
 676  
      * Set the permissions (if given) for the underlying folder.
 677  
      * Note: Since the FTP SITE command might be server dependent, we cannot
 678  
      * rely on the functionality available on each FTP server!
 679  
      * So we can only try and hope it works (and catch away all Exceptions).
 680  
      *
 681  
      * @param permissions group and directory permissions
 682  
      */
 683  
     private void setPermissions( RepositoryPermissions permissions )
 684  
     {
 685  4
         if ( permissions != null )
 686  
         {
 687  
             // Process permissions; note that if we get errors or exceptions here, they are ignored.
 688  
             // This appears to be a conscious decision, based on other parts of this code.
 689  4
             String group = permissions.getGroup();
 690  4
             if ( group != null )
 691  
             {
 692  
                 try
 693  
                 {
 694  0
                     ftp.sendSiteCommand( "CHGRP " + permissions.getGroup() );
 695  
                 }
 696  0
                 catch ( IOException e )
 697  
                 {
 698  0
                 }
 699  
             }
 700  4
             String mode = permissions.getDirectoryMode();
 701  4
             if ( mode != null )
 702  
             {
 703  
                 try
 704  
                 {
 705  0
                     ftp.sendSiteCommand( "CHMOD " + permissions.getDirectoryMode() );
 706  
                 }
 707  0
                 catch ( IOException e )
 708  
                 {
 709  0
                 }
 710  
             }
 711  
         }
 712  4
     }
 713  
 
 714  
     /**
 715  
      * Recursively create directories.
 716  
      *
 717  
      * @param fileName    the path to create (might be nested)
 718  
      * @param permissions
 719  
      * @return ok
 720  
      * @throws IOException
 721  
      */
 722  
     private boolean makeFtpDirectoryRecursive( String fileName, RepositoryPermissions permissions )
 723  
         throws IOException
 724  
     {
 725  27
         if ( fileName == null || fileName.length() == 0
 726  
             || fileName.replace( '/', '_' ).trim().length() == 0 ) // if a string is '/', '//' or similar
 727  
         {
 728  0
             return false;
 729  
         }
 730  
 
 731  27
         int slashPos = fileName.indexOf( "/" );
 732  27
         String oldPwd = null;
 733  27
         boolean ok = true;
 734  
 
 735  27
         if ( slashPos == 0 )
 736  
         {
 737  
             // this is an absolute directory
 738  1
             oldPwd = ftp.printWorkingDirectory();
 739  
 
 740  
             // start with the root
 741  1
             ftp.changeWorkingDirectory( "/" );
 742  1
             fileName = fileName.substring( 1 );
 743  
 
 744  
             // look up the next path separator
 745  1
             slashPos = fileName.indexOf( "/" );
 746  
         }
 747  
 
 748  27
         if ( slashPos >= 0 && slashPos < ( fileName.length() - 1 ) ) // not only a slash at the end, like in 'newDir/'
 749  
         {
 750  4
             if ( oldPwd == null )
 751  
             {
 752  3
                 oldPwd = ftp.printWorkingDirectory();
 753  
             }
 754  
 
 755  4
             String nextDir = fileName.substring( 0, slashPos );
 756  
 
 757  
             // we only create the nextDir if it doesn't yet exist
 758  4
             if ( !ftp.changeWorkingDirectory( nextDir ) )
 759  
             {
 760  3
                 ok &= ftp.makeDirectory( nextDir );
 761  
             }
 762  
 
 763  4
             if ( ok )
 764  
             {
 765  
                 // set the permissions for the freshly created directory
 766  4
                 setPermissions( permissions );
 767  
 
 768  4
                 ftp.changeWorkingDirectory( nextDir );
 769  
 
 770  
                 // now create the deeper directories
 771  4
                 String remainingDirs = fileName.substring( slashPos + 1 );
 772  4
                 ok &= makeFtpDirectoryRecursive( remainingDirs, permissions );
 773  
             }
 774  4
         }
 775  
         else
 776  
         {
 777  23
             ok = ftp.makeDirectory( fileName );
 778  
         }
 779  
 
 780  27
         if ( oldPwd != null )
 781  
         {
 782  
             // change back to the old working directory
 783  4
             ftp.changeWorkingDirectory( oldPwd );
 784  
         }
 785  
 
 786  27
         return ok;
 787  
     }
 788  
 
 789  
     public String getControlEncoding()
 790  
     {
 791  36
         return controlEncoding;
 792  
     }
 793  
 
 794  
     public void setControlEncoding( String controlEncoding )
 795  
     {
 796  37
         this.controlEncoding = controlEncoding;
 797  37
     }
 798  
 }