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.vfs2.provider.ftp;
18  
19  import java.io.IOException;
20  import java.util.Collection;
21  import java.util.concurrent.atomic.AtomicReference;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.commons.vfs2.Capability;
26  import org.apache.commons.vfs2.FileObject;
27  import org.apache.commons.vfs2.FileSystemException;
28  import org.apache.commons.vfs2.FileSystemOptions;
29  import org.apache.commons.vfs2.VfsLog;
30  import org.apache.commons.vfs2.provider.AbstractFileName;
31  import org.apache.commons.vfs2.provider.AbstractFileSystem;
32  import org.apache.commons.vfs2.provider.GenericFileName;
33  
34  /**
35   * An FTP file system.
36   */
37  public class FtpFileSystem extends AbstractFileSystem {
38  
39      private static final Log LOG = LogFactory.getLog(FtpFileSystem.class);
40  
41      // private final String hostname;
42      // private final int port;
43      // private final String username;
44      // private final String password;
45  
46      // An idle client
47      private final AtomicReference<FtpClient> idleClient = new AtomicReference<>();
48  
49      /**
50       * @param rootName The root of the file system.
51       * @param ftpClient The FtpClient.
52       * @param fileSystemOptions The FileSystemOptions.
53       * @since 2.0 (was protected)
54       */
55      public FtpFileSystem(final GenericFileName rootName, final FtpClient ftpClient,
56              final FileSystemOptions fileSystemOptions) {
57          super(rootName, null, fileSystemOptions);
58          // hostname = rootName.getHostName();
59          // port = rootName.getPort();
60  
61          idleClient.set(ftpClient);
62      }
63  
64      /**
65       * Adds the capabilities of this file system.
66       */
67      @Override
68      protected void addCapabilities(final Collection<Capability> caps) {
69          caps.addAll(FtpFileProvider.CAPABILITIES);
70      }
71  
72      /**
73       * Cleans up the connection to the server.
74       *
75       * @param client The FtpClient.
76       */
77      private void closeConnection(final FtpClient client) {
78          try {
79              // Clean up
80              if (client.isConnected()) {
81                  client.disconnect();
82              }
83          } catch (final IOException e) {
84              // getLogger().warn("vfs.provider.ftp/close-connection.error", e);
85              VfsLog.warn(getLogger(), LOG, "vfs.provider.ftp/close-connection.error", e);
86          }
87      }
88  
89      /**
90       * Creates a file object.
91       */
92      @Override
93      protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
94          return new FtpFileObject(name, this, getRootName());
95      }
96  
97      /**
98       * Gets the wrapper to access this file system.
99       *
100      * @return new instance.
101      * @throws FileSystemException if any error occurs.
102      * @since 2.1
103      */
104     protected FTPClientWrapper createWrapper() throws FileSystemException {
105         return new FTPClientWrapper((GenericFileName) getRoot().getName(), getFileSystemOptions());
106     }
107 
108     @Override
109     protected void doCloseCommunicationLink() {
110         final FtpClient idle = idleClient.getAndSet(null);
111         // Clean up the connection
112         if (idle != null) {
113             closeConnection(idle);
114         }
115     }
116 
117     /**
118      * Creates an FTP client to use.
119      *
120      * @return An FTPCleint.
121      * @throws FileSystemException if an error occurs.
122      */
123     public FtpClient getClient() throws FileSystemException {
124         FtpClient client = idleClient.getAndSet(null);
125 
126         if (client == null || !client.isConnected()) {
127             client = createWrapper();
128         }
129 
130         return client;
131     }
132 
133     /**
134      * Returns an FTP client after use.
135      *
136      * @param client The FTPClient.
137      */
138     public void putClient(final FtpClient client) {
139         // Save client for reuse if none is idle.
140         if (!idleClient.compareAndSet(null, client)) {
141             // An idle client is already present so close the connection.
142             closeConnection(client);
143         }
144     }
145 }