All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.wicp.tams.common.apiext.ClassLoaderPlugin Maven / Gradle / Ivy

There is a newer version: 6.1.0
Show newest version
package net.wicp.tams.common.apiext;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;

import javassist.ClassPool;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.constant.PathType;

/**
 * 
 * @author 偏锋书生
 *
 */
@Slf4j
public class ClassLoaderPlugin {
	private TamsURLClassLoader classLoader;

	private final int maxLevel;// 默认为1层,如果有多个插件,需要2层目录

	public TamsURLClassLoader getClassLoader() {
		return classLoader;
	}

	private ClassPool pool = ClassPool.getDefault();

	private Set jars = new HashSet();

	public Set getJars() {
		return jars;
	}

	public ClassPool getPool() {
		return pool;
	}

	public void close() {
		try {
			if (this.classLoader != null) {
				this.classLoader.close();
			}
		} catch (IOException e) {
			log.error("关闭classLoader失败", e);
		} finally {
			this.classLoader = null;
		}
	}

	public ClassLoaderPlugin(String jarfileDir, ClassLoader parent, int maxLevel) {
		this(new File(jarfileDir), parent, maxLevel);
		Validate.validState(new File(jarfileDir).exists(), "classLoader插件所在目录不存在:" + jarfileDir);
	}

	/***
	 * 加载子插件,并得到相关classloader
	 * 
	 * @param pluginDir
	 * @param parent
	 * @param maxLevel
	 * @return
	 */
	public static ClassLoader pluginClassLoader(String pluginDir, ClassLoader parent, int maxLevel) {
		ClassLoader retLoad = parent;
		if (StringUtil.isNull(pluginDir)) {// 插件加载
			log.error("插件目录为空值,使用父的classload");
			return parent;
		}
		//PathType pathType = PathType.getByName(pluginDir);
		String pathValue = PathType.getPath(pluginDir,false);
		if (StringUtil.isNull(pathValue)) {
			return parent;
		}
		ClassLoaderPlugin retLoadplugin = new ClassLoaderPlugin(pathValue, parent, 1);
		retLoad = retLoadplugin.getClassLoader();
		return retLoad;
	}

	/**
	 * 适合 jar-lib形式
	 * 
	 * @param pluginDir
	 * @return
	 */
	public static ClassLoader pluginClassLoader(String pluginDir) {
		return pluginClassLoader(pluginDir, Thread.currentThread().getContextClassLoader(), 1);
	}

	public ClassLoaderPlugin(File jarfileDir) {
		this(jarfileDir, null, 1);
	}

	public ClassLoaderPlugin(File jarfileDir, ClassLoader parent, int maxLevel) {
		this.maxLevel = maxLevel;
		this.classLoader = createClassLoader(jarfileDir, parent);// 它需要maxLevel,所在在后面
	}

	public Class loadClass(String className) throws ClassNotFoundException {

		return classLoader.loadClass(className);
	}

	public void addToClassLoader(final String baseDir, final FileFilter filter) {
		File base = new File(baseDir);
		if (base != null && base.exists() && base.isDirectory()) {
			File[] files = base.listFiles(filter);
			if (files == null || files.length == 0) {
				log.warn("No files added to classloader from lib: " + baseDir + " (resolved as: "
						+ base.getAbsolutePath() + ").");
			} else {
				this.classLoader = replaceClassLoader(classLoader, base, filter);
			}
		} else {
			log.warn("Can't find (or read) directory to add to classloader: " + baseDir + " (resolved as: "
					+ base.getAbsolutePath() + ").");
		}
	}

	public void addToClassLoader(final String baseDir) {
		addToClassLoader(baseDir, new SuffixFileFilter(".jar"));
	}

	private TamsURLClassLoader createClassLoader(final File libDir, ClassLoader parent) {
		if (null == parent) {
			parent = Thread.currentThread().getContextClassLoader();
		}
		return replaceClassLoader(new TamsURLClassLoader(new URL[0], parent), libDir, new SuffixFileFilter(".jar"));
	}

	private void findElements(java.util.List inputURLs, final File[] bases, final FileFilter filter,
			int curlever) {
		if (curlever >= maxLevel) {
			return;
		}
		if (ArrayUtils.isEmpty(bases)) {
			return;
		}
		List nextDirs = new ArrayList<>();
		for (File base : bases) {
			if (null != base && base.canRead() && base.isDirectory()) {
				File[] files = base.listFiles(filter);
				if (null != files && files.length > 0) {
					for (int j = 0; j < files.length; j++) {
						try {
							URL element = files[j].toURI().normalize().toURL();
							inputURLs.add(element);
							jars.add(files[j].getPath());
							log.info("Adding '{}' to classloader", element.toString());
							pool.appendClassPath(files[j].getPath());
							log.info("Adding '{}' to pool", element.toString());

						} catch (MalformedURLException e) {
							log.error("load jar file error", e);
							throw new RuntimeException("load jar file error ");
						} catch (NotFoundException e) {
							log.error("add jar to pool error", e);
							throw new RuntimeException("pool addpath error ");
						}
					}
				}

				if (curlever < maxLevel - 1) {
					File[] listFiles = base.listFiles(new FileFilter() {
						@Override
						public boolean accept(File pathname) {
							return pathname.isDirectory();
						}
					});
					nextDirs.addAll(Arrays.asList(listFiles));
				}
			}
		}
		curlever++;
		findElements(inputURLs, nextDirs.toArray(new File[nextDirs.size()]), filter, curlever);
	}

	private TamsURLClassLoader replaceClassLoader(final TamsURLClassLoader oldLoader, final File base,
			final FileFilter filter) {
		if (null != base && base.canRead() && base.isDirectory()) {
			List inputURLs = new ArrayList<>();
			for (URL url : oldLoader.getURLs()) {
				inputURLs.add(url);
			}
			findElements(inputURLs, new File[] { base }, filter, 0);
			if (inputURLs.size() == 0) {
				log.error("replaceClassLoader base dir:{} is empty", base.getAbsolutePath());
				return new TamsURLClassLoader(inputURLs.toArray(new URL[inputURLs.size()]), oldLoader.getParent());
			}
			ClassLoader oldParent = oldLoader.getParent();
			try {
				oldLoader.close();
			} catch (IOException e) {
				log.error("close classload error ", e);
			}
			return new TamsURLClassLoader(inputURLs.toArray(new URL[inputURLs.size()]), oldParent);
		}
		return new TamsURLClassLoader(new URL[0], oldLoader.getParent());
	}

	public int getMaxLevel() {
		return this.maxLevel;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy