commons-VFS on webapp

僕にとってのcommons-VFSの使い道はおそらく設定ファイルの読み込みなんですが、Webアプリの場合、ServletContext上に設定ファイルを置いている場合(/WEB-INF/confとか)もありえます。

でもcommons-VFSはそんなことには対応してません。そこでいろいろ試したところ、ちょろっとコードを書くと、以下のような記述からファイルをゲットできることが判明しました。

  • webcontext://vfsSample.jsp
  • webcontext://WEB-INF/conf/setting.properties
  • jar:webcontext://WEB-INF/lib/log4j-1.2.8.jar!/org/apache/log4j/xml/log4j.dtd


実際にcommons-VFSに触るVfsWebContext.javaはこんな感じ。

/*
 * Created on 2005/08/04
 */
package org.asyrinx.brownie.vfs.sample;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.servlet.ServletContext;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.apache.commons.vfs.provider.temp.TemporaryFileProvider;

public class VfsWebContext {

    public VfsWebContext(ServletContext context) throws FileSystemException {
        super();
        this.fileSystemManager = VFS.getManager();
        if (this.fileSystemManager instanceof DefaultFileSystemManager) {
            final DefaultFileSystemManager defaultFileSystemManager = (DefaultFileSystemManager) this.fileSystemManager;
            if (defaultFileSystemManager.hasProvider("webcontext"))
                return;
            final String contextRoot = context.getRealPath(".");
            defaultFileSystemManager.addProvider("webcontext",
                    new TemporaryFileProvider(new File(contextRoot)));
        }
    }

    private final FileSystemManager fileSystemManager;

    public String getContent(String vfsPath) throws IOException {
        if (vfsPath == null)
            return null;
        final FileObject fileObject = this.fileSystemManager
                .resolveFile(vfsPath);
        return read(fileObject.getContent().getInputStream());
    }

    private String read(InputStream source) throws IOException {
        final Reader reader = new BufferedReader(new InputStreamReader(source));
        final StringBuffer dest = new StringBuffer();
        int c = reader.read();
        while (c > -1) {
            dest.append((char) c);
            c = reader.read();
        }
        return dest.toString();
    }

}

VfsWebContextを使うvfsSample.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ page contentType="text/html; charset=UTF-8" import="org.asyrinx.brownie.vfs.sample.*" %>
<%!
	VfsWebContext vfsWebContext = null;
%>
<%
	if (vfsWebContext == null) {
		vfsWebContext = new VfsWebContext(application);
	}
%>
<html>
	<head>
		<title>commons-VFS on web context</title>
	</head>
	<body>
		<form name="f">
			VFS Path: <input type="text" name="vfsPath" value="<%= request.getParameter("vfsPath")%>" size="50"/>
			<input type="submit" value="getContent"/>
		</form>
		<textarea id="result" cols="120" rows="20"><%= vfsWebContext.getContent( request.getParameter("vfsPath") ) %></textarea>
	</body>
</html>


JSPを動かしてみたら、VSF PATHのところに前述のVFSのパスを入力してgetContentでサブミットすると、そのファイルの中身が表示されます。

最初コンテキストを理解するProviderを作らなきゃだめかと思ってたんですが、TemporaryFileProviderで全然用が足りちゃうのね。結構簡単。調べればもっと面白いかも。