View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.commons.vfs.provider.ftp;
    18
    19  import org.apache.commons.net.ftp.FTPClient;
    20  import org.apache.commons.net.ftp.FTPFile;
    21  import org.apache.commons.vfs.FileSystemException;
    22  import org.apache.commons.vfs.FileSystemOptions;
    23  import org.apache.commons.vfs.UserAuthenticationData;
    24  import org.apache.commons.vfs.util.UserAuthenticatorUtils;
    25  import org.apache.commons.vfs.provider.GenericFileName;
    26
    27  import java.io.IOException;
    28  import java.io.InputStream;
    29  import java.io.OutputStream;
    30
    31  /***
    32   * A wrapper to the FTPClient to allow automatic reconnect on connection loss.<br />
    33   * I decided to not to use eg. noop() to determine the state of the connection to avoid unnecesary server round-trips.
    34   */
    35  class FTPClientWrapper implements FtpClient
    36  {
    37      private final GenericFileName root;
    38      private final FileSystemOptions fileSystemOptions;
    39
    40      private FTPClient ftpClient = null;
    41
    42      FTPClientWrapper(final GenericFileName root, final FileSystemOptions fileSystemOptions) throws FileSystemException
    43      {
    44          this.root = root;
    45          this.fileSystemOptions = fileSystemOptions;
    46          getFtpClient(); // fail-fast
    47      }
    48
    49      public GenericFileName getRoot()
    50      {
    51          return root;
    52      }
    53
    54      public FileSystemOptions getFileSystemOptions()
    55      {
    56          return fileSystemOptions;
    57      }
    58
    59      private FTPClient createClient() throws FileSystemException
    60      {
    61          final GenericFileName rootName = getRoot();
    62
    63  		UserAuthenticationData authData = null;
    64  		try
    65  		{
    66  			authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, FtpFileProvider.AUTHENTICATOR_TYPES);
    67
    68  			return FtpClientFactory.createConnection(rootName.getHostName(),
    69  				rootName.getPort(),
    70  				UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName.getUserName())),
    71  				UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName.getPassword())),
    72  				rootName.getPath(),
    73  				getFileSystemOptions());
    74  		}
    75  		finally
    76  		{
    77  			UserAuthenticatorUtils.cleanup(authData);
    78  		}
    79  	}
    80
    81  	private FTPClient getFtpClient() throws FileSystemException
    82      {
    83          if (ftpClient == null)
    84          {
    85              ftpClient = createClient();
    86          }
    87
    88          return ftpClient;
    89      }
    90
    91      public boolean isConnected() throws FileSystemException
    92      {
    93          return getFtpClient().isConnected();
    94      }
    95
    96      public void disconnect() throws IOException
    97      {
    98          try
    99          {
    100             getFtpClient().disconnect();
    101         }
    102         finally
    103         {
    104             ftpClient = null;
    105         }
    106     }
    107
    108     public FTPFile[] listFiles(String relPath) throws IOException
    109     {
    110         try
    111         {
    112             return getFtpClient().listFiles(relPath);
    113         }
    114         catch (IOException e)
    115         {
    116             disconnect();
    117             return getFtpClient().listFiles(relPath);
    118         }
    119     }
    120
    121     public boolean removeDirectory(String relPath) throws IOException
    122     {
    123         try
    124         {
    125             return getFtpClient().removeDirectory(relPath);
    126         }
    127         catch (IOException e)
    128         {
    129             disconnect();
    130             return getFtpClient().removeDirectory(relPath);
    131         }
    132     }
    133
    134     public boolean deleteFile(String relPath) throws IOException
    135     {
    136         try
    137         {
    138             return getFtpClient().deleteFile(relPath);
    139         }
    140         catch (IOException e)
    141         {
    142             disconnect();
    143             return getFtpClient().deleteFile(relPath);
    144         }
    145     }
    146
    147     public boolean rename(String oldName, String newName) throws IOException
    148     {
    149         try
    150         {
    151             return getFtpClient().rename(oldName, newName);
    152         }
    153         catch (IOException e)
    154         {
    155             disconnect();
    156             return getFtpClient().rename(oldName, newName);
    157         }
    158     }
    159
    160     public boolean makeDirectory(String relPath) throws IOException
    161     {
    162         try
    163         {
    164             return getFtpClient().makeDirectory(relPath);
    165         }
    166         catch (IOException e)
    167         {
    168             disconnect();
    169             return getFtpClient().makeDirectory(relPath);
    170         }
    171     }
    172
    173     public boolean completePendingCommand() throws IOException
    174     {
    175         if (ftpClient != null)
    176         {
    177             return getFtpClient().completePendingCommand();
    178         }
    179
    180         return true;
    181     }
    182
    183     public InputStream retrieveFileStream(String relPath) throws IOException
    184     {
    185         try
    186         {
    187             return getFtpClient().retrieveFileStream(relPath);
    188         }
    189         catch (IOException e)
    190         {
    191             disconnect();
    192             return getFtpClient().retrieveFileStream(relPath);
    193         }
    194     }
    195
    196     public InputStream retrieveFileStream(String relPath, long restartOffset) throws IOException
    197     {
    198         try
    199         {
    200             FTPClient client = getFtpClient();
    201             client.setRestartOffset(restartOffset);
    202             return client.retrieveFileStream(relPath);
    203         }
    204         catch (IOException e)
    205         {
    206             disconnect();
    207
    208             FTPClient client = getFtpClient();
    209             client.setRestartOffset(restartOffset);
    210             return client.retrieveFileStream(relPath);
    211         }
    212     }
    213
    214     public OutputStream appendFileStream(String relPath) throws IOException
    215     {
    216         try
    217         {
    218             return getFtpClient().appendFileStream(relPath);
    219         }
    220         catch (IOException e)
    221         {
    222             disconnect();
    223             return getFtpClient().appendFileStream(relPath);
    224         }
    225     }
    226
    227     public OutputStream storeFileStream(String relPath) throws IOException
    228     {
    229         try
    230         {
    231             return getFtpClient().storeFileStream(relPath);
    232         }
    233         catch (IOException e)
    234         {
    235             disconnect();
    236             return getFtpClient().storeFileStream(relPath);
    237         }
    238     }
    239
    240     public boolean abort() throws IOException
    241     {
    242         try
    243         {
    244             // imario@apache.org: 2005-02-14
    245             // it should be better to really "abort" the transfer, but
    246             // currently I didnt manage to make it work - so lets "abort" the hard way.
    247             // return getFtpClient().abort();
    248
    249             disconnect();
    250             return true;
    251         }
    252         catch (IOException e)
    253         {
    254             disconnect();
    255         }
    256         return true;
    257     }
    258
    259     public String getReplyString() throws IOException
    260     {
    261         return getFtpClient().getReplyString();
    262     }
    263 }