Apache FtpServerとは

Apache FtpServer(以下、FtpServer)は100% Javaで書かれたオープンソースのFTPサーバである。Javaが動作する環境ならばどこでも実行できる上、UNIX/Linux環境のデーモンやWindowsサービスとしてバックグラウンドで動作させることが可能。またAPIを介してJavaプログラムから各種機能を呼び出すことが可能なため、アプリケーション内部に組み込んで利用することもできる。その他、OSGiバンドルとしてSpringベースのアプリケーションに組み込むこともできるようになっている。したがってJavaアプリケーションでリソースのダウンロードやアップロードをサポートする場合に便利なツールである。

ネットワーク部分の実装はApacheプロジェクトによるネットワークアプリケーションフレームワーク「Apache MINA」をベースにしている。したがってパフォーマンスとスケーラビリティに関しては申し分ないレベルだ。

それに加えて、FtpServerでは「Ftplet」と呼ばれるFTPサーバの動作を独自に拡張する仕組みが提供される。FtpletはFTPコンテナによって通知されるFTPイベントを処理するための軽量なオブジェクトであり、開発者はFtplet APIによって独自のFtpletを作成することができる。そしてFtpServer自身がFTPコンテナとしての機能を持つため、自前のFtpletをこれにデプロイしておくことで、ファイルのアップロードやダウンロードの要求に対して何らかの処理を行うようにカスタマイズすることができるというわけだ。

JavaプログラムからFtpServerを起動する

FtpServerはこのページよりダウンロードすることができる。本稿は最新版であるバージョン1.0.0を、Windows環境で利用するとして話を進める。ダウンロードしたファイルを適当なフォルダに展開すると、apache-ftpserver-1.0.0というフォルダ(以後、これを[FTP_HOME]と表記する)内にbin、common、docs、javadocs、resの各フォルダが格納されている。

FtpServerを通常のFTPサーバとして使用する場合には、bin以下にあるftpd.bat(シェル環境ではftpd.sh)を実行すればよい。設定を変更する場合には、[FTP_HOME]\res\confフォルダにあるftpd-typical.xmlおよびftpd-full.xmlを参考にして設定ファイルを記述し、ftpd.batの実行時引数にファイル名を指定すればよい。

今回はFtpServerをJavaプログラム内から実行する方法について解説する。FtpServerを利用するために必要なライブラリは[FTP_HOME]\common\libフォルダに格納されている。基本的な機能を使うためには最低限以下のJARファイルをクラスパスに含めておく必要がある。ただし、slf4j-log4j12-1.5.2.jarとlog4j-.1.2.14.jarについては、SLF4Jに含まれるslf4j-simple-xxx.jarのような他のSLF4J実装に置き換えてもよい。

  • ftpserver-core-1.0.0.jar
  • ftplet-api-1.0.0.jar
  • mina-core-2.0.0-M4.jar
  • slf4j-api-1.5.2.jar
  • slf4j-log4j12-1.5.2.jar
  • log4j-.1.2.14.jar

FtpServerを実行する基本的なコードは以下のようになる。

リスト1

package jp.co.mycom.toolde;

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.listener.ListenerFactory;

public class FtpServerSample {
    public FtpServerSample() {
        try {
            FtpServerFactory serverFactory = new FtpServerFactory();
            ListenerFactory listenerFactory = new ListenerFactory();
            // ポート番号を設定
            listenerFactory.setPort(2221);
            // リスナをServerFactoryに追加
            serverFactory.addListener("default", listenerFactory.createListener());

            // ユーザ認証設定
            // (後述)

            // FTPサーバをスタート
            FtpServer server = serverFactory.createServer();
            server.start();
        } catch (FtpException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        FtpServerSample doit = new FtpServerSample();
    }
}

基本的な手順は次のような感じだ。

  1. FtpServerFactoryを生成する
  2. ListenerFactoryを生成し、リスナの設定を変更する
  3. リスナオブジェクトを生成してFtpServerFactoryに追加
  4. FtpServerFactoryからFtpServerを生成
  5. FtpServerのstart()メソッドでFTPサーバをスタート

ListenerFactoryを使用することでポート番号やサーバ名、タイムアウト時間、ブロックするアドレスなどの設定を行える。ただし、デフォルト設定のままで利用する場合にはこの部分の処理は省略できる。

FTPサーバ自体はこれで起動できるが、このままではユーザの設定を行っていないため外部からアクセスすることができない。プログラム内でユーザを設定するには次のような処理を加えればよい。必要なクラスのimport宣言を忘れないこと。

リスト2

            // ユーザ認証設定
            PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
            userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
            UserManager userManager = userManagerFactory.createUserManager();

            BaseUser user = new BaseUser();
            user.setName("ユーザ名");
            user.setPassword("パスワード");
            user.setHomeDirectory("ホームディレクトリのパス");
            userManager.save(user);

            serverFactory.setUserManager(userManager);

ユーザ情報の管理はUserManagerオブジェクトによって行う。このオブジェクトはUserManagerFactoryオブジェクトより生成できる。UserManagerFactoryには、プロパティ形式でユーザ情報を管理するPropertiesUserManagerFactoryクラスと、データベースで管理するDbUserManagerFactoryクラスの2種類の実装が用意されている。この例ではPropertiesUserManagerFactoryクラスを利用している。パスワード認証を行う場合には、setPasswordEncryptor()メソッドにPasswordEncryptorインスタンスを渡せばよい。FtpServerではあらかじめ3種類の認証方法が用意されている。

各ユーザ情報はそれぞれUserオブジェクトに格納し、UserManagerのsave()メソッドで登録する。Userインタフェースを独自に実装してもいいが、FtpServerにはorg.apache.ftpserver.usermanager.impl.BaseUserという実装クラスが含まれているのでこれを利用してもよい。

最後にsetUserManager()メソッドを使ってUserManagerをServerFactoryに設定すればユーザの設定は完了だ。

なお、ユーザ情報はプロパティファイルから読み込ませることもできる。その場合、[FTP_HOME]\res\confフォルダにあるuser.propertiesを参考にしてプロパティファイルを作成し、次のようにしてUserManagerFactoryに設定する。

リスト3

            userManagerFactory.setFile(new File("プロパティファイル名"));

作成したプログラムをコンパイル/実行すれば、任意のFTPクライアントからアクセスしてファイルのアップロードやダウンロードができるはずだ。次回はFtpletの使い方を紹介する。