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.ftps;
018
019import java.io.IOException;
020
021import javax.net.ssl.KeyManager;
022import javax.net.ssl.SSLException;
023import javax.net.ssl.TrustManager;
024
025import org.apache.commons.net.ftp.FTPSClient;
026import org.apache.commons.vfs2.FileSystemException;
027import org.apache.commons.vfs2.FileSystemOptions;
028import org.apache.commons.vfs2.provider.ftp.FtpClientFactory;
029
030/**
031 * Create FTPSClient instances.
032 *
033 * @since 2.0
034 */
035public final class FtpsClientFactory {
036    private FtpsClientFactory() {
037    }
038
039    /**
040     * Creates a new connection to the server.
041     *
042     * @param hostname The host name.
043     * @param port The port.
044     * @param username The user name for authentication.
045     * @param password The user's password.
046     * @param workingDirectory The directory to use.
047     * @param fileSystemOptions The FileSystemOptions.
048     * @return The FTPSClient.
049     * @throws FileSystemException if an error occurs.
050     */
051    public static FTPSClient createConnection(final String hostname, final int port, final char[] username,
052            final char[] password, final String workingDirectory, final FileSystemOptions fileSystemOptions)
053            throws FileSystemException {
054        final FtpsConnectionFactory factory = new FtpsConnectionFactory(FtpsFileSystemConfigBuilder.getInstance());
055        return factory.createConnection(hostname, port, username, password, workingDirectory, fileSystemOptions);
056    }
057
058    /** Connection Factory for FTPS case. */
059    private static final class FtpsConnectionFactory
060            extends FtpClientFactory.ConnectionFactory<FTPSClient, FtpsFileSystemConfigBuilder> {
061
062        private FtpsConnectionFactory(final FtpsFileSystemConfigBuilder builder) {
063            super(builder);
064        }
065
066        @Override
067        protected FTPSClient createClient(final FileSystemOptions fileSystemOptions) throws FileSystemException {
068            final FTPSClient client;
069            if (builder.getFtpsMode(fileSystemOptions) == FtpsMode.IMPLICIT) {
070                client = new FTPSClient(true);
071            } else {
072                client = new FTPSClient();
073            }
074
075            final TrustManager trustManager = builder.getTrustManager(fileSystemOptions);
076            if (trustManager != null) {
077                client.setTrustManager(trustManager);
078            }
079
080            final KeyManager keyManager = builder.getKeyManager(fileSystemOptions);
081            if (keyManager != null) {
082                client.setKeyManager(keyManager);
083            }
084            return client;
085        }
086
087        @Override
088        protected void setupOpenConnection(final FTPSClient client, final FileSystemOptions fileSystemOptions)
089                throws IOException {
090            final FtpsDataChannelProtectionLevel level = builder.getDataChannelProtectionLevel(fileSystemOptions);
091            if (level != null) {
092                // '0' means streaming, that's what we do!
093                try {
094                    client.execPBSZ(0);
095                    client.execPROT(level.name());
096                } catch (final SSLException e) {
097                    throw new FileSystemException("vfs.provider.ftps/data-channel.level", e, level.toString());
098                }
099            }
100        }
101    }
102}