|
@@ -1,13 +1,6 @@
|
|
-package com.alibaba.otter.canal.client.support;
|
|
|
|
|
|
+package com.alibaba.otter.canal.client.adapter.support;
|
|
|
|
|
|
-import org.apache.commons.lang.StringUtils;
|
|
|
|
-import org.slf4j.Logger;
|
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
|
-
|
|
|
|
-import java.io.BufferedReader;
|
|
|
|
-import java.io.File;
|
|
|
|
-import java.io.FilenameFilter;
|
|
|
|
-import java.io.InputStreamReader;
|
|
|
|
|
|
+import java.io.*;
|
|
import java.net.MalformedURLException;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
import java.net.URL;
|
|
import java.net.URLClassLoader;
|
|
import java.net.URLClassLoader;
|
|
@@ -17,6 +10,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentMap;
|
|
import java.util.concurrent.ConcurrentMap;
|
|
import java.util.regex.Pattern;
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* SPI 类加载器
|
|
* SPI 类加载器
|
|
*
|
|
*
|
|
@@ -24,33 +20,36 @@ import java.util.regex.Pattern;
|
|
* @version 1.0.0
|
|
* @version 1.0.0
|
|
*/
|
|
*/
|
|
public class ExtensionLoader<T> {
|
|
public class ExtensionLoader<T> {
|
|
- private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
|
|
|
|
|
|
|
|
- private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
|
|
|
|
|
+ private static final Logger logger = LoggerFactory
|
|
|
|
+ .getLogger(ExtensionLoader.class);
|
|
|
|
+
|
|
|
|
+ private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
|
|
|
|
|
- private static final String CANAL_DIRECTORY = "META-INF/canal/";
|
|
|
|
|
|
+ private static final String CANAL_DIRECTORY = "META-INF/canal/";
|
|
|
|
|
|
- private static final String DEFAULT_CLASSLOADER_POLICY = "internal";
|
|
|
|
|
|
+ private static final String DEFAULT_CLASSLOADER_POLICY = "internal";
|
|
|
|
|
|
- private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
|
|
|
|
|
|
+ private static final Pattern NAME_SEPARATOR = Pattern
|
|
|
|
+ .compile("\\s*[,]+\\s*");
|
|
|
|
|
|
- private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
|
|
|
|
|
- private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();
|
|
|
|
|
|
- private final Class<?> type;
|
|
|
|
|
|
+ private final Class<?> type;
|
|
|
|
|
|
- private final String classLoaderPolicy;
|
|
|
|
|
|
+ private final String classLoaderPolicy;
|
|
|
|
|
|
- private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
|
|
|
|
|
|
- private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
|
|
|
|
|
+ private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
|
|
|
|
|
|
- private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
|
|
|
|
|
|
- private String cachedDefaultName;
|
|
|
|
|
|
+ private String cachedDefaultName;
|
|
|
|
|
|
- private ConcurrentHashMap<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
|
|
|
|
|
|
+ private ConcurrentHashMap<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
|
|
|
|
|
|
private static <T> boolean withExtensionAnnotation(Class<T> type) {
|
|
private static <T> boolean withExtensionAnnotation(Class<T> type) {
|
|
return type.isAnnotationPresent(SPI.class);
|
|
return type.isAnnotationPresent(SPI.class);
|
|
@@ -62,14 +61,13 @@ public class ExtensionLoader<T> {
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type, String classLoaderPolicy) {
|
|
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type, String classLoaderPolicy) {
|
|
- if (type == null)
|
|
|
|
- throw new IllegalArgumentException("Extension type == null");
|
|
|
|
|
|
+ if (type == null) throw new IllegalArgumentException("Extension type == null");
|
|
if (!type.isInterface()) {
|
|
if (!type.isInterface()) {
|
|
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
|
|
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
|
|
}
|
|
}
|
|
if (!withExtensionAnnotation(type)) {
|
|
if (!withExtensionAnnotation(type)) {
|
|
- throw new IllegalArgumentException("Extension type(" + type +
|
|
|
|
- ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
|
|
|
|
|
|
+ throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @"
|
|
|
|
+ + SPI.class.getSimpleName() + " Annotation!");
|
|
}
|
|
}
|
|
|
|
|
|
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
|
|
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
|
|
@@ -80,7 +78,7 @@ public class ExtensionLoader<T> {
|
|
return loader;
|
|
return loader;
|
|
}
|
|
}
|
|
|
|
|
|
- private ExtensionLoader(Class<?> type, String classLoaderPolicy) {
|
|
|
|
|
|
+ private ExtensionLoader(Class<?> type, String classLoaderPolicy){
|
|
this.type = type;
|
|
this.type = type;
|
|
this.classLoaderPolicy = classLoaderPolicy;
|
|
this.classLoaderPolicy = classLoaderPolicy;
|
|
}
|
|
}
|
|
@@ -93,7 +91,6 @@ public class ExtensionLoader<T> {
|
|
return cachedNames.get(extensionClass);
|
|
return cachedNames.get(extensionClass);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
public ConcurrentHashMap<String, IllegalStateException> getExceptions() {
|
|
public ConcurrentHashMap<String, IllegalStateException> getExceptions() {
|
|
return exceptions;
|
|
return exceptions;
|
|
}
|
|
}
|
|
@@ -107,8 +104,7 @@ public class ExtensionLoader<T> {
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
public T getLoadedExtension(String name) {
|
|
public T getLoadedExtension(String name) {
|
|
- if (name == null || name.length() == 0)
|
|
|
|
- throw new IllegalArgumentException("Extension name == null");
|
|
|
|
|
|
+ if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null");
|
|
Holder<Object> holder = cachedInstances.get(name);
|
|
Holder<Object> holder = cachedInstances.get(name);
|
|
if (holder == null) {
|
|
if (holder == null) {
|
|
cachedInstances.putIfAbsent(name, new Holder<>());
|
|
cachedInstances.putIfAbsent(name, new Holder<>());
|
|
@@ -136,8 +132,7 @@ public class ExtensionLoader<T> {
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
public T getExtension(String name) {
|
|
public T getExtension(String name) {
|
|
- if (name == null || name.length() == 0)
|
|
|
|
- throw new IllegalArgumentException("Extension name == null");
|
|
|
|
|
|
+ if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null");
|
|
if ("true".equals(name)) {
|
|
if ("true".equals(name)) {
|
|
return getDefaultExtension();
|
|
return getDefaultExtension();
|
|
}
|
|
}
|
|
@@ -164,16 +159,14 @@ public class ExtensionLoader<T> {
|
|
*/
|
|
*/
|
|
public T getDefaultExtension() {
|
|
public T getDefaultExtension() {
|
|
getExtensionClasses();
|
|
getExtensionClasses();
|
|
- if (null == cachedDefaultName || cachedDefaultName.length() == 0
|
|
|
|
- || "true".equals(cachedDefaultName)) {
|
|
|
|
|
|
+ if (null == cachedDefaultName || cachedDefaultName.length() == 0 || "true".equals(cachedDefaultName)) {
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
return getExtension(cachedDefaultName);
|
|
return getExtension(cachedDefaultName);
|
|
}
|
|
}
|
|
|
|
|
|
public boolean hasExtension(String name) {
|
|
public boolean hasExtension(String name) {
|
|
- if (name == null || name.length() == 0)
|
|
|
|
- throw new IllegalArgumentException("Extension name == null");
|
|
|
|
|
|
+ if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null");
|
|
try {
|
|
try {
|
|
return getExtensionClass(name) != null;
|
|
return getExtensionClass(name) != null;
|
|
} catch (Throwable t) {
|
|
} catch (Throwable t) {
|
|
@@ -197,7 +190,7 @@ public class ExtensionLoader<T> {
|
|
/**
|
|
/**
|
|
* 编程方式添加新扩展点
|
|
* 编程方式添加新扩展点
|
|
*
|
|
*
|
|
- * @param name 扩展点名
|
|
|
|
|
|
+ * @param name 扩展点名
|
|
* @param clazz 扩展点类
|
|
* @param clazz 扩展点类
|
|
* @throws IllegalStateException 要添加扩展点名已经存在
|
|
* @throws IllegalStateException 要添加扩展点名已经存在
|
|
*/
|
|
*/
|
|
@@ -205,20 +198,17 @@ public class ExtensionLoader<T> {
|
|
getExtensionClasses(); // load classes
|
|
getExtensionClasses(); // load classes
|
|
|
|
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
- throw new IllegalStateException("Input type " +
|
|
|
|
- clazz + "not implement Extension " + type);
|
|
|
|
|
|
+ throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type);
|
|
}
|
|
}
|
|
if (clazz.isInterface()) {
|
|
if (clazz.isInterface()) {
|
|
- throw new IllegalStateException("Input type " +
|
|
|
|
- clazz + "can not be interface!");
|
|
|
|
|
|
+ throw new IllegalStateException("Input type " + clazz + "can not be interface!");
|
|
}
|
|
}
|
|
|
|
|
|
- if (StringUtils.isBlank(name)) {
|
|
|
|
|
|
+ if (name == null || "".equals(name)) {
|
|
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
|
|
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
|
|
}
|
|
}
|
|
if (cachedClasses.get().containsKey(name)) {
|
|
if (cachedClasses.get().containsKey(name)) {
|
|
- throw new IllegalStateException("Extension name " +
|
|
|
|
- name + " already existed(Extension " + type + ")!");
|
|
|
|
|
|
+ throw new IllegalStateException("Extension name " + name + " already existed(Extension " + type + ")!");
|
|
}
|
|
}
|
|
|
|
|
|
cachedNames.put(clazz, name);
|
|
cachedNames.put(clazz, name);
|
|
@@ -228,7 +218,7 @@ public class ExtensionLoader<T> {
|
|
/**
|
|
/**
|
|
* 编程方式添加替换已有扩展点
|
|
* 编程方式添加替换已有扩展点
|
|
*
|
|
*
|
|
- * @param name 扩展点名
|
|
|
|
|
|
+ * @param name 扩展点名
|
|
* @param clazz 扩展点类
|
|
* @param clazz 扩展点类
|
|
* @throws IllegalStateException 要添加扩展点名已经存在
|
|
* @throws IllegalStateException 要添加扩展点名已经存在
|
|
* @deprecated 不推荐应用使用,一般只在测试时可以使用
|
|
* @deprecated 不推荐应用使用,一般只在测试时可以使用
|
|
@@ -238,20 +228,17 @@ public class ExtensionLoader<T> {
|
|
getExtensionClasses(); // load classes
|
|
getExtensionClasses(); // load classes
|
|
|
|
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
- throw new IllegalStateException("Input type " +
|
|
|
|
- clazz + "not implement Extension " + type);
|
|
|
|
|
|
+ throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type);
|
|
}
|
|
}
|
|
if (clazz.isInterface()) {
|
|
if (clazz.isInterface()) {
|
|
- throw new IllegalStateException("Input type " +
|
|
|
|
- clazz + "can not be interface!");
|
|
|
|
|
|
+ throw new IllegalStateException("Input type " + clazz + "can not be interface!");
|
|
}
|
|
}
|
|
|
|
|
|
- if (StringUtils.isBlank(name)) {
|
|
|
|
|
|
+ if (name == null || "".equals(name)) {
|
|
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
|
|
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
|
|
}
|
|
}
|
|
if (!cachedClasses.get().containsKey(name)) {
|
|
if (!cachedClasses.get().containsKey(name)) {
|
|
- throw new IllegalStateException("Extension name " +
|
|
|
|
- name + " not existed(Extension " + type + ")!");
|
|
|
|
|
|
+ throw new IllegalStateException("Extension name " + name + " not existed(Extension " + type + ")!");
|
|
}
|
|
}
|
|
|
|
|
|
cachedNames.put(clazz, name);
|
|
cachedNames.put(clazz, name);
|
|
@@ -259,13 +246,12 @@ public class ExtensionLoader<T> {
|
|
cachedInstances.remove(name);
|
|
cachedInstances.remove(name);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
private T createExtension(String name) {
|
|
private T createExtension(String name) {
|
|
Class<?> clazz = getExtensionClasses().get(name);
|
|
Class<?> clazz = getExtensionClasses().get(name);
|
|
if (clazz == null) {
|
|
if (clazz == null) {
|
|
- throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
|
|
|
|
- type + ") could not be instantiated: class could not be found");
|
|
|
|
|
|
+ throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
|
|
|
|
+ + ") could not be instantiated: class could not be found");
|
|
}
|
|
}
|
|
try {
|
|
try {
|
|
T instance = (T) EXTENSION_INSTANCES.get(clazz);
|
|
T instance = (T) EXTENSION_INSTANCES.get(clazz);
|
|
@@ -275,17 +261,15 @@ public class ExtensionLoader<T> {
|
|
}
|
|
}
|
|
return instance;
|
|
return instance;
|
|
} catch (Throwable t) {
|
|
} catch (Throwable t) {
|
|
- throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
|
|
|
|
- type + ") could not be instantiated: " + t.getMessage(), t);
|
|
|
|
|
|
+ throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
|
|
|
|
+ + ") could not be instantiated: " + t.getMessage(),
|
|
|
|
+ t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
private Class<?> getExtensionClass(String name) {
|
|
private Class<?> getExtensionClass(String name) {
|
|
- if (type == null)
|
|
|
|
- throw new IllegalArgumentException("Extension type == null");
|
|
|
|
- if (name == null)
|
|
|
|
- throw new IllegalArgumentException("Extension name == null");
|
|
|
|
|
|
+ if (type == null) throw new IllegalArgumentException("Extension type == null");
|
|
|
|
+ if (name == null) throw new IllegalArgumentException("Extension name == null");
|
|
Class<?> clazz = getExtensionClasses().get(name);
|
|
Class<?> clazz = getExtensionClasses().get(name);
|
|
if (clazz == null)
|
|
if (clazz == null)
|
|
throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!");
|
|
throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!");
|
|
@@ -312,13 +296,14 @@ public class ExtensionLoader<T> {
|
|
throw new IllegalStateException("failed to get class loader resource");
|
|
throw new IllegalStateException("failed to get class loader resource");
|
|
}
|
|
}
|
|
String dirtyPath = url.toString();
|
|
String dirtyPath = url.toString();
|
|
- String jarPath = dirtyPath.replaceAll("^.*file:/", ""); //removes file:/ and everything before it
|
|
|
|
- jarPath = jarPath.replaceAll("jar!.*", "jar"); //removes everything after .jar, if .jar exists in dirtyPath
|
|
|
|
- jarPath = jarPath.replaceAll("%20", " "); //necessary if path has spaces within
|
|
|
|
- if (!jarPath.endsWith(".jar")) { // this is needed if you plan to run the app using Spring Tools Suit play button.
|
|
|
|
|
|
+ String jarPath = dirtyPath.replaceAll("^.*file:/", ""); // removes file:/ and everything before it
|
|
|
|
+ jarPath = jarPath.replaceAll("jar!.*", "jar"); // removes everything after .jar, if .jar exists in dirtyPath
|
|
|
|
+ jarPath = jarPath.replaceAll("%20", " "); // necessary if path has spaces within
|
|
|
|
+ if (!jarPath.endsWith(".jar")) { // this is needed if you plan to run the app using Spring Tools Suit play
|
|
|
|
+ // button.
|
|
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
|
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
|
}
|
|
}
|
|
- return Paths.get(jarPath).getParent().toString(); //Paths - from java 8
|
|
|
|
|
|
+ return Paths.get(jarPath).getParent().toString(); // Paths - from java 8
|
|
}
|
|
}
|
|
|
|
|
|
private Map<String, Class<?>> loadExtensionClasses() {
|
|
private Map<String, Class<?>> loadExtensionClasses() {
|
|
@@ -329,7 +314,7 @@ public class ExtensionLoader<T> {
|
|
String[] names = NAME_SEPARATOR.split(value);
|
|
String[] names = NAME_SEPARATOR.split(value);
|
|
if (names.length > 1) {
|
|
if (names.length > 1) {
|
|
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
|
|
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
|
|
- + ": " + Arrays.toString(names));
|
|
|
|
|
|
+ + ": " + Arrays.toString(names));
|
|
}
|
|
}
|
|
if (names.length == 1) cachedDefaultName = names[0];
|
|
if (names.length == 1) cachedDefaultName = names[0];
|
|
}
|
|
}
|
|
@@ -337,12 +322,17 @@ public class ExtensionLoader<T> {
|
|
|
|
|
|
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
|
|
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
|
|
|
|
|
|
- //1. lib folder,customized extension classLoader (jar_dir/lib)
|
|
|
|
|
|
+ // 1. lib folder,customized extension classLoader (jar_dir/lib)
|
|
String dir = File.separator + this.getJarDirectoryPath() + File.separator + "lib";
|
|
String dir = File.separator + this.getJarDirectoryPath() + File.separator + "lib";
|
|
logger.info("extension classpath dir: " + dir);
|
|
logger.info("extension classpath dir: " + dir);
|
|
File externalLibDir = new File(dir);
|
|
File externalLibDir = new File(dir);
|
|
|
|
+ if (!externalLibDir.exists()) {
|
|
|
|
+ externalLibDir = new File(
|
|
|
|
+ File.separator + this.getJarDirectoryPath() + File.separator + "canal_client" + File.separator + "lib");
|
|
|
|
+ }
|
|
if (externalLibDir.exists()) {
|
|
if (externalLibDir.exists()) {
|
|
File[] files = externalLibDir.listFiles(new FilenameFilter() {
|
|
File[] files = externalLibDir.listFiles(new FilenameFilter() {
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public boolean accept(File dir, String name) {
|
|
public boolean accept(File dir, String name) {
|
|
return name.endsWith(".jar");
|
|
return name.endsWith(".jar");
|
|
@@ -359,8 +349,10 @@ public class ExtensionLoader<T> {
|
|
|
|
|
|
ClassLoader parent = Thread.currentThread().getContextClassLoader();
|
|
ClassLoader parent = Thread.currentThread().getContextClassLoader();
|
|
URLClassLoader localClassLoader;
|
|
URLClassLoader localClassLoader;
|
|
- if (!StringUtils.isEmpty(classLoaderPolicy) && DEFAULT_CLASSLOADER_POLICY.equalsIgnoreCase(classLoaderPolicy)) {
|
|
|
|
- localClassLoader = new URLClassLoader(new URL[]{url}, parent) {
|
|
|
|
|
|
+ if (classLoaderPolicy == null || "".equals(classLoaderPolicy)
|
|
|
|
+ || DEFAULT_CLASSLOADER_POLICY.equalsIgnoreCase(classLoaderPolicy)) {
|
|
|
|
+ localClassLoader = new URLClassLoader(new URL[] { url }, parent) {
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
Class<?> c = findLoadedClass(name);
|
|
Class<?> c = findLoadedClass(name);
|
|
@@ -368,15 +360,13 @@ public class ExtensionLoader<T> {
|
|
return c;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
|
|
- if (name.startsWith("java.")
|
|
|
|
- || name.startsWith("org.slf4j.")
|
|
|
|
- || name.startsWith("org.apache.logging")
|
|
|
|
- || name.startsWith("org.apache.commons.logging.")) {
|
|
|
|
- //|| name.startsWith("org.apache.hadoop.")) {
|
|
|
|
|
|
+ if (name.startsWith("java.") || name.startsWith("org.slf4j.")
|
|
|
|
+ || name.startsWith("org.apache.logging")
|
|
|
|
+ || name.startsWith("org.apache.commons.logging.")) {
|
|
|
|
+ // || name.startsWith("org.apache.hadoop.")) {
|
|
c = super.loadClass(name);
|
|
c = super.loadClass(name);
|
|
}
|
|
}
|
|
- if (c != null)
|
|
|
|
- return c;
|
|
|
|
|
|
+ if (c != null) return c;
|
|
|
|
|
|
try {
|
|
try {
|
|
// 先加载jar内的class,可避免jar冲突
|
|
// 先加载jar内的class,可避免jar冲突
|
|
@@ -391,19 +381,19 @@ public class ExtensionLoader<T> {
|
|
return super.loadClass(name);
|
|
return super.loadClass(name);
|
|
}
|
|
}
|
|
|
|
|
|
- // @Override
|
|
|
|
- // public Enumeration<URL> getResources(String name) throws IOException {
|
|
|
|
- // @SuppressWarnings("unchecked")
|
|
|
|
- // Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public Enumeration<URL> getResources(String name) throws IOException {
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
|
|
|
|
|
|
- // tmp[0] = findResources(name); //local class path first
|
|
|
|
- // //tmp[1] = super.getResources(name);
|
|
|
|
|
|
+ tmp[0] = findResources(name); // local class path first
|
|
|
|
+ // tmp[1] = super.getResources(name);
|
|
|
|
|
|
- // return new CompoundEnumeration<>(tmp);
|
|
|
|
- // }
|
|
|
|
|
|
+ return new CompoundEnumeration<>(tmp);
|
|
|
|
+ }
|
|
};
|
|
};
|
|
} else {
|
|
} else {
|
|
- localClassLoader = new URLClassLoader(new URL[]{url}, parent);
|
|
|
|
|
|
+ localClassLoader = new URLClassLoader(new URL[] { url }, parent);
|
|
}
|
|
}
|
|
|
|
|
|
loadFile(extensionClasses, CANAL_DIRECTORY, localClassLoader);
|
|
loadFile(extensionClasses, CANAL_DIRECTORY, localClassLoader);
|
|
@@ -411,7 +401,7 @@ public class ExtensionLoader<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- //2. load inner extension class with default classLoader
|
|
|
|
|
|
+ // 2. load inner extension class with default classLoader
|
|
ClassLoader classLoader = findClassLoader();
|
|
ClassLoader classLoader = findClassLoader();
|
|
loadFile(extensionClasses, CANAL_DIRECTORY, classLoader);
|
|
loadFile(extensionClasses, CANAL_DIRECTORY, classLoader);
|
|
loadFile(extensionClasses, SERVICES_DIRECTORY, classLoader);
|
|
loadFile(extensionClasses, SERVICES_DIRECTORY, classLoader);
|
|
@@ -419,6 +409,40 @@ public class ExtensionLoader<T> {
|
|
return extensionClasses;
|
|
return extensionClasses;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public static class CompoundEnumeration<E> implements Enumeration<E> {
|
|
|
|
+
|
|
|
|
+ private Enumeration<E>[] enums;
|
|
|
|
+ private int index = 0;
|
|
|
|
+
|
|
|
|
+ public CompoundEnumeration(Enumeration<E>[] enums){
|
|
|
|
+ this.enums = enums;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private boolean next() {
|
|
|
|
+ while (this.index < this.enums.length) {
|
|
|
|
+ if (this.enums[this.index] != null && this.enums[this.index].hasMoreElements()) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ++this.index;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public boolean hasMoreElements() {
|
|
|
|
+ return this.next();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public E nextElement() {
|
|
|
|
+ if (!this.next()) {
|
|
|
|
+ throw new NoSuchElementException();
|
|
|
|
+ } else {
|
|
|
|
+ return this.enums[this.index].nextElement();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private void loadFile(Map<String, Class<?>> extensionClasses, String dir, ClassLoader classLoader) {
|
|
private void loadFile(Map<String, Class<?>> extensionClasses, String dir, ClassLoader classLoader) {
|
|
String fileName = dir + type.getName();
|
|
String fileName = dir + type.getName();
|
|
try {
|
|
try {
|
|
@@ -450,11 +474,13 @@ public class ExtensionLoader<T> {
|
|
}
|
|
}
|
|
if (line.length() > 0) {
|
|
if (line.length() > 0) {
|
|
Class<?> clazz = classLoader.loadClass(line);
|
|
Class<?> clazz = classLoader.loadClass(line);
|
|
- //Class<?> clazz = Class.forName(line, true, classLoader);
|
|
|
|
|
|
+ // Class<?> clazz = Class.forName(line, true, classLoader);
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
if (!type.isAssignableFrom(clazz)) {
|
|
- throw new IllegalStateException("Error when load extension class(interface: " +
|
|
|
|
- type + ", class line: " + clazz.getName() + "), class "
|
|
|
|
- + clazz.getName() + "is not subtype of interface.");
|
|
|
|
|
|
+ throw new IllegalStateException(
|
|
|
|
+ "Error when load extension class(interface: " + type
|
|
|
|
+ + ", class line: " + clazz.getName()
|
|
|
|
+ + "), class " + clazz.getName()
|
|
|
|
+ + "is not subtype of interface.");
|
|
} else {
|
|
} else {
|
|
try {
|
|
try {
|
|
clazz.getConstructor(type);
|
|
clazz.getConstructor(type);
|
|
@@ -471,7 +497,11 @@ public class ExtensionLoader<T> {
|
|
extensionClasses.put(n, clazz);
|
|
extensionClasses.put(n, clazz);
|
|
} else if (c != clazz) {
|
|
} else if (c != clazz) {
|
|
cachedNames.remove(clazz);
|
|
cachedNames.remove(clazz);
|
|
- throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
|
|
|
|
|
|
+ throw new IllegalStateException(
|
|
|
|
+ "Duplicate extension " + type.getName() + " name "
|
|
|
|
+ + n + " on "
|
|
|
|
+ + c.getName() + " and "
|
|
|
|
+ + clazz.getName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -479,7 +509,12 @@ public class ExtensionLoader<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Throwable t) {
|
|
} catch (Throwable t) {
|
|
- IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
|
|
|
|
|
|
+ IllegalStateException e = new IllegalStateException(
|
|
|
|
+ "Failed to load extension class(interface: " + type + ", class line: "
|
|
|
|
+ + line + ") in " + url
|
|
|
|
+ + ", cause: "
|
|
|
|
+ + t.getMessage(),
|
|
|
|
+ t);
|
|
exceptions.put(line, e);
|
|
exceptions.put(line, e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -490,18 +525,19 @@ public class ExtensionLoader<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Throwable t) {
|
|
} catch (Throwable t) {
|
|
- logger.error("Exception when load extension class(interface: " +
|
|
|
|
- type + ", class file: " + url + ") in " + url, t);
|
|
|
|
|
|
+ logger.error("Exception when load extension class(interface: " + type + ", class file: " + url
|
|
|
|
+ + ") in " + url,
|
|
|
|
+ t);
|
|
}
|
|
}
|
|
} // end of while urls
|
|
} // end of while urls
|
|
}
|
|
}
|
|
} catch (Throwable t) {
|
|
} catch (Throwable t) {
|
|
- logger.error("Exception when load extension class(interface: " +
|
|
|
|
- type + ", description file: " + fileName + ").", t);
|
|
|
|
|
|
+ logger.error(
|
|
|
|
+ "Exception when load extension class(interface: " + type + ", description file: " + fileName + ").",
|
|
|
|
+ t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
private static ClassLoader findClassLoader() {
|
|
private static ClassLoader findClassLoader() {
|
|
return ExtensionLoader.class.getClassLoader();
|
|
return ExtensionLoader.class.getClassLoader();
|
|
}
|
|
}
|