Skip to content

Instantly share code, notes, and snippets.

@yuba
Last active May 26, 2016 04:02
Show Gist options
  • Save yuba/37d62814036e00ee57e2cd66bf755d72 to your computer and use it in GitHub Desktop.
Save yuba/37d62814036e00ee57e2cd66bf755d72 to your computer and use it in GitHub Desktop.
任意のjarファイルから条件に合ったクラスをロードする ref: http://qiita.com/yuba/items/f9f02d4e81c5020c268a
/**
* 指定したjarファイルから指定interfaceの実装クラス(引数なしコンストラクタを持つもの)をすべてロードして返します。
* @param jarPath jarファイル
* @param i 実装しているべきinterfaceまたは親クラス
* @param <Interface> 実装しているべきinterfaceまたは親クラス
* @return jarファイル内に含まれる、条件に合うクラスすべてを含むリスト
* @throws IOException jarファイルの読み込みができませんでした。
*/
public static <Interface> List<Class<Interface>> loadClassesInJar(String jarPath, Class<Interface> i) throws IOException
{
final URL jarUrl = new File(jarPath).toURI().toURL();
final URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[]{jarUrl});
final List<Class<Interface>> result = new ArrayList<Class<Interface>>();
final JarFile jarFile = new JarFile(jarPath);
for (final Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); )
{
// ファイル要素に限って(=ディレクトリをはじいて)スキャン
final JarEntry jarEntry = entries.nextElement();
if (jarEntry.isDirectory()) continue;
// classファイルに限定
final String fileName = jarEntry.getName();
if (!fileName.endsWith(".class")) continue;
// classファイルをクラスとしてロード。
final Class<?> clazz;
try {
clazz = urlClassLoader.loadClass(fileName.substring(0, fileName.length() - 6).replace('/', '.'));
} catch (ClassNotFoundException e) {
continue;
}
// iの派生型であることを確認
if (!i.isAssignableFrom(clazz)) continue;
// 引数なしコンストラクタを持つことを確認
try {
clazz.getConstructor();
} catch (NoSuchMethodException e) {
continue;
}
result.add((Class<Interface>) clazz);
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment