ClassLoader

package org.liufei.neta.lib;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.apache.log4j.Logger;
import org.liufei.neta.util.FileSystemUtils;

/**
* ClassLoader工厂。
*
* @author 刘飞
*/
public final class ClassLoaderFactory {

private static final Logger LOG = Logger
.getLogger ( ClassLoaderFactory.class );

/**
* 加载目录文件和jar文件到JVM中。
*
* @param path
* 目录文件
* @param parent
* 父级ClassLoader
* @return
* @throws Exception
*/
public static ClassLoader createClassLoader ( String[] path,
final ClassLoader parent ) throws Exception {

if ( LOG.isDebugEnabled () ) LOG.debug ( "Creating new class loader" );
/**
* 为该ClassLoader构建Classpath
*/
Set<URL> set = new LinkedHashSet<URL> ();

if ( path != null ) {
if ( path.length > 0 ) {
for ( String p : path ) {
File file = new File ( p );

List<File> list = new ArrayList<File> ();
FileSystemUtils.listAllFiles ( file, list );
for ( File f : list ) {
URL url = f.toURI ().toURL ();
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including file " + url );
set.add ( url );
}
}
}
else {
return Thread.currentThread ().getContextClassLoader ();
}
}
else {
return Thread.currentThread ().getContextClassLoader ();
}

/**
* 构建一个新的ClassLoader返回。
*/
final URL[] array = set.toArray ( new URL[ set.size () ] );
return AccessController
.doPrivileged ( new PrivilegedAction<StandardClassLoader> () {
@Override
public StandardClassLoader run () {
if ( parent == null ) return new StandardClassLoader (
array );
else return new StandardClassLoader ( array, parent );
}
} );
}

/**
* 加载目录文件和jar文件到JVM中。
*
* @param unpacked
* 未打包的目录
* @param packed
* 打包的jar文件
* @param parent
* 父级ClassLoader
* @return
* @throws Exception
*/
public static ClassLoader createClassLoader ( File unpacked[],
File packed[], final ClassLoader parent ) throws Exception {

if ( LOG.isDebugEnabled () ) LOG.debug ( "Creating new class loader" );

/**
* 为该ClassLoader构建Classpath
*/
Set<URL> set = new LinkedHashSet<URL> ();

/**
* 加载目录
*/
if ( unpacked != null ) {
for ( int i = 0 ; i < unpacked.length ; i++ ) {
File file = unpacked [ i ];
if ( ! file.exists () || ! file.canRead () ) continue;
file = new File ( file.getCanonicalPath () + File.separator );
URL url = file.toURI ().toURL ();
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including directory " + url );
set.add ( url );
}
}

/**
* 加载目录下的JAR文件
*/
if ( packed != null ) {
for ( int i = 0 ; i < packed.length ; i++ ) {
File directory = packed [ i ];
if ( ! directory.isDirectory () || ! directory.exists ()
|| ! directory.canRead () ) continue;
String filenames[] = directory.list ();
for ( int j = 0 ; j < filenames.length ; j++ ) {
String filename = filenames [ j ]
.toLowerCase ( Locale.ENGLISH );
if ( ! filename.endsWith ( ".jar" ) ) continue;
File file = new File ( directory, filenames [ j ] );
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including jar file "
+ file.getAbsolutePath () );
URL url = file.toURI ().toURL ();
set.add ( url );
}
}
}

/**
* 构建一个新的ClassLoader返回。
*/
final URL[] array = set.toArray ( new URL[ set.size () ] );
return AccessController
.doPrivileged ( new PrivilegedAction<StandardClassLoader> () {
@Override
public StandardClassLoader run () {
if ( parent == null ) return new StandardClassLoader (
array );
else return new StandardClassLoader ( array, parent );
}
} );
}

/**
* 加载目录文件和jar文件到JVM中。
*
* @param repositories
* @param parent
* @return
* @throws Exception
*/
public static ClassLoader createClassLoader (
List<Repository> repositories, final ClassLoader parent )
throws Exception {

if ( LOG.isDebugEnabled () ) LOG.debug ( "Creating new class loader" );

/**
* 为该ClassLoader构建Classpath
*/
Set<URL> set = new LinkedHashSet<URL> ();

if ( repositories != null ) {
for ( Repository repository : repositories ) {
if ( repository.getType () == RepositoryType.URL ) {
URL url = new URL ( repository.getLocation () );
if ( LOG.isDebugEnabled () ) LOG.debug ( " Including URL "
+ url );
set.add ( url );
}
else if ( repository.getType () == RepositoryType.DIR ) {
File directory = new File ( repository.getLocation () );
directory = directory.getCanonicalFile ();
if ( ! validateFile ( directory, RepositoryType.DIR ) ) {
continue;
}
URL url = directory.toURI ().toURL ();
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including directory " + url );
set.add ( url );
}
else if ( repository.getType () == RepositoryType.JAR ) {
File file = new File ( repository.getLocation () );
file = file.getCanonicalFile ();
if ( ! validateFile ( file, RepositoryType.JAR ) ) {
continue;
}
URL url = file.toURI ().toURL ();
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including jar file " + url );
set.add ( url );
}
else if ( repository.getType () == RepositoryType.GLOB ) {
File directory = new File ( repository.getLocation () );
directory = directory.getCanonicalFile ();
if ( ! validateFile ( directory, RepositoryType.GLOB ) ) {
continue;
}
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including directory glob "
+ directory.getAbsolutePath () );
String filenames[] = directory.list ();
for ( int j = 0 ; j < filenames.length ; j++ ) {
String filename = filenames [ j ]
.toLowerCase ( Locale.ENGLISH );
if ( ! filename.endsWith ( ".jar" ) ) continue;
File file = new File ( directory, filenames [ j ] );
file = file.getCanonicalFile ();
if ( ! validateFile ( file, RepositoryType.JAR ) ) {
continue;
}
if ( LOG.isDebugEnabled () ) LOG
.debug ( " Including glob jar file "
+ file.getAbsolutePath () );
URL url = file.toURI ().toURL ();
set.add ( url );
}
}
}
}

/**
* 构建一个新的ClassLoader返回。
*/
final URL[] array = set.toArray ( new URL[ set.size () ] );
if ( LOG.isDebugEnabled () ) for ( int i = 0 ; i < array.length ; i++ ) {
LOG.debug ( " location " + i + " is " + array [ i ] );
}

return AccessController
.doPrivileged ( new PrivilegedAction<StandardClassLoader> () {
@Override
public StandardClassLoader run () {
if ( parent == null ) return new StandardClassLoader (
array );
else return new StandardClassLoader ( array, parent );
}
} );
}

private static boolean validateFile ( File file, RepositoryType type )
throws IOException {
if ( RepositoryType.DIR == type || RepositoryType.GLOB == type ) {
if ( ! file.exists () || ! file.isDirectory () || ! file.canRead () ) {
LOG.warn ( "Problem with JAR file [" + file + "], exists: ["
+ file.exists () + "], canRead: [" + file.canRead ()
+ "]" );
return false;
}
}
else if ( RepositoryType.JAR == type ) {
if ( ! file.exists () || ! file.canRead () ) {
LOG.warn ( "Problem with JAR file [" + file + "], exists: ["
+ file.exists () + "], canRead: [" + file.canRead ()
+ "]" );
return false;
}
}
return true;
}

public static enum RepositoryType {
DIR, GLOB, JAR, URL
}

public static class Repository {
private String location;
private RepositoryType type;

public Repository ( String location, RepositoryType type ) {
this.location = location;
this.type = type;
}

public String getLocation () {
return location;
}

public RepositoryType getType () {
return type;
}
}
}

package org.liufei.neta.lib;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.liufei.neta.util.ClassUtils;
import org.liufei.neta.util.FileCopyUtils;
import org.liufei.neta.util.ObjectCreator;

/**
* 动态加载jar文件, 指定目录下的jar文件和Class文件装入虚拟机供调用。
*
* @author 刘飞
*/
public class ClasspathLoader extends URLClassLoader {

private static final Logger LOG = Logger.getLogger ( ClasspathLoader.class );

/**
* @param urls
*/
public ClasspathLoader ( URL[] urls ) {
super ( urls );
this.debugUrls ( urls );
}

/**
* @param url
*/
public ClasspathLoader ( URL url ) {
this ( new URL[] {
url
} );
}

/**
* @param url
* @throws MalformedURLException
*/
public ClasspathLoader ( String url ) throws MalformedURLException {
this ( toUrl ( url ) );
}

/**
* @param urls
* @throws MalformedURLException
*/
public ClasspathLoader ( String[] urls ) throws MalformedURLException {
this ( toUrl ( urls ) );
}

/**
* 加载并实例化指定类名称的类.
*
* @param clazz
* 类名称
* @param constructorArgTypes
* 构造参数类型
* @param constructorArgs
* 构造参数
* @return
* @throws LinkageError
* @throws ClassNotFoundException
*/
public Object newInstance ( String clazz,
List<Class<?>> constructorArgTypes, List<Object> constructorArgs )
throws ClassNotFoundException, LinkageError {
return ObjectCreator.create ( this.load ( clazz ), constructorArgTypes,
constructorArgs );
}

/**
* 加载并实例化指定类名称的类, 该类必须有一个无参的构造方法。
*
* @param clazz
* 类名称
* @return
* @throws LinkageError
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public Object newInstance ( String clazz ) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, LinkageError {
return this.load ( clazz ).newInstance ();
}

/**
* 加载类
*
* @param clazz
* 类名称
* @return
* @throws ClassNotFoundException
* @throws LinkageError
*/
public Class<?> load ( String clazz ) throws ClassNotFoundException,
LinkageError {
return ClassUtils.forName ( clazz, this );
}

/**
* 从比特流里加载java字节码并编译生成Class对象加载到JVM
*
* @param name
* 类名称
* @param b
* @param off
* @param len
* @return
* @throws ClassFormatError
*/
public Class<?> defineClassByBytes ( String name, byte[] b, int off, int len )
throws ClassFormatError {
return this.defineClass ( name, b, off, len );
}

/**
* 从文件中读取比特流加载java字节码并编译生成Class对象加载到JVM
*
* @param name
* 类名称
* @param file
* class字节码文件
* @return
* @throws IOException
*/
public Class<?> defineClassByBytes ( String name, File file )
throws IOException {
byte[] b = FileCopyUtils.copyToByteArray ( file );
return this.defineClass ( name, b, 0, b.length );
}

/**
* 从文件中读取比特流加载java字节码并编译生成Class对象加载到JVM
*
* @param name
* 类名称
* @param file
* class字节码文件
* @return
* @throws IOException
*/
public Class<?> defineClassByBytes ( String name, String file )
throws IOException {
return this.defineClassByBytes ( name, new File ( file ) );
}

@Override
protected Class<?> findClass ( String name ) throws ClassNotFoundException {
return super.findClass ( name );
}

@Override
protected synchronized Class<?> loadClass ( String name, boolean resolve )
throws ClassNotFoundException {
return super.loadClass ( name, resolve );
}

@Override
public Class<?> loadClass ( String name ) throws ClassNotFoundException {
return super.loadClass ( name );
}

private void debugUrls ( URL... urls ) {
for ( URL url : urls ) {
LOG.debug ( "loading java class source from classpath url : "
+ url.toString () );
}
}

/**
* 将路径数组转换为URL对象数组。
*
* @param urls
* @return
* @throws MalformedURLException
*/
private static URL[] toUrl ( String[] urls ) throws MalformedURLException {
List<URL> list = new ArrayList<URL> ();
for ( String u : urls ) {
list.add ( toUrl ( u ) );
}
return list.toArray ( new URL[ urls.length ] );
}

/**
* 将路径数组转换为URL对象数组。
*
* @param urls
* @return
* @throws MalformedURLException
*/
private static URL toUrl ( String url ) throws MalformedURLException {
return new URL ( url );
}
}
package org.liufei.neta.util;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

/**
* 系统包操作工具。
*
* @author 刘飞
*/
public class PackageUtil {

/**
* 找出指定文件下指定包名的所有类
*
* @param fileDir
* 文件
* @param pkgName
* 包名
* @return
*/
public static List<String> getClassInPackage ( String fileDir,
String pkgName ) {
Assert.notNull ( fileDir ) ;
Assert.notNull ( pkgName ) ;
return getClassInPackage ( new File ( fileDir ), pkgName );
}

/**
* 找出指定文件下指定包名的所有类
*
* @param fileDir
* 文件
* @param pkgName
* 包名
* @return
*/
public static List<String> getClassInPackage ( File fileDir, String pkgName ) {
Assert.notNull ( fileDir ) ;
Assert.notNull ( pkgName ) ;
List<File> dirs = new ArrayList<File> ();
FileSystemUtils.listAllFiles ( fileDir, dirs );
return getClassInPackage ( dirs, pkgName );
}

/**
* 找出指定目录下的所有类
*
* @param dirs
* 目录
* @param pkgName
* 包名
* @return
*/
public static List<String> getClassInPackage ( List<File> dirs,
String pkgName ) {
Assert.notNull ( dirs ) ;
Assert.notNull ( pkgName ) ;
List<String> ret = new ArrayList<String> ();
String pkg = pkgName.replace ( ".", File.separator );
String rPath = pkgName.replace ( '.', '/' ) + "/";
try {
for ( File classPath : dirs ) {
if ( ! classPath.exists () ) continue;
if ( classPath.isDirectory () ) {
File dir = new File ( classPath, rPath );
if ( ! dir.exists () ) continue;
for ( File file : dir.listFiles () ) {
if ( file.isFile () ) {
String clsName = file.getName ();
clsName = pkgName
+ "."
+ clsName.substring ( 0,
clsName.length () - 6 );
ret.add ( clsName );
}
}
}
else if ( classPath.isFile ()
&& ( classPath.getName ().endsWith ( ".java" ) || classPath
.getName ().endsWith ( ".class" ) )
&& classPath.getName ().indexOf ( "$" ) == - 1
&& classPath.getAbsolutePath ().indexOf ( pkg ) != - 1 ) {

if ( classPath.getName ().endsWith ( ".java" ) ) {
String clsName = classPath.getAbsolutePath ()
.substring (
classPath.getAbsolutePath ().indexOf (
pkg ) ).replace (
File.separator, "." );

clsName = clsName.substring ( 0, clsName.length () - 5 );
ret.add ( clsName );
}
else if ( classPath.getName ().endsWith ( ".class" ) ) {
String clsName = classPath.getAbsolutePath ()
.substring (
classPath.getAbsolutePath ().indexOf (
pkg ) ).replace (
File.separator, "." );

clsName = clsName.substring ( 0, clsName.length () - 6 );
ret.add ( clsName );
}
}
else {
FileInputStream fis = new FileInputStream ( classPath );
JarInputStream jis = new JarInputStream ( fis, false );
JarEntry e = null;
while ( ( e = jis.getNextJarEntry () ) != null ) {
String eName = e.getName ();
if ( eName.startsWith ( rPath )
&& ! eName.endsWith ( "/" ) ) {
ret.add ( eName.replace ( '/', '.' ).substring ( 0,
eName.length () - 6 ) );
}
jis.closeEntry ();
}
jis.close ();
}
}
for ( String cls : getClassInPackage ( pkgName ) ) {
ret.add ( cls );
}
}
catch ( Exception e ) {
throw new RuntimeException ( e );
}

return ret;
}

/**
* 找出系统目录下的所有类
*
* @param pkgName
* 包名
* @return
*/
public static List<String> getClassInPackage ( String pkgName ) {
Assert.notNull ( pkgName ) ;
List<String> ret = new ArrayList<String> ();
String pkg = pkgName.replace ( ".", File.separator );
String rPath = pkgName.replace ( '.', '/' ) + "/";
try {
for ( File classPath : CLASS_PATH_ARRAY ) {
if ( ! classPath.exists () ) continue;
if ( classPath.isDirectory () ) {
File dir = new File ( classPath, rPath );
if ( ! dir.exists () ) continue;
for ( File file : dir.listFiles () ) {
if ( file.isFile () ) {
String clsName = file.getName ();
clsName = pkgName
+ "."
+ clsName.substring ( 0,
clsName.length () - 6 );
ret.add ( clsName );
}
}
}
else if ( classPath.isFile ()
&& ( classPath.getName ().endsWith ( ".java" ) || classPath
.getName ().endsWith ( ".class" ) )
&& classPath.getName ().indexOf ( "$" ) == - 1
&& classPath.getAbsolutePath ().indexOf ( pkg ) != - 1 ) {

if ( classPath.getName ().endsWith ( ".java" ) ) {
String clsName = classPath.getAbsolutePath ()
.substring (
classPath.getAbsolutePath ().indexOf (
pkg ) ).replace (
File.separator, "." );

clsName = clsName.substring ( 0, clsName.length () - 5 );
ret.add ( clsName );
}
else if ( classPath.getName ().endsWith ( ".class" ) ) {
String clsName = classPath.getAbsolutePath ()
.substring (
classPath.getAbsolutePath ().indexOf (
pkg ) ).replace (
File.separator, "." );

clsName = clsName.substring ( 0, clsName.length () - 6 );
ret.add ( clsName );
}
}
else {
FileInputStream fis = new FileInputStream ( classPath );
JarInputStream jis = new JarInputStream ( fis, false );
JarEntry e = null;
while ( ( e = jis.getNextJarEntry () ) != null ) {
String eName = e.getName ();
if ( eName.startsWith ( rPath )
&& ! eName.endsWith ( "/" )
&& eName.indexOf ( "$" ) == - 1 ) {
ret.add ( eName.replace ( '/', '.' ).substring ( 0,
eName.length () - 6 ) );
}
jis.closeEntry ();
}
jis.close ();
}
}
}
catch ( Exception e ) {
throw new RuntimeException ( e );
}

return ret;
}

private static String[] CLASS_PATH_PROP = {
"java.class.path", "java.ext.dirs", "sun.boot.class.path",
"user.dir", "java.library.path", "java.home", "user.home"
};

private static List<File> CLASS_PATH_ARRAY = getClassPath ();

private static List<File> getClassPath () {
List<File> ret = new ArrayList<File> ();
String delim = ":";
if ( System.getProperty ( "os.name" ).indexOf ( "Windows" ) != - 1 ) delim = ";";
for ( String pro : CLASS_PATH_PROP ) {
String[] pathes = System.getProperty ( pro ).split ( delim );
for ( String path : pathes )
ret.add ( new File ( path ) );
}
return ret;
}

public static void main ( String[] args ) {
List<String> classes = PackageUtil.getClassInPackage ( "D:/lib",
"org.liufei" );
for ( String string : classes ) {
System.out.println ( "class : " + string );
}
System.out.println (classes.size ());
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值