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

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