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を返すようにはできない‥!?