見出し画像

Apache Commons VFS のすすめ (2)

最初に

前回は、Commons VFS の基本的な使用方法を説明しました。
今回は、そこから更に一歩進んで、Commons VFS を使用する際に知っておいた方が良いことを説明します。

一歩踏み込むために

先に Commons VFS の詳細について説明します。
この詳細を押さえておくと、後の説明がわかりやすくなると思います。

構造

Commons VFS は主に 4 つのクラスが存在します。
Commons VFS の機能を管理する FileSystemManager、個々のファイルシステムを管理する FileProvider、ファイルシステムの接続情報などのコンテキスト毎に作成される FileSystem、ファイルを表す FileObject です。

ただし、FileProvider は独自のファイルシステムを提供するプロバイダーの実装者が意識するもので、FileSystemManager の内部で使用されるに留まっており、あまり表に出てきません。

これらのクラスは以下の様な関係になっています。

クラスの関係図

オブジェクトキャッシュ

Commons VFS はファイルにアクセスするとき、URL を用いてアクセスします。
このとき、URL スキーマ毎に実装された FileProvider を FileSystemManager が選択して、FileProvider が FileSystem をキャッシュして返しています。FileSystem は FileObject のインスタンスをキャッシュして管理しています。

このように各クラスがオブジェクトをキャッシュしているため、基本的には、同じ URL を指定して FileObject を取得した場合には、同じ FileSystem に管理されている FileObject が返ります。

FileObject file1 = manager.resolveFile("ftp://example.com/commons/vfs/");
FileObject file2 = manager.resolveFile("ftp://example.com/commons/vfs/");
// URI が同じなので FileObject は同じ
if (file1 == file2) {
}

オプションを指定する。

FTP などに接続するとき、ユーザ名やパスワードを指定する必要があるときには、FileSystemOptions を使用してオプションを指定することが出来ます。

オプションの設定の仕方は接続先のファイルシステムによって異なりますが、基本的には、***SystemConfigBuilder という名前の設定ビルダーを使用して設定します。

FileSystemOptions options = new FileSystemOptions();

// FTP の認証設定には DefaultFileSystemConfigBuilder を使用する。
// FTP の場合、domain は使用されないので未指定で良い。
UserAuthenticator authenticator = new StaticUserAuthenticator(null, "userName", "password");
DefaultFileSystemConfigBuilder.getInstance()
  .setUserAuthenticator(options, authenticator);

FtpFileSystemConfigBuilder configBuilder = FtpFileSystemConfigBuilder.getInstance();

// コネクションタイムアウトを 20 秒にする。
configBuilder.setConnectTimeout(options, Duration.ofSeconds(20));
// データタイムアウトを 30 秒にする。
configBuilder.setDataTimeout(options, Duration.ofSeconds(30));

FileObject file = manager.resolveFile("ftp://example.com/", options);

URL とオプションを受け取った FileProvider は違うオプションが指定された場合、別の FileSystem で管理するように振り分けています。

このようにして取得した FileObject は指定したオプションが反映された FileSystem の管理下にある FileObject になります。

接続単位を意識する。

オプションを指定して取得した FileObject はオプションを指定せずに取得する FileObject とは基本的に別接続となり、別の FileSystem の管理下となります。
オプションを指定すると、オプションに従った FileSystem が作成され、この FileSystem が接続単位となるため、同じオプションを指定したときのみ同じ FileObject が返されることになります。

FileSystemOptions options = new FileSystemOptions();

  :

FileObject file1 = manager.resolveFile("ftp://example.com/", options);

FileObject file2 = manager.resolveFile("ftp://example.com/");
// インスタンスが異なる。
if (file1 != file2) {
}
// FileSystem も異なる。
if (file1.getFileSystem() != file2.getFileSystem()) {
}

// 同じオプションを指定した場合には同じインスタンスが返る。
FileObject file3 = manager.resolveFile("ftp://example.com/", options);
// インスタンスが同じ
if (file1 == file3) {
}

// 同じオプションを指定した場合は、FileSystem が同じになる。
FileObject file4 = manager.resolveFile("ftp://example.com/commons/vfs", options);
// パスが違うので、インスタンスは異なる。
if (file1 != file2) {
}
// FileSystem が同じ
if (file1.getFileSystem() == file4.getFileSystem()) {
}

このようにオプション毎に違う FileSystem で管理されるため、既存の File クラスと同じようにパスだけで FileObject を取得しようとすると、違う接続の FileObject 取得されて、見た目は同じ URL の FileObject ではあるが、equals 判定で失敗したりします。

FileObject を持ち回る。

Commons VFS の場合、URL スキーマと FileSystemOptions をペアで管理することが望ましいです。

しかし、この 2 つを常に管理するのは、手間となります。

そこで、FileSystemManager から取得するのは、最初のルートパスなどの FileObject を取得するときだけにして、取得した FileObject を持ち回るようにします。

以降は、FileSystemManager を用いず、持ち回った FileObject からサブパスの FileObject を取得するなどするなどして、FileObject から FileObject を取得することを意識することで、同じ接続が使用されるようになります。

FileSystemOptions options = new FileSystemOptions();

  :

// ルートを取得
FileObject root = manager.resolveFile("ftp://example.com/", options);

// 取得した FileObject からサブパスのファイルを取得する。
FileObject subFile = root.resolveFile("commons/vfs");
for (FileObject child : subFile.getChildren()) {
  :
}

まとめ

Commons VFS では FileObject を持ち回って、そこからサブファイルなどを取得した方が良いです。

Java の File クラスの場合、File クラスからパスを取得して、再度、パスから File クラスを取得すると言ったことをよく行いますが、Commons VFS では接続先を念頭に入れなければいけないため、おすすめ出来ません。

この辺は、File クラスとはまた違った使い方となるので注意が必要となります。

続きは・・・

今回は、Commons VFS の構造や FileObject の扱い方に踏み込んだ説明をしました。

次回は、Commons VFS のちょっと面白い機能について紹介します。
お楽しみに。

#プログラミング #Java #Apache #エンジニア#ITエンジニア#開発#ウイングアーク#ウイングアーク1st#テックブログ#エンジニア転職#エンジニア採用

この記事が気に入ったらサポートをしてみませんか?