/** * */ package jframe.core.plugin.loader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jframe.core.conf.Config; import jframe.core.conf.ConfigConstants; import jframe.core.plugin.Plugin; import jframe.core.plugin.loader.ext.PluginServiceCreator; import jframe.core.util.FileUtil; /** * @author dzh * @date Sep 30, 2013 10:54:35 AM * @since 1.0 */ public class PluginCreator { private static final Logger LOG = LoggerFactory.getLogger(PluginCreator.class); public static final String FILE_PLUGIN = "META-INF/plugin.properties"; protected Config _config; protected PluginCreator(Config config) { this._config = config; } protected PluginClassLoaderContext context; public static final PluginCreator newCreator(Config config, PluginClassLoaderContext context) { PluginCreator pc = new PluginServiceCreator(config); pc.context = context; return pc; } public String getRootCachePath() { return _config.getConfig(Config.APP_CACHE); } /** * * @param plugin * file * @return */ public PluginCase loadPlugin(File plugin) { JarFile jar = null; PluginCase pc = null; try { jar = new JarFile(plugin); if (!isValidPlugin(jar)) { jar.close(); return null; } Properties p = new Properties(); InputStream is = null; try { is = jar.getInputStream(jar.getJarEntry(FILE_PLUGIN)); p.load(is); } catch (Exception e) { LOG.error(e.getMessage()); return null; } finally { if (is != null) is.close(); } if (isForbidden(p.getProperty(PluginCase.P_PLUGIN_NAME))) { LOG.info("Forbid plugin: " + p.getProperty(PluginCase.P_PLUGIN_NAME)); return null; } pc = new PluginCase(); pc.setPluginName(p.getProperty(PluginCase.P_PLUGIN_NAME)); LOG.info("Loading plugin " + p.getProperty(PluginCase.P_PLUGIN_NAME)); pc.setJarPath(plugin.getAbsolutePath()); pc.setCachePath(getRootCachePath() + File.separator + pc.getPluginName()); File cache = new File(pc.getCachePath()); // init cache folder if (!cache.exists()) cache.mkdirs(); if (p.getProperty(PluginCase.P_PLUGIN_CLASS) != null) { pc.setPluginClass(p.getProperty(PluginCase.P_PLUGIN_CLASS)); } // TODO support * if (p.getProperty(PluginCase.P_PLUGIN_DLL) != null) { File dll = new File(cache, PluginCase.DLL); if (!dll.exists()) dll.mkdirs(); List<String> dlls = new LinkedList<String>(); for (String d : p.getProperty(PluginCase.P_PLUGIN_DLL, "").split("\\s+")) { String name = FileUtil.getLastName(d); FileUtil.copyJarEntry(jar, d, dll.getAbsolutePath() + File.separator + name, false); dlls.add(name); } if (dlls.size() > 0) pc.setPluginDll(dlls); } if (p.getProperty(PluginCase.P_PLUGIN_LIB) != null) { File lib = new File(cache, PluginCase.LIB); if (!lib.exists()) lib.mkdirs(); List<String> libs = new LinkedList<String>(); for (String d : p.getProperty(PluginCase.P_PLUGIN_LIB, "").split("\\s+")) { String name = FileUtil.getLastName(d); FileUtil.copyJarEntry(jar, d, lib.getAbsolutePath() + File.separator + name, false); libs.add(name); } if (libs.size() > 0) pc.setPluginLib(libs); } loadPlugin(pc, p); } catch (IOException e) { LOG.error("Jar IO is error." + e.getMessage()); return null; } finally { if (jar != null) { try { jar.close(); } catch (IOException e) { LOG.warn("Plugin jar close error: " + e.getLocalizedMessage()); } } } return pc; } protected void loadPlugin(PluginCase pc, Properties p) { // parse import-plugin if (p.getProperty(PluginCase.P_IMPORT_PLUGIN) != null) { pc.setImportPlugin(parseList(p.getProperty(PluginCase.P_IMPORT_PLUGIN))); } if (p.getProperty(PluginCase.P_IMPORT_CLASS) != null) { pc.setImportClass(parseList(p.getProperty(PluginCase.P_IMPORT_CLASS))); } if (p.getProperty(PluginCase.P_EXPORT_CLASS) != null) { pc.setExportClass(parseList(p.getProperty(PluginCase.P_EXPORT_CLASS))); } } protected List<String> parseList(String pValue) { if (pValue == null || "".equals(pValue)) return Collections.emptyList(); return Arrays.asList(pValue.split("\\s+")); } /** * * @param pc * @return Plugin or Null */ public Plugin createPlugin(PluginClassLoader pcl, PluginCase pc) { if (pcl == null || pc == null) return null; return pcl.createPlugin(pc); } public PluginClassLoader createPluginClassLoader(PluginCase pc) { PluginClassLoader pcl = new PluginClassLoader(pc, context); return pcl; } /** * * @param jar * @return whether jar is a valid plugin or not */ public boolean isValidPlugin(JarFile jar) { JarEntry je = jar.getJarEntry(FILE_PLUGIN); // if (je == null) return false; InputStream is = null; try { is = jar.getInputStream(je); Properties p = new Properties(); p.load(is); if (p.getProperty(PluginCase.P_PLUGIN_CLASS) == null || p.getProperty(PluginCase.P_PLUGIN_NAME) == null) { return false; } } catch (IOException e) { LOG.error(e.getMessage()); } finally { if (is != null) try { is.close(); } catch (IOException e) { LOG.warn(e.getMessage()); } } return true; } /** * 判断一个插件是否被进制 * * @param pluginName * @return */ public boolean isForbidden(String pluginName) { String[] plugins = _config.getConfig(ConfigConstants.PLUGIN_FORBID, "").split(" "); return Arrays.asList(plugins).contains(pluginName); } /** * */ public void close() { _config = null; } }