HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

Class.getResourceで返されるURLの謎

WebSphere Application Server v6.1.0.21 で、以下のJSPを実行してみる。

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page errorPage="jspError.jsp" %>
<%@ page import="hoge.foo.bar.my_app.MyClass" %>
<%@ page import="java.net.*" %>
<%@ page import="java.io.*" %>

<pre>
<%
try {
    Class[] cls = {
        MyClass.class,    // Webアプリに含まれるクラス
        Object.class,     // 基本クラス、またはWAS本体に含まれるクラス
    };
    String[] paths = {
        "version/profile.version",    // WASを起動したJava VMのクラスパスに指定されているフォルダに存在するファイル
        "my-app-config.xml",          // Webアプリの WEB-INF/classes の下にしか存在しないファイル
    };
    for (int i = 0; i < cls.length; ++i) {
        for (int j = 0; j < paths.length; ++j) {
            URL url = cls[i].getResource("/" + paths[j]);
            out.println("[" + i + "-" + j + "][" + cls[i] + "][" + "/" + paths[j] + "]");
            out.println("    " + url);
        }
    }
} catch (Exception e) {
    e.printStackTrace(new PrintWriter(out));
}
%>
</pre>

すると、思いがけない結果が表示される。

[0-0][class hoge.foo.bar.my_app.MyClass][/version/profile.version]
    file:/D:/Program%20Files/ibm/WebSphere61/AppServer/profiles/AppSrv01/properties/version/profile.version
[0-1][class hoge.foo.bar.my_app.MyClass][/my-app-config.xml]
    file:/D:/Program Files/ibm/WebSphere61/AppServer/profiles/AppSrv01/installedApps/hhelibexNode01Cell/MYAPP EAR.ear/myapp.war/WEB-INF/classes/my-app-config.xml
[1-0][class java.lang.Object][/version/profile.version]
    file:/D:/Program%20Files/ibm/WebSphere61/AppServer/profiles/AppSrv01/properties/version/profile.version
[1-1][class java.lang.Object][/my-app-config.xml]
    null

"0-0"、"1-0"のように、WASを実行しているJava VMのクラスパスに含まれるリソースのURLは、空白(U+0020)がURLエンコードされている。
一方、("1-1"がnullなのは当たり前として、)"0-1"のケースでは、空白(U+0020)はURLエンコードされていない。このURLオブジェクトのtoURI()メソッドを呼ぶと、不正な文字が含まれていると怒られてしまう。
調べてみると、Java VMのカスタムプロパティを設定することで、どちらのケースともにURLエンコードされるように動作させることができるようだ。
IBM - PK64379; 6.1.0.15: ClassLoader.getResource encodes spaces in URLs

プロパティ名:com.ibm.ws.classloader.encodeResourceURLs
値:true

とりあえず、これで目的の動作をするようになるので半ばどうでもいいのだが、上記カスタムプロパティの値をfalseにしても、"0-0"、"1-0"のように、WASを実行しているJava VMのクラスパスに含まれるリソースのURLは、空白(U+0020)がURLエンコードされたものが返される(カスタムプロパティを追加しない場合と変わらない)。すべてにおいてURLエンコードされていないURLを返すようにはできない‥!?