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

com.zusmart.basic.extension.ExtensionLoader Maven / Gradle / Ivy

Go to download

基础模块,提供配置,日志,SPI,图排序,路径匹配,资源扫描,包扫描,常用工具类

There is a newer version: 0.0.3
Show newest version
package com.zusmart.basic.extension;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.zusmart.basic.logging.Logger;
import com.zusmart.basic.logging.LoggerFactory;
import com.zusmart.basic.toolkit.AnnotationUtils;
import com.zusmart.basic.toolkit.ClassUtils;
import com.zusmart.basic.toolkit.GenericUtils;
import com.zusmart.basic.toolkit.StringUtils;

/**
 * 参考Dubbo实现的SPI机制,部分代码进行调整
 * 
 * @author Administrator
 *
 * @param 
 *            扩展点接口对象
 */
public class ExtensionLoader {

	private static final String PATH_SERVICES = "META-INF/services/";
	private static final String PATH_INTERNAL = "META-INF/internal/";
	private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
	private static final ConcurrentMap, ExtensionLoader> LOADERS = new ConcurrentHashMap, ExtensionLoader>();

	private static class Holder {
		private volatile H value;

		private H get() {
			return this.value;
		}

		private void set(H value) {
			this.value = value;
		}
	}

	private static ClassLoader getClassLoader() {
		return ClassUtils.getClassLoader(ExtensionLoader.class);
	}

	private static void assertExtension(Class type) {
		if (null == type) {
			throw new IllegalArgumentException("extension type must not be null");
		}
		if (!type.isInterface()) {
			throw new IllegalArgumentException(String.format("extension type is not interface (%s)", type));
		}
		if (!AnnotationUtils.hasAnnotation(type, Extension.class)) {
			throw new IllegalArgumentException(String.format("extension type missing @Extension annotation (%s)", type));
		}
	}

	public static  ExtensionLoader getExtensionLoader(Class type) {
		assertExtension(type);
		ExtensionLoader loader = GenericUtils.parse(LOADERS.get(type));
		if (null == loader) {
			LOADERS.putIfAbsent(type, new ExtensionLoader(type));
			loader = GenericUtils.parse(LOADERS.get(type));
		}
		return loader;
	}

	public static  E getExtension(Class type, String name) {
		ExtensionLoader loader = getExtensionLoader(type);
		return loader.getExtension(name);
	}

	public static  E getDefaultExtension(Class type) {
		ExtensionLoader loader = getExtensionLoader(type);
		return loader.getDefaultExtension();
	}

	private final String name;
	private final Class type;
	private final ExtensionScope scope;
	private final Holder>> cacheClasses = new Holder>>();
	private final ConcurrentMap> cachedData = new ConcurrentHashMap>();

	private ExtensionLoader(Class type) {
		assertExtension(type);
		Extension extension = type.getAnnotation(Extension.class);
		this.name = extension.value();
		this.type = type;
		this.scope = extension.scope();
	}

	/**
	 * 获取指定名称的扩展点对象
	 * 
	 * @param name
	 *            扩展点名称
	 * @return 扩展点对象
	 */
	public T getExtension(String name) {
		if (StringUtils.isBlank(name)) {
			throw new IllegalArgumentException("extension name must not be blank");
		}
		Holder holder = this.cachedData.get(name);
		if (null == holder) {
			this.cachedData.putIfAbsent(name, new Holder());
			holder = this.cachedData.get(name);
		}
		if (this.scope == ExtensionScope.Singleton) {
			Object instance = holder.get();
			if (null == instance) {
				synchronized (holder) {
					instance = holder.get();
					if (null == instance) {
						instance = this.createExtension(name);
						holder.set(instance);
					}
				}
			}
			return GenericUtils.parse(instance);
		} else {
			return GenericUtils.parse(this.createExtension(name));
		}
	}

	/**
	 * 获取默认名称的扩展点对象,可能为空
	 * 
	 * @return 扩展点对象
	 */
	public T getDefaultExtension() {
		if (StringUtils.isBlank(this.name)) {
			return null;
		}
		return this.getExtension(this.name);
	}

	private Object createExtension(String name) {
		Class clazz = this.getExtensionClasses().get(name);
		if (null == clazz) {
			throw new IllegalStateException(String.format("can not find extension (interface : %s , name : %s)", this.type, name));
		}
		try {
			T instance = GenericUtils.parse(clazz.newInstance());
			this.injectExtension(instance);
			return instance;
		} catch (Throwable t) {
			throw new IllegalStateException(String.format("create instance failed (interface : %s ,name : %s , class : %s)", this.type, name, clazz));
		}
	}

	private void injectExtension(Object instance) {

	}

	private Map> getExtensionClasses() {
		Map> classes = this.cacheClasses.get();
		if (null == classes) {
			synchronized (this.cacheClasses) {
				classes = this.cacheClasses.get();
				if (null == classes) {
					classes = this.loadExtensionClasses();
					this.cacheClasses.set(classes);
				}
			}
		}
		return classes;
	}

	private Map> loadExtensionClasses() {
		Map> classes = new HashMap>();
		this.loadDirectory(classes, PATH_SERVICES);
		this.loadDirectory(classes, PATH_INTERNAL);
		return classes;
	}

	private void loadDirectory(Map> classes, String path) {
		String fileName = path + this.type.getName();
		try {
			Enumeration urls = null;
			ClassLoader classLoader = getClassLoader();
			if (null != classLoader) {
				urls = classLoader.getResources(fileName);
			} else {
				urls = ClassLoader.getSystemResources(fileName);
			}
			if (null != urls) {
				while (urls.hasMoreElements()) {
					URL url = urls.nextElement();
					this.loadResource(classes, classLoader, url);
				}
			}
		} catch (Throwable t) {
			logger.error("load extension class failed (interface : {} , file : {})", this.type, fileName, t);
		}
	}

	private void loadResource(Map> classes, ClassLoader classLoader, URL url) {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
			try {
				String line = null;
				while ((line = reader.readLine()) != null) {
					final int ci = line.indexOf("#");
					if (ci >= 0) {
						line = line.substring(0, ci);
					}
					line = line.trim();
					if (line.length() > 0) {
						try {
							String name = null;
							int i = line.indexOf("=");
							if (i > 0) {
								name = line.substring(0, i).trim();
								line = line.substring(i + 1).trim();
							} else {
								name = line;
							}
							Class clazz = Class.forName(line);
							if (clazz.isAnnotationPresent(ExtensionService.class)) {
								ExtensionService service = clazz.getAnnotation(ExtensionService.class);
								if (StringUtils.isNotBlank(service.value())) {
									name = service.value();
								}
							}
							classes.put(name, Class.forName(line));
							logger.debug("load extension class success (interface : {} , path : {} , line : {} , name : {})", this.type, url, line, name);
						} catch (Throwable tt) {
							logger.error("load extension class failed (interface : {} , path : {} , line : {})", this.type, url, line, tt);
						}
					}
				}
			} finally {
				reader.close();
			}
		} catch (Throwable t) {
			logger.error("load extension class failed (interface : {} , path : {})", this.type, url, t);
		}
	}

}