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.vfs2.provider.ftp;
018
019 import java.io.IOException;
020
021 import org.apache.commons.net.ftp.FTP;
022 import org.apache.commons.net.ftp.FTPClient;
023 import org.apache.commons.net.ftp.FTPClientConfig;
024 import org.apache.commons.net.ftp.FTPReply;
025 import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
026 import org.apache.commons.vfs2.FileSystemException;
027 import org.apache.commons.vfs2.FileSystemOptions;
028 import org.apache.commons.vfs2.util.UserAuthenticatorUtils;
029
030 /**
031 * Create a FtpClient instance.
032 *
033 * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
034 */
035 public final class FtpClientFactory
036 {
037 private static final int BUFSZ = 40;
038
039 private FtpClientFactory()
040 {
041 }
042
043 /**
044 * Creates a new connection to the server.
045 *
046 * @param hostname The host name of the server.
047 * @param port The port to connect to.
048 * @param username The name of the user for authentication.
049 * @param password The user's password.
050 * @param workingDirectory The base directory.
051 * @param fileSystemOptions The FileSystemOptions.
052 * @return An FTPClient.
053 * @throws FileSystemException if an error occurs while connecting.
054 */
055 public static FTPClient createConnection(String hostname, int port, char[] username, char[] password,
056 String workingDirectory, FileSystemOptions fileSystemOptions)
057 throws FileSystemException
058 {
059 // Determine the username and password to use
060 if (username == null)
061 {
062 username = "anonymous".toCharArray();
063 }
064
065 if (password == null)
066 {
067 password = "anonymous".toCharArray();
068 }
069
070 try
071 {
072 final FTPClient client = new FTPClient();
073
074 configureClient(fileSystemOptions, client);
075
076 FTPFileEntryParserFactory myFactory =
077 FtpFileSystemConfigBuilder.getInstance().getEntryParserFactory(fileSystemOptions);
078 if (myFactory != null)
079 {
080 client.setParserFactory(myFactory);
081 }
082
083 try
084 {
085 client.connect(hostname, port);
086
087 int reply = client.getReplyCode();
088 if (!FTPReply.isPositiveCompletion(reply))
089 {
090 throw new FileSystemException("vfs.provider.ftp/connect-rejected.error", hostname);
091 }
092
093 // Login
094 if (!client.login(
095 UserAuthenticatorUtils.toString(username),
096 UserAuthenticatorUtils.toString(password)))
097 {
098 throw new FileSystemException("vfs.provider.ftp/login.error",
099 new Object[]{hostname, UserAuthenticatorUtils.toString(username)}, null);
100 }
101
102 // Set binary mode
103 if (!client.setFileType(FTP.BINARY_FILE_TYPE))
104 {
105 throw new FileSystemException("vfs.provider.ftp/set-binary.error", hostname);
106 }
107
108 // Set dataTimeout value
109 Integer dataTimeout = FtpFileSystemConfigBuilder.getInstance().getDataTimeout(fileSystemOptions);
110 if (dataTimeout != null)
111 {
112 client.setDataTimeout(dataTimeout.intValue());
113 }
114
115 Integer socketTimeout = FtpFileSystemConfigBuilder.getInstance().getSoTimeout(fileSystemOptions);
116 if (socketTimeout != null)
117 {
118 client.setSoTimeout(socketTimeout.intValue());
119 }
120
121 // Change to root by default
122 // All file operations a relative to the filesystem-root
123 // String root = getRoot().getName().getPath();
124
125 Boolean userDirIsRoot = FtpFileSystemConfigBuilder.getInstance().getUserDirIsRoot(fileSystemOptions);
126 if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue()))
127 {
128 if (!client.changeWorkingDirectory(workingDirectory))
129 {
130 throw new FileSystemException("vfs.provider.ftp/change-work-directory.error", workingDirectory);
131 }
132 }
133
134 Boolean passiveMode = FtpFileSystemConfigBuilder.getInstance().getPassiveMode(fileSystemOptions);
135 if (passiveMode != null && passiveMode.booleanValue())
136 {
137 client.enterLocalPassiveMode();
138 }
139
140 String controlEncoding = FtpFileSystemConfigBuilder.getInstance().getControlEncoding(fileSystemOptions);
141 if (controlEncoding != null)
142 {
143 client.setControlEncoding(controlEncoding);
144 }
145 }
146 catch (final IOException e)
147 {
148 if (client.isConnected())
149 {
150 client.disconnect();
151 }
152 throw e;
153 }
154
155 return client;
156 }
157 catch (final Exception exc)
158 {
159 throw new FileSystemException("vfs.provider.ftp/connect.error", new Object[]{hostname}, exc);
160 }
161 }
162
163 private static void configureClient(FileSystemOptions fileSystemOptions, FTPClient client)
164 {
165 String key = FtpFileSystemConfigBuilder.getInstance().getEntryParser(fileSystemOptions);
166 if (key != null)
167 {
168 FTPClientConfig config = new FTPClientConfig(key);
169
170 String serverLanguageCode =
171 FtpFileSystemConfigBuilder.getInstance().getServerLanguageCode(fileSystemOptions);
172 if (serverLanguageCode != null)
173 {
174 config.setServerLanguageCode(serverLanguageCode);
175 }
176 String defaultDateFormat =
177 FtpFileSystemConfigBuilder.getInstance().getDefaultDateFormat(fileSystemOptions);
178 if (defaultDateFormat != null)
179 {
180 config.setDefaultDateFormatStr(defaultDateFormat);
181 }
182 String recentDateFormat =
183 FtpFileSystemConfigBuilder.getInstance().getRecentDateFormat(fileSystemOptions);
184 if (recentDateFormat != null)
185 {
186 config.setRecentDateFormatStr(recentDateFormat);
187 }
188 String serverTimeZoneId =
189 FtpFileSystemConfigBuilder.getInstance().getServerTimeZoneId(fileSystemOptions);
190 if (serverTimeZoneId != null)
191 {
192 config.setServerTimeZoneId(serverTimeZoneId);
193 }
194 String[] shortMonthNames =
195 FtpFileSystemConfigBuilder.getInstance().getShortMonthNames(fileSystemOptions);
196 if (shortMonthNames != null)
197 {
198 StringBuilder shortMonthNamesStr = new StringBuilder(BUFSZ);
199 for (int i = 0; i < shortMonthNames.length; i++)
200 {
201 if (shortMonthNamesStr.length() > 0)
202 {
203 shortMonthNamesStr.append("|");
204 }
205 shortMonthNamesStr.append(shortMonthNames[i]);
206 }
207 config.setShortMonthNames(shortMonthNamesStr.toString());
208 }
209
210 client.configure(config);
211 }
212 }
213 }