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