JarClassLoader
Jarファイル用のクラスローダを作りました。
例のDBを縦に表示するヤツの中で使っています。
あれはJDBCのパスを実行時に設定できます。
つまり、クラスパスを設定していないところからクラスを読み込んでます。
通常はこんな感じで接続しますよね。
Class.forName(driverName); Connection conn = Connection.getConnection(url, user, password);
独自クラスローダを使う場合は以下のようになります。
String[] jarnames = ... // 複数のJarファイルが設定可能 JarClassLoader jarClassLoader = new JarClassLoader(); jarClassLoader.setJarFilenames(jarnames); Class driverClass = Class.forName(driverName, true, jarClassLoader); Driver driver = (Driver) driverClass.newInstance(); DriverManager.registerDriver(driver); Properties prop = new Properties(); prop.put("user", user); prop.put("password", pass); Connection conn = driver.connect(url, prop);
以下がソースです。よければどうぞ。
import java.io.BufferedInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class JarClassLoader extends ClassLoader { ArrayList jarnames; /** * @param paths 個々のパスには末尾にセパレータをつけないこと。 */ public JarClassLoader() { this.jarnames = new ArrayList(); } public void setJarFilenames(ArrayList jarnames) { this.jarnames = jarnames; } public Class findClass(String name) { byte b = loadClassData(name); if (b == null) return null; return defineClass(name, b, 0, b.length); } /** * 指定されたパスを使って、サーバのクラスを取得する. */ private byte loadClassData(String name) { for (int i=0; i<jarnames.size(); i++) { String jarname = (String) jarnames.get(i); byte bytes = loadClassData1(name, jarname); if (bytes != null) return bytes; } return null; // 見つからなかった(;_;) } private byte loadClassData1(String name, String jarname) { String fname = name.replace('.', '\\') + ".class"; String fname2 = name.replace('.', '/') + ".class"; try { JarFile jarfile = new JarFile(jarname); JarEntry entry = jarfile.getJarEntry(fname); if (entry == null) { entry = jarfile.getJarEntry(fname2); } if (entry == null) return null; // 見つからなかった(;_;) BufferedInputStream in = new BufferedInputStream(jarfile.getInputStream(entry)); byte[] bytes = new byte[(int) entry.getSize()]; int size = in.read(bytes); assert size == entry.getSize(); in.close(); return bytes; } catch (IOException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } return null; // 見つからなかった(;_;) } }