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