org.seasar.framework.util.ClassLoaderUtil Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.framework.util;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import org.seasar.framework.exception.ClassNotFoundRuntimeException;
import org.seasar.framework.exception.IORuntimeException;
import org.seasar.framework.message.MessageFormatter;
/**
* {@link ClassLoader}を扱うためのユーティリティ・クラスです。
*
* @author koichik
*/
public abstract class ClassLoaderUtil {
private static final Method findLoadedClassMethod = getFindLoadedClassMethod();
private static final Method defineClassMethod = getDefineClassMethod();
private static final Method definePackageMethod = getDefinePackageMethod();
/**
* インスタンスを構築します。
*/
protected ClassLoaderUtil() {
}
private static Method getFindLoadedClassMethod() {
final Method method = ClassUtil.getDeclaredMethod(ClassLoader.class,
"findLoadedClass", new Class[] { String.class });
if (method.trySetAccessible())
method.setAccessible(true);
return method;
}
private static Method getDefineClassMethod() {
final Method method = ClassUtil.getDeclaredMethod(ClassLoader.class,
"defineClass", new Class[] { String.class, byte[].class,
int.class, int.class });
if (method.trySetAccessible())
method.setAccessible(true);
return method;
}
private static Method getDefinePackageMethod() {
final Method method = ClassUtil.getDeclaredMethod(ClassLoader.class,
"definePackage", new Class[] { String.class, String.class,
String.class, String.class, String.class, String.class,
String.class, URL.class });
if (method.trySetAccessible())
method.setAccessible(true);
return method;
}
/**
* クラスローダを返します。
*
* クラスローダは以下の順で検索します。
*
*
* - 呼び出されたスレッドにコンテキスト・クラスローダが設定されている場合はそのコンテキスト・クラスローダ
* - ターゲット・クラスをロードしたクラスローダを取得できればそのクラスローダ
* - このクラスをロードしたクラスローダを取得できればそのクラスローダ
* - システムを取得できればそのクラスローダ
*
*
* ただし、ターゲット・クラスをロードしたクラスローダとこのクラスをロードしたクラスローダの両方が取得できた場合で、
* ターゲット・クラスをロードしたクラスローダがこのクラスをロードしたクラスローダの祖先であった場合は、
* このクラスをロードしたクラスローダを返します。
*
*
* @param targetClass
* ターゲット・クラス
* @return クラスローダ
* @throws IllegalStateException
* クラスローダを取得できなかった場合
*/
public static ClassLoader getClassLoader(final Class> targetClass) {
final ClassLoader contextClassLoader = Thread.currentThread()
.getContextClassLoader();
if (contextClassLoader != null) {
return contextClassLoader;
}
final ClassLoader targetClassLoader = targetClass.getClassLoader();
final ClassLoader thisClassLoader = ClassLoaderUtil.class
.getClassLoader();
if (targetClassLoader != null && thisClassLoader != null) {
if (isAncestor(thisClassLoader, targetClassLoader)) {
return thisClassLoader;
}
return targetClassLoader;
}
if (targetClassLoader != null) {
return targetClassLoader;
}
if (thisClassLoader != null) {
return thisClassLoader;
}
final ClassLoader systemClassLoader = ClassLoader
.getSystemClassLoader();
if (systemClassLoader != null) {
return systemClassLoader;
}
throw new IllegalStateException(MessageFormatter.getMessage("ESSR0001",
new Object[] { "ClassLoader" }));
}
/**
* コンテキストクラスローダから指定された名前を持つすべてのリソースを探します。
*
* @param name
* リソース名
* @return リソースに対する URL
* オブジェクトの列挙。リソースが見つからなかった場合、列挙は空になる。クラスローダがアクセスを持たないリソースは列挙に入らない
* @see java.lang.ClassLoader#getResources(String)
*/
public static Iterator getResources(final String name) {
return getResources(Thread.currentThread().getContextClassLoader(),
name);
}
/**
* {@link #getClassLoader(Class)}が返すクラスローダから指定された名前を持つすべてのリソースを探します。
*
* @param targetClass
* ターゲット・クラス
* @param name
* リソース名
* @return リソースに対する URL
* オブジェクトの列挙。リソースが見つからなかった場合、列挙は空になる。クラスローダがアクセスを持たないリソースは列挙に入らない
* @see java.lang.ClassLoader#getResources(String)
*/
public static Iterator getResources(final Class> targetClass,
final String name) {
return getResources(getClassLoader(targetClass), name);
}
/**
* 指定のクラスローダから指定された名前を持つすべてのリソースを探します。
*
* @param loader
* クラスローダ
* @param name
* リソース名
* @return リソースに対する URL
* オブジェクトの列挙。リソースが見つからなかった場合、列挙は空になる。クラスローダがアクセスを持たないリソースは列挙に入らない
* @see java.lang.ClassLoader#getResources(String)
*/
public static Iterator getResources(final ClassLoader loader,
final String name) {
try {
final Enumeration e = loader.getResources(name);
return new EnumerationIterator(e);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
}
/**
* クラスローダother
がクラスローダcl
の祖先ならtrue
を返します。
*
* @param cl
* クラスローダ
* @param other
* クラスローダ
* @return クラスローダother
がクラスローダcl
の祖先ならtrue
*/
protected static boolean isAncestor(ClassLoader cl, final ClassLoader other) {
while (cl != null) {
if (cl == other) {
return true;
}
cl = cl.getParent();
}
return false;
}
/**
* 指定のクラスローダまたはその祖先の暮らすローダが、 このバイナリ名を持つクラスの起動ローダとしてJava仮想マシンにより記録されていた場合は、
* 指定されたバイナリ名を持つクラスを返します。 記録されていなかった場合はnull
を返します。
*
* @param classLoader
* クラスローダ
* @param className
* クラスのバイナリ名
* @return Class
オブジェクト。クラスがロードされていない場合はnull
* @see java.lang.ClassLoader#findLoadedClass(String)
*/
public static Class> findLoadedClass(final ClassLoader classLoader,
final String className) {
for (ClassLoader loader = classLoader; loader != null; loader = loader
.getParent()) {
final Class> clazz = (Class>) MethodUtil.invoke(
findLoadedClassMethod, loader, new Object[] { className });
if (clazz != null) {
return clazz;
}
}
return null;
}
/**
* バイトの配列をClass
クラスのインスタンスに変換します。
*
* @param classLoader
* バイナリデータからClass
クラスのインスタンスに変換するクラスローダ
* @param className
* クラスのバイナリ名
* @param bytes
* クラスデータを構成するバイト列
* @param offset
* クラスデータbytes
の開始オフセット
* @param length
* クラスデータの長さ
* @return 指定されたクラスデータから作成されたClass
オブジェクト
* @see java.lang.ClassLoader#defineClass(String, byte[], int, int)
*/
public static Class> defineClass(final ClassLoader classLoader,
final String className, final byte[] bytes, final int offset,
final int length) {
return (Class>) MethodUtil.invoke(defineClassMethod, classLoader,
new Object[] { className, bytes, Integer.valueOf(offset),
Integer.valueOf(length) });
}
/**
* 指定のClassLoader
で名前を使ってパッケージを定義します。
*
* @param classLoader
* パッケージを定義するクラスローダ
* @param name
* パッケージ名
* @param specTitle
* 仕様のタイトル
* @param specVersion
* 仕様のバージョン
* @param specVendor
* 仕様のベンダー
* @param implTitle
* 実装のタイトル
* @param implVersion
* 実装のバージョン
* @param implVendor
* 実装のベンダー
* @param sealBase
* null
でない場合、このパッケージは指定されたコードソースURL
オブジェクトを考慮してシールされる。そうでない場合、パッケージはシールされない
* @return 新しく定義されたPackage
オブジェクト
* @see java.lang.ClassLoader#definePackage(String, String, String, String,
* String, String, String, URL)
*/
public static Package definePackage(final ClassLoader classLoader,
final String name, final String specTitle,
final String specVersion, final String specVendor,
final String implTitle, final String implVersion,
final String implVendor, final URL sealBase) {
return (Package) MethodUtil.invoke(definePackageMethod, classLoader,
new Object[] { name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor, sealBase });
}
/**
* 指定されたバイナリ名を持つクラスをロードします。
*
* @param loader
* クラスローダ
* @param className
* クラスのバイナリ名
* @return 結果のClass
オブジェクト
* @throws ClassNotFoundRuntimeException
* クラスが見つからなかった場合
* @see java.lang.ClassLoader#loadClass(String)
*/
public static Class> loadClass(final ClassLoader loader,
final String className) {
try {
return loader.loadClass(className);
} catch (final ClassNotFoundException e) {
throw new ClassNotFoundRuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy