`
liufei.fir
  • 浏览: 676501 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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 ());
	}
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics