001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2.provider.ftp; 018 019import java.io.IOException; 020import java.util.Collection; 021import java.util.concurrent.atomic.AtomicReference; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.apache.commons.vfs2.Capability; 026import org.apache.commons.vfs2.FileObject; 027import org.apache.commons.vfs2.FileSystemException; 028import org.apache.commons.vfs2.FileSystemOptions; 029import org.apache.commons.vfs2.VfsLog; 030import org.apache.commons.vfs2.provider.AbstractFileName; 031import org.apache.commons.vfs2.provider.AbstractFileSystem; 032import org.apache.commons.vfs2.provider.GenericFileName; 033 034/** 035 * An FTP file system. 036 */ 037public class FtpFileSystem extends AbstractFileSystem { 038 039 private static final Log LOG = LogFactory.getLog(FtpFileSystem.class); 040 041 // private final String hostname; 042 // private final int port; 043 // private final String username; 044 // private final String password; 045 046 // An idle client 047 private final AtomicReference<FtpClient> idleClient = new AtomicReference<>(); 048 049 /** 050 * Constructs a new instance. 051 * 052 * @param rootName The root of the file system. 053 * @param ftpClient The FtpClient. 054 * @param fileSystemOptions The FileSystemOptions. 055 * @since 2.0 (was protected) 056 */ 057 public FtpFileSystem(final GenericFileName rootName, final FtpClient ftpClient, 058 final FileSystemOptions fileSystemOptions) { 059 super(rootName, null, fileSystemOptions); 060 // hostname = rootName.getHostName(); 061 // port = rootName.getPort(); 062 063 idleClient.set(ftpClient); 064 } 065 066 /** 067 * Adds the capabilities of this file system. 068 */ 069 @Override 070 protected void addCapabilities(final Collection<Capability> caps) { 071 caps.addAll(FtpFileProvider.CAPABILITIES); 072 } 073 074 /** 075 * Cleans up the connection to the server. 076 * 077 * @param client The FtpClient. 078 */ 079 private void closeConnection(final FtpClient client) { 080 try { 081 // Clean up 082 if (client.isConnected()) { 083 client.disconnect(); 084 } 085 } catch (final IOException e) { 086 // getLogger().warn("vfs.provider.ftp/close-connection.error", e); 087 VfsLog.warn(getLogger(), LOG, "vfs.provider.ftp/close-connection.error", e); 088 } 089 } 090 091 /** 092 * Creates a file object. 093 */ 094 @Override 095 protected FileObject createFile(final AbstractFileName name) throws FileSystemException { 096 return new FtpFileObject(name, this, getRootName()); 097 } 098 099 /** 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}