All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.wicp.tams.common.apiext.ClassLoaderPlugin Maven / Gradle / Ivy
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;
}
}