0N/A/*
2362N/A * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Aimport java.net.*;
0N/Aimport java.io.*;
0N/Aimport java.util.ArrayList;
0N/A
0N/A/**
0N/A * This class implements a simple FTP server that can handle multiple
0N/A * connections concurrently. This is mostly meant as a test environment.
0N/A * You have to provide 2 handlers for it to be effective, one to simulate
0N/A * (or access) a filesystem and one to deal with authentication.
0N/A * See {@link FtpFileSystemHandler} and {@link FtpAuthHandler}.
0N/A *
0N/A * Since it is a subclass of Thread, you have to call <code>start()</code>
0N/A * To get it running.
0N/A *
0N/A * Usage example:<p>
0N/A *
0N/A * <code>
0N/A * FtpServer server = new FtpServer(0);
0N/A * int port = server.getLocalPort();
0N/A * server.setFileSystemHandler(myFSHandler);
0N/A * server.setAuthHandler(myAuthHandler);
0N/A * server.start();
0N/A * </code>
0N/A *
0N/A */
0N/A
0N/Apublic class FtpServer extends Thread {
0N/A private ServerSocket listener = null;
0N/A private FtpFileSystemHandler fsh = null;
0N/A private FtpAuthHandler auth = null;
0N/A private boolean done = false;
0N/A private ArrayList<FtpCommandHandler> clients = new ArrayList<FtpCommandHandler>();
0N/A
0N/A /**
0N/A * Creates an instance of an FTP server which will listen for incoming
0N/A * connections on the specified port. If the port is set to 0, it will
0N/A * automatically select an available ephemeral port.
0N/A */
0N/A public FtpServer(int port) throws IOException {
0N/A listener = new ServerSocket(port);
0N/A }
0N/A
0N/A /**
0N/A * Creates an instance of an FTP server that will listen on the default
0N/A * FTP port, usually 21.
0N/A */
0N/A public FtpServer() throws IOException {
0N/A this(21);
0N/A }
0N/A
0N/A public void setFileSystemHandler(FtpFileSystemHandler f) {
0N/A fsh = f;
0N/A }
0N/A
0N/A public void setAuthHandler(FtpAuthHandler a) {
0N/A auth = a;
0N/A }
0N/A
0N/A public void terminate() {
0N/A done = true;
0N/A interrupt();
0N/A }
0N/A
0N/A public void killClients() {
0N/A synchronized (clients) {
0N/A int c = clients.size();
0N/A while (c > 0) {
0N/A c--;
0N/A FtpCommandHandler cl = clients.get(c);
0N/A cl.terminate();
0N/A cl.interrupt();
0N/A }
0N/A }
0N/A }
0N/A
0N/A public int getLocalPort() {
0N/A return listener.getLocalPort();
0N/A }
0N/A
0N/A void addClient(Socket client) {
0N/A FtpCommandHandler h = new FtpCommandHandler(client, this);
0N/A h.setHandlers(fsh, auth);
0N/A synchronized (clients) {
0N/A clients.add(h);
0N/A }
0N/A h.start();
0N/A }
0N/A
0N/A void removeClient(FtpCommandHandler cl) {
0N/A synchronized (clients) {
0N/A clients.remove(cl);
0N/A }
0N/A }
0N/A
0N/A public int activeClientsCount() {
0N/A synchronized (clients) {
0N/A return clients.size();
0N/A }
0N/A }
0N/A
0N/A public void run() {
0N/A Socket client;
0N/A
0N/A try {
0N/A while (!done) {
0N/A client = listener.accept();
0N/A addClient(client);
0N/A }
0N/A listener.close();
0N/A } catch (IOException e) {
0N/A
0N/A }
0N/A }
0N/A}