org.springframework.integration.ftp.session.AbstractFtpSessionFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.ftp.session.AbstractFtpSessionFactory.java

Source

/*
 * Copyright 2002-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.integration.ftp.session;

import java.io.IOException;
import java.net.SocketException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import org.springframework.integration.MessagingException;
import org.springframework.integration.file.remote.session.Session;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.util.Assert;

/**
 * Base class for FTP SessionFactory implementations.
 *
 * @author Iwein Fuld
 * @author Mark Fisher
 * @author Oleg Zhurakousky
 * @since 2.0
 */
public abstract class AbstractFtpSessionFactory<T extends FTPClient> implements SessionFactory<FTPFile> {

    public static final String DEFAULT_REMOTE_WORKING_DIRECTORY = "/";

    private final Log logger = LogFactory.getLog(this.getClass());

    protected FTPClientConfig config;

    protected String username;

    protected String host;

    protected String password;

    protected int port = FTP.DEFAULT_PORT;

    protected int bufferSize = 2048; //see https://issues.apache.org/jira/browse/NET-207

    protected int clientMode = FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE;

    protected int fileType = FTP.BINARY_FILE_TYPE;

    protected String controlEncoding = FTP.DEFAULT_CONTROL_ENCODING;

    /**
     * File types defined by {@link org.apache.commons.net.ftp.FTP} constants:
     * <ul>
     * <li>{@link org.apache.commons.net.ftp.FTP#ASCII_FILE_TYPE}</li>
     * <li>{@link org.apache.commons.net.ftp.FTP#EBCDIC_FILE_TYPE}</li>
     * <li>{@link org.apache.commons.net.ftp.FTP#BINARY_FILE_TYPE} (DEFAULT)</li>
     * <li>{@link org.apache.commons.net.ftp.FTP#LOCAL_FILE_TYPE}</li>
     * </ul>
     * @param fileType
     */
    public void setFileType(int fileType) {
        this.fileType = fileType;
    }

    public void setControlEncoding(String controlEncoding) {
        Assert.hasText(controlEncoding);
        this.controlEncoding = controlEncoding;
    }

    public void setConfig(FTPClientConfig config) {
        Assert.notNull(config);
        this.config = config;
    }

    public void setBufferSize(int bufferSize) {
        this.bufferSize = bufferSize;
    }

    public void setHost(String host) {
        Assert.hasText(host);
        this.host = host;
    }

    public void setPort(int port) {
        Assert.isTrue(port > 0, "Port number should be > 0");
        this.port = port;
    }

    public void setUsername(String user) {
        Assert.hasText(user, "'user' should be a nonempty string");
        this.username = user;
    }

    public void setPassword(String pass) {
        Assert.notNull(pass, "password should not be null");
        this.password = pass;
    }

    /**
     * ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0 <br>
     * A constant indicating the FTP session is expecting all transfers
     * to occur between the client (local) and server and that the server
     * should connect to the client's data port to initiate a data transfer.
     * This is the default data connection mode when and FTPClient instance
     * is created.
     * PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2 <br>
     * A constant indicating the FTP session is expecting all transfers
     * to occur between the client (local) and server and that the server
     * is in passive mode, requiring the client to connect to the
     * server's data port to initiate a transfer.
     */
    public void setClientMode(int clientMode) {
        Assert.isTrue(
                clientMode == FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE
                        || clientMode == FTPClient.PASSIVE_LOCAL_DATA_CONNECTION_MODE,
                "Only local modes are supported. Was: " + clientMode);
        this.clientMode = clientMode;
    }

    public Session<FTPFile> getSession() {
        try {
            return new FtpSession(this.createClient());
        } catch (Exception e) {
            throw new IllegalStateException("failed to create FTPClient", e);
        }
    }

    private T createClient() throws SocketException, IOException {
        final T client = this.createClientInstance();
        Assert.notNull(client, "client must not be null");
        client.configure(this.config);
        Assert.hasText(this.username, "username is required");

        this.postProcessClientBeforeConnect(client);

        // Connect
        client.connect(this.host, this.port);

        if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
            throw new MessagingException(
                    "Connecting to server [" + host + ":" + port + "] failed. Please check the connection.");
        }
        logger.debug("Connected to server [" + host + ":" + port + "]");

        // Login
        if (!client.login(username, password)) {
            throw new IllegalStateException(
                    "Login failed. The respponse from the server is: " + client.getReplyString());
        }

        this.postProcessClientAfterConnect(client);

        this.updateClientMode(client);
        client.setFileType(fileType);
        client.setBufferSize(bufferSize);
        client.setControlEncoding(controlEncoding);
        return client;
    }

    /**
     * Sets the mode of the connection. Only local modes are supported.
     */
    private void updateClientMode(FTPClient client) {
        switch (this.clientMode) {
        case FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE:
            client.enterLocalActiveMode();
            break;
        case FTPClient.PASSIVE_LOCAL_DATA_CONNECTION_MODE:
            client.enterLocalPassiveMode();
            break;
        default:
            break;
        }
    }

    protected abstract T createClientInstance();

    /**
     * Will handle additional initialization after client.connect() method was invoked, 
     * but before any action on the client has been taken 
     */
    protected void postProcessClientAfterConnect(T t) throws IOException {
        // NOOP
    }

    /**
     * Will handle additional initialization before client.connect() method was invoked. 
     */
    protected void postProcessClientBeforeConnect(T client) throws IOException {
        // NOOP
    }

}