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       * Constructs a new instance.
51       *
52       * @param rootName The root of the file system.
53       * @param ftpClient The FtpClient.
54       * @param fileSystemOptions The FileSystemOptions.
55       * @since 2.0 (was protected)
56       */
57      public FtpFileSystem(final GenericFileName rootName, final FtpClient ftpClient,
58              final FileSystemOptions fileSystemOptions) {
59          super(rootName, null, fileSystemOptions);
60          // hostname = rootName.getHostName();
61          // port = rootName.getPort();
62  
63          idleClient.set(ftpClient);
64      }
65  
66      /**
67       * Adds the capabilities of this file system.
68       */
69      @Override
70      protected void addCapabilities(final Collection<Capability> caps) {
71          caps.addAll(FtpFileProvider.CAPABILITIES);
72      }
73  
74      /**
75       * Cleans up the connection to the server.
76       *
77       * @param client The FtpClient.
78       */
79      private void closeConnection(final FtpClient client) {
80          try {
81              // Clean up
82              if (client.isConnected()) {
83                  client.disconnect();
84              }
85          } catch (final IOException e) {
86              // getLogger().warn("vfs.provider.ftp/close-connection.error", e);
87              VfsLog.warn(getLogger(), LOG, "vfs.provider.ftp/close-connection.error", e);
88          }
89      }
90  
91      /**
92       * Creates a file object.
93       */
94      @Override
95      protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
96          return new FtpFileObject(name, this, getRootName());
97      }
98  
99      /**
100      * Gets the wrapper to access this file system.
101      *
102      * @return new instance.
103      * @throws FileSystemException if any error occurs.
104      * @since 2.1
105      */
106     protected FTPClientWrapper createWrapper() throws FileSystemException {
107         return new FTPClientWrapper((GenericFileName) getRoot().getName(), getFileSystemOptions());
108     }
109 
110     @Override
111     protected void doCloseCommunicationLink() {
112         final FtpClient idle = idleClient.getAndSet(null);
113         // Clean up the connection
114         if (idle != null) {
115             closeConnection(idle);
116         }
117     }
118 
119     /**
120      * Creates an FTP client to use.
121      *
122      * @return An FTPClient.
123      * @throws FileSystemException if an error occurs.
124      */
125     public FtpClient getClient() throws FileSystemException {
126         FtpClient client = idleClient.getAndSet(null);
127 
128         if (client == null || !client.isConnected()) {
129             client = createWrapper();
130         }
131 
132         return client;
133     }
134 
135     /**
136      * Returns an FTP client after use.
137      *
138      * @param client The FTPClient.
139      */
140     public void putClient(final FtpClient client) {
141         // Save client for reuse if none is idle.
142         if (!idleClient.compareAndSet(null, client)) {
143             // An idle client is already present so close the connection.
144             closeConnection(client);
145         }
146     }
147 }