
com.jcute.basic.extension.ExtensionLoader Maven / Gradle / Ivy
The newest version!
package com.jcute.basic.extension;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import com.jcute.basic.extension.annotation.Extension;
import com.jcute.basic.extension.annotation.ExtensionName;
import com.jcute.basic.util.StringUtil;
/**
* 扩展点服务加载器
*
* @author koko
*
*/
public class ExtensionLoader{
// 默认搜索配置文件的路径
private static final String D_SERVICES = "META-INF/services/";
private static final String D_INTERNAL = "META-INF/internal/";
// 缓存不同类型的扩展点loader
private static final ConcurrentHashMap> loaders = new ConcurrentHashMap>();
private final Class> targetType;
private final String targetName;
private final ExtensionScope targetScope;
private final ConcurrentHashMap> targetClasses = new ConcurrentHashMap>();
private final ConcurrentHashMap targetInstances = new ConcurrentHashMap();
private ExtensionLoader(Class> type){
Extension extension = type.getAnnotation(Extension.class);
this.targetType = type;
this.targetName = StringUtil.isBlank(extension.name()) ? null : extension.name();
this.targetScope = extension.scope();
this.doRefresh();
}
public T getService(String name){
String targetName = name;
if(StringUtil.isBlank(targetName)){
targetName = this.targetName;
}
if(StringUtil.isBlank(targetName)){
return null;
}
Class type = this.targetClasses.get(targetName);
if(null == type){
return null;
}
if(this.targetScope == ExtensionScope.Prototype){
return this.doCreateInstance(type);
}
T result = this.targetInstances.get(targetName);
if(null == result){
result = this.doCreateInstance(type);
if(null == result){
return null;
}
this.targetInstances.put(targetName,result);
}
return result;
}
@SuppressWarnings("unchecked")
public static ExtensionLoader getExtensionLoader(Class type){
if(null == type){
throw new IllegalArgumentException("extension type must not be null");
}
if(!type.isInterface()){
throw new IllegalArgumentException("extension type must interface");
}
Extension extension = type.getAnnotation(Extension.class);
if(null == extension){
throw new IllegalArgumentException("extension type missing @Extension annotation");
}
String name = type.getName();
if(!loaders.containsKey(name)){
loaders.put(name,new ExtensionLoader(type));
}
return (ExtensionLoader)loaders.get(name);
}
public static E getService(Class type,String name){
ExtensionLoader extensionLoader = getExtensionLoader(type);
if(null == extensionLoader){
throw new NullPointerException("extension loader not found");
}
return extensionLoader.getService(name);
}
public static E getService(Class type){
return getService(type,null);
}
private T doCreateInstance(Class type){
try{
return type.newInstance();
}catch(Throwable t){
t.printStackTrace();
}
return null;
}
private void doRefresh(){
Map> classes = new HashMap>();
this.doLoadClass(D_SERVICES,classes);
this.doLoadClass(D_INTERNAL,classes);
this.targetClasses.putAll(classes);
}
private void doLoadClass(String path,Map> classes){
try{
ClassLoader classLoader = ExtensionLoader.class.getClassLoader();
String loadPath = String.format("%s%s",path,this.targetType.getName());
Enumeration urls = null;
if(null == classLoader){
urls = ClassLoader.getSystemResources(loadPath);
}else{
urls = classLoader.getResources(loadPath);
}
if(null == urls){
return;
}
while(urls.hasMoreElements()){
URL url = urls.nextElement();
Map mapping = this.doReadFile(url);
if(null == mapping || mapping.isEmpty()){
continue;
}
for(Entry entry : mapping.entrySet()){
Class type = this.doClassForName(entry.getValue());
if(null == type){
continue;
}
String name = entry.getKey();
if(null != type.getAnnotation(ExtensionName.class)){
name = type.getAnnotation(ExtensionName.class).name();
}
classes.put(name,type);
}
}
}catch(Throwable t){}
}
@SuppressWarnings("unchecked")
private Class doClassForName(String className){
try{
Class> result = Class.forName(className);
if(this.targetType.isAssignableFrom(result)){
return (Class)result;
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private Map doReadFile(URL url){
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
Map result = new HashMap();
try{
inputStream = url.openStream();
inputStreamReader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
String line = null;
while((line = bufferedReader.readLine()) != null){
if(StringUtil.isBlank(line)){
continue;
}
String path = line.trim();
int index = path.indexOf("=");
String name = null;
String type = line;
if(index > 0){
name = path.substring(0,index);
type = path.substring(index+1);
if(StringUtil.isBlank(type)){
continue;
}
if(StringUtil.isBlank(name)){
name = type;
}
}else{
name = type = path;
}
result.put(name,type);
}
}catch(Throwable t){
}finally{
if(null != bufferedReader){
try{
bufferedReader.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(null != inputStreamReader){
try{
inputStreamReader.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(null != inputStream){
try{
inputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy