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: */
017: package org.apache.commons.vfs.provider.ftp;
018:
019: import org.apache.commons.net.ftp.FTPClient;
020: import org.apache.commons.net.ftp.FTPFile;
021: import org.apache.commons.vfs.FileSystemException;
022: import org.apache.commons.vfs.FileSystemOptions;
023: import org.apache.commons.vfs.UserAuthenticationData;
024: import org.apache.commons.vfs.util.UserAuthenticatorUtils;
025: import org.apache.commons.vfs.provider.GenericFileName;
026:
027: import java.io.IOException;
028: import java.io.InputStream;
029: import java.io.OutputStream;
030:
031: /**
032: * A wrapper to the FTPClient to allow automatic reconnect on connection loss.<br />
033: * I decided to not to use eg. noop() to determine the state of the connection to avoid unnecesary server round-trips.
034: */
035: class FTPClientWrapper implements FtpClient {
036: private final GenericFileName root;
037: private final FileSystemOptions fileSystemOptions;
038:
039: private FTPClient ftpClient = null;
040:
041: FTPClientWrapper(final GenericFileName root,
042: final FileSystemOptions fileSystemOptions)
043: throws FileSystemException {
044: this .root = root;
045: this .fileSystemOptions = fileSystemOptions;
046: getFtpClient(); // fail-fast
047: }
048:
049: public GenericFileName getRoot() {
050: return root;
051: }
052:
053: public FileSystemOptions getFileSystemOptions() {
054: return fileSystemOptions;
055: }
056:
057: private FTPClient createClient() throws FileSystemException {
058: final GenericFileName rootName = getRoot();
059:
060: UserAuthenticationData authData = null;
061: try {
062: authData = UserAuthenticatorUtils.authenticate(
063: fileSystemOptions,
064: FtpFileProvider.AUTHENTICATOR_TYPES);
065:
066: return FtpClientFactory.createConnection(rootName
067: .getHostName(), rootName.getPort(),
068: UserAuthenticatorUtils.getData(authData,
069: UserAuthenticationData.USERNAME,
070: UserAuthenticatorUtils.toChar(rootName
071: .getUserName())),
072: UserAuthenticatorUtils.getData(authData,
073: UserAuthenticationData.PASSWORD,
074: UserAuthenticatorUtils.toChar(rootName
075: .getPassword())), rootName
076: .getPath(), getFileSystemOptions());
077: } finally {
078: UserAuthenticatorUtils.cleanup(authData);
079: }
080: }
081:
082: private FTPClient getFtpClient() throws FileSystemException {
083: if (ftpClient == null) {
084: ftpClient = createClient();
085: }
086:
087: return ftpClient;
088: }
089:
090: public boolean isConnected() throws FileSystemException {
091: return ftpClient != null && ftpClient.isConnected();
092: }
093:
094: public void disconnect() throws IOException {
095: try {
096: getFtpClient().disconnect();
097: } finally {
098: ftpClient = null;
099: }
100: }
101:
102: public FTPFile[] listFiles(String relPath) throws IOException {
103: try {
104: return getFtpClient().listFiles(relPath);
105: } catch (IOException e) {
106: disconnect();
107: return getFtpClient().listFiles(relPath);
108: }
109: }
110:
111: public boolean removeDirectory(String relPath) throws IOException {
112: try {
113: return getFtpClient().removeDirectory(relPath);
114: } catch (IOException e) {
115: disconnect();
116: return getFtpClient().removeDirectory(relPath);
117: }
118: }
119:
120: public boolean deleteFile(String relPath) throws IOException {
121: try {
122: return getFtpClient().deleteFile(relPath);
123: } catch (IOException e) {
124: disconnect();
125: return getFtpClient().deleteFile(relPath);
126: }
127: }
128:
129: public boolean rename(String oldName, String newName)
130: throws IOException {
131: try {
132: return getFtpClient().rename(oldName, newName);
133: } catch (IOException e) {
134: disconnect();
135: return getFtpClient().rename(oldName, newName);
136: }
137: }
138:
139: public boolean makeDirectory(String relPath) throws IOException {
140: try {
141: return getFtpClient().makeDirectory(relPath);
142: } catch (IOException e) {
143: disconnect();
144: return getFtpClient().makeDirectory(relPath);
145: }
146: }
147:
148: public boolean completePendingCommand() throws IOException {
149: if (ftpClient != null) {
150: return getFtpClient().completePendingCommand();
151: }
152:
153: return true;
154: }
155:
156: public InputStream retrieveFileStream(String relPath)
157: throws IOException {
158: try {
159: return getFtpClient().retrieveFileStream(relPath);
160: } catch (IOException e) {
161: disconnect();
162: return getFtpClient().retrieveFileStream(relPath);
163: }
164: }
165:
166: public InputStream retrieveFileStream(String relPath,
167: long restartOffset) throws IOException {
168: try {
169: FTPClient client = getFtpClient();
170: client.setRestartOffset(restartOffset);
171: return client.retrieveFileStream(relPath);
172: } catch (IOException e) {
173: disconnect();
174:
175: FTPClient client = getFtpClient();
176: client.setRestartOffset(restartOffset);
177: return client.retrieveFileStream(relPath);
178: }
179: }
180:
181: public OutputStream appendFileStream(String relPath)
182: throws IOException {
183: try {
184: return getFtpClient().appendFileStream(relPath);
185: } catch (IOException e) {
186: disconnect();
187: return getFtpClient().appendFileStream(relPath);
188: }
189: }
190:
191: public OutputStream storeFileStream(String relPath)
192: throws IOException {
193: try {
194: return getFtpClient().storeFileStream(relPath);
195: } catch (IOException e) {
196: disconnect();
197: return getFtpClient().storeFileStream(relPath);
198: }
199: }
200:
201: public boolean abort() throws IOException {
202: try {
203: // imario@apache.org: 2005-02-14
204: // it should be better to really "abort" the transfer, but
205: // currently I didnt manage to make it work - so lets "abort" the hard way.
206: // return getFtpClient().abort();
207:
208: disconnect();
209: return true;
210: } catch (IOException e) {
211: disconnect();
212: }
213: return true;
214: }
215:
216: public String getReplyString() throws IOException {
217: return getFtpClient().getReplyString();
218: }
219: }
|