2008年7月3日木曜日

jar ファイルの場所を見つける方法

自作の jar ファイルに含まれたクラスを使うとき、その jar のパスやディレクトリを知りたいと思ったことありませんか?

かなり昔に作った自作ライブラリの一部ですが、最近、思い出したように使ってみて便利だったので紹介します。
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.ProtectionDomain;
import java.security.CodeSource;

public class ClassUtils {

public static URL findClassLocation(Class c)
throws SecurityException {
Package p = c.getPackage();
String className;
if (p != null) {
className = c.getName().substring(p.getName().length() + 1);
} else {
className = c.getName();
}
URL location = c.getResource(className + ".class");
if (location == null) {
// NOTE: 昔 Tomcat の WEB-INF/lib とかの jar を探すときはこの
// 処理に入ったのだが。。。今は不要かも。
ProtectionDomain domain = c.getProtectionDomain();
CodeSource source = domain.getCodeSource();
if (source != null) {
location = source.getLocation();
}
}
return location;
}

private static File findBaseDirectory(URL classLocation)
throws IOException {
if (classLocation == null) {
return null;
}
String file = classLocation.getFile();
if (classLocation.getProtocol().equals("jar")) {
int i = file.lastIndexOf('!');
if (i != -1) {
file = file.substring(0, i);
}
return findBaseDirectory(new URL(file));
}
File dir = new File(URLDecoder.decode(file,
System.getProperty("file.encoding")));
if (!dir.isDirectory()) {
dir = dir.getParentFile();
}
return dir;
}

public static File findBaseDirectory(Class c)
throws SecurityException, IOException {
return findBaseDirectory(findClassLocation(c));
}

public static void main(String[] args) throws Exception {
System.out.println(findBaseDirectory(java.lang.String.class));
}
}


これがあれば xxx.home などのシステムプロパティ渡さずに済むことが多々あると思います。
sen などもこれに対応してくれればなぁ。。。