org.apache.ftpserver.ConnectionManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ftpserver.ConnectionManagerImpl.java

Source

// $Id: ConnectionManagerImpl.java 306760 2005-10-06 11:42:47 +0530 (Thu, 06 Oct 2005) rana_b $
/*
 * Copyright 2004 The Apache Software Foundation
 *
 * 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.apache.ftpserver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ftpserver.ftplet.Configuration;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.interfaces.ConnectionManagerObserver;
import org.apache.ftpserver.interfaces.IConnection;
import org.apache.ftpserver.interfaces.IConnectionManager;
import org.apache.ftpserver.usermanager.BaseUser;

/**
 * Connection service to manage all the connections (request handlers).
 * 
 * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
 */
public class ConnectionManagerImpl implements IConnectionManager {

    private Log m_log;

    private ConnectionManagerObserver m_observer;
    private Timer m_timer;
    private Vector m_conList = new Vector();

    private int m_maxConnections;
    private int m_maxLogins;
    private boolean m_anonEnabled;
    private int m_maxAnonLogins;

    private int m_defaultIdleSec;
    private int m_pollIntervalSec;

    /**
     * Set the log factory.
     */
    public void setLogFactory(LogFactory factory) {
        m_log = factory.getInstance(getClass());
    }

    /**
     * Configure connection service
     */
    public void configure(Configuration config) throws FtpException {

        // get configuration parameters
        m_maxConnections = config.getInt("max-connection", 20);
        m_maxLogins = config.getInt("max-login", 10);
        m_anonEnabled = config.getBoolean("anonymous-login-enabled", true);
        m_maxAnonLogins = config.getInt("max-anonymous-login", 10);
        m_defaultIdleSec = config.getInt("default-idle-time", 60);
        m_pollIntervalSec = config.getInt("timeout-poll-inverval", 60);

        // set timer to remove inactive users and load data
        m_timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            public void run() {
                timerTask();
            }
        };
        m_timer.schedule(timerTask, 0, m_pollIntervalSec * 1000L);
    }

    /**
     * Set connection manager observer.
     */
    public void setObserver(ConnectionManagerObserver observer) {
        m_observer = observer;
    }

    /**
     * Get maximum number of connections.
     */
    public int getMaxConnections() {
        return m_maxConnections;
    }

    /**
     * Get maximum number of logins.
     */
    public int getMaxLogins() {
        return m_maxLogins;
    }

    /**
     * Is anonymous login enabled?
     */
    public boolean isAnonymousLoginEnabled() {
        return m_anonEnabled;
    }

    /**
     * Get maximum anonymous logins
     */
    public int getMaxAnonymousLogins() {
        return m_maxAnonLogins;
    }

    /**
     * Get all request handlers
     */
    public List getAllConnections() {
        List cons = m_conList;
        if (cons == null) {
            return new Vector();
        }
        return new Vector(cons);
    }

    /**
     * New connection has been established.
     */
    public void newConnection(IConnection connection) {

        // null connection - ignore
        if (connection == null) {
            return;
        }

        // disposed - ignore
        List cons = m_conList;
        if (cons == null) {
            return;
        }
        cons.add(connection);

        // notify observer about a new connection
        ConnectionManagerObserver observer = m_observer;
        if (observer != null) {
            observer.openedConnection(connection);
            observer.updatedConnection(connection);
        }

        // set default idle time
        BaseUser user = (BaseUser) connection.getRequest().getUser();
        user.setMaxIdleTime(m_defaultIdleSec);

        // now start a new thread to serve this connection
        new Thread(connection).start();
    }

    /**
     * Connection has been updated - notify listeners
     */
    public void updateConnection(IConnection connection) {

        // null connection - ignore
        if (connection == null) {
            return;
        }

        // notify observer
        ConnectionManagerObserver observer = m_observer;
        if (observer != null) {
            observer.updatedConnection(connection);
        }
    }

    /**
     * Close connection.
     */
    public void closeConnection(IConnection connection) {

        // null connection - ignore
        if (connection == null) {
            return;
        }

        // close socket
        List cons = m_conList;
        if (cons != null) {
            cons.remove(connection);
        }
        connection.close();

        // notify observer
        ConnectionManagerObserver observer = m_observer;
        if (observer != null) {
            observer.closedConnection(connection);
        }
    }

    /**
     * Close all connections.
     */
    public void closeAllConnections() {
        List allCons = getAllConnections();
        for (Iterator it = allCons.iterator(); it.hasNext();) {
            IConnection connection = (IConnection) it.next();
            closeConnection(connection);
        }
        allCons.clear();
    }

    /**
     * Timer thread will call this method periodically to
     * close inactice connections.
     */
    public void timerTask() {

        // get all connections
        ArrayList inactiveCons = new ArrayList();
        long currTime = System.currentTimeMillis();
        Vector conList = m_conList;
        if (conList == null) {
            return;
        }

        // get inactive client connection list 
        synchronized (conList) {
            long idleTimeMillis = m_defaultIdleSec * 1000L;
            for (int i = conList.size(); --i >= 0;) {
                IConnection con = (IConnection) conList.get(i);
                if (con == null) {
                    continue;
                }

                // idle client connection
                FtpRequestImpl request = (FtpRequestImpl) con.getRequest();
                if (request == null) {
                    continue;
                }
                if (request.isTimeout(currTime)) {
                    inactiveCons.add(con);
                }

                // idle data connection
                FtpDataConnection dataCon = request.getFtpDataConnection();
                if (dataCon == null) {
                    continue;
                }
                synchronized (dataCon) {

                    // data transfer is going on - no need to close
                    if (dataCon.isActive()) {
                        continue;
                    }

                    // data connection is already closed 
                    long requestTime = dataCon.getRequestTime();
                    if (requestTime == 0L) {
                        continue;
                    }

                    // idle data connectin timeout - close it 
                    if ((currTime - requestTime) > idleTimeMillis) {
                        m_log.info("Removing idle data connection for " + request.getUser());
                        dataCon.closeDataSocket();
                    }
                }
            }
        }

        // close idle client connections
        for (Iterator conIt = inactiveCons.iterator(); conIt.hasNext();) {
            IConnection connection = (IConnection) conIt.next();
            if (connection == null) {
                continue;
            }

            FtpRequest request = connection.getRequest();
            if (request == null) {
                continue;
            }

            m_log.info("Removing idle user " + request.getUser());
            closeConnection(connection);
        }
    }

    /**
     * Dispose connections
     */
    public void dispose() {

        // stop timer
        Timer timer = m_timer;
        if (timer != null) {
            timer.cancel();
            m_timer = null;
        }

        // close all connections
        List cons = m_conList;
        if (cons != null) {
            closeAllConnections();
            m_conList = null;
        }
    }
}