📄 pluginloader.java
字号:
/* Copyright (C) 2003 Adam Olsen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */package com.valhalla.pluginmanager;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.util.ArrayList;import java.util.Hashtable;import java.util.Properties;import java.util.jar.JarEntry;import com.valhalla.settings.Settings;/** * This class supports the loading of custom plugins from jar files. The main * class in the Jar should be named after the jar filename and should be in the * "package" String passed to the PluginLoader package. For example, the plugin * LookAndFeel would be in a jar file called LookAndFeel.jar, and if the package * parameter was com.valhalla.jbother.plugins there would need to be a class * called <code>com.valhalla.jbother.plugins.LookAndFeel</code> in the jar * file * * @author Adam Olsen * @version 1.0 */public class PluginLoader extends ClassLoader { private static PluginLoader instance = null; private static int pluginAPIVersion = 91213; private String pluginDir = null; private Hashtable loadedClasses = new Hashtable(); // contains information // about what classes // have // already been loaded private static ArrayList availablePlugins = new ArrayList(); // the list of // available // plugins private static ArrayList invalidPlugins = new ArrayList(); private static ArrayList incompatiblePlugins = new ArrayList(); private static ArrayList installedPlugins = new ArrayList(); private static Hashtable loadedPlugins = new Hashtable(); /** * The default constructor * * @param pluginDir * the directory to search for plugins in .jar format */ private PluginLoader() { } /** * Gets the singleton of this class * * @return the PluginLoader singleton */ public static PluginLoader getInstance() { if (instance == null) instance = new PluginLoader(); return instance; } public static PluginLoader getNewInstance() { instance = new PluginLoader(); return instance; } /** * Finds which plugin contains the specified native library, extracts it to * a temporary location, and returns the path to that location or null if * the native library could not be found. * * @param the * name of the library * @return the location of the newly created temporary file */ public String findLibrary(String lib) { String l = super.findLibrary(lib); if (l != null) return l; PluginJAR jar = getPluginThatContains("native/" + lib); if (jar == null) return null; try { JarEntry entry = jar.getJarEntry("native/" + lib); int index = lib.lastIndexOf('.'); String suffix = lib.substring(index, lib.length()); lib = lib.substring(0, index); File temporaryDll = File.createTempFile(lib, suffix); InputStream inputStream = jar.getInputStream(entry); FileOutputStream outputStream = new FileOutputStream(temporaryDll); byte[] array = new byte[8192]; for (int i = inputStream.read(array); i != -1; i = inputStream .read(array)) { outputStream.write(array, 0, i); } outputStream.close(); temporaryDll.deleteOnExit(); com.valhalla.Logger.debug(temporaryDll.getPath()); return temporaryDll.getPath(); } catch (Exception ex) { com.valhalla.Logger.logException(ex); return null; } } /** * @return a list of currently loaded plugins */ public Hashtable getLoadedPlugins() { return loadedPlugins; } /** * @return a list of available plugins */ public ArrayList getAvailablePlugins() { return availablePlugins; } /** * @return a list of installed plugins */ public ArrayList getInstalledPlugins() { return installedPlugins; } /** * @return a list of invalid plugins */ public ArrayList getInvalidPlugins() { return invalidPlugins; } /** * @return a list of incompatible plugins */ public ArrayList getIncompatiblePlugins() { return incompatiblePlugins; } /** * Returns the jar file for the specified plugin name * * @param name * the plugin name * @return the jar file corresponding to the name */ public PluginJAR getPlugin(String name) { PluginJAR jar = null; for (int i = 0; i < availablePlugins.size(); i++) { PluginJAR temp = (PluginJAR) availablePlugins.get(i); if (temp.getName().equals(name)) jar = temp; } return jar; } /** * Returns the PluginJAR that contains <tt>file</tt> * * @param file * the file to search for * @return the PluginJAR that contains <tt>file</tt> */ private PluginJAR getPluginThatContains(String file) { PluginJAR jar = null; for (int i = 0; i < availablePlugins.size(); i++) { PluginJAR temp = (PluginJAR) availablePlugins.get(i); if (temp.contains(file)) jar = temp; } return jar; } /** * Returns the plugin that is represented by location * * @param location * the location of the plugin * @return the PluginJAR representing the specified location */ private PluginJAR getPluginFromLocation(String location) { PluginJAR jar = null; for (int i = 0; i < availablePlugins.size(); i++) { PluginJAR temp = (PluginJAR) availablePlugins.get(i); if (temp.getLocation().equals(location)) jar = temp; } return jar; } /** * Gets the current plugin API version * * @return the current plugin API version */ public static int getAPIVersion() { return pluginAPIVersion; } /** * Attempts to load the available plugins */ public void loadPlugins() { for (int i = 0; i < availablePlugins.size(); i++) { PluginJAR jar = (PluginJAR) availablePlugins.get(i); if (!jar.getLoaded()) { try { jar.loadPlugin(); } catch (Exception e) { com.valhalla.Logger.logException(e); } } else { com.valhalla.Logger.debug("Plugin is already loaded."); } } } /** * Reads in all the available plugins and the information about them */ public void findPlugins(String d) { this.pluginDir = d; String files[] = null; File pluginDir = null; installedPlugins.clear(); ArrayList newAvailable = new ArrayList(); invalidPlugins.clear(); incompatiblePlugins.clear(); try { // open up the plugin directory pluginDir = new File(this.pluginDir); if (!pluginDir.isDirectory()) return; files = pluginDir.list(); } catch (Exception exception) { return; } boolean ignoreIncompatible = Settings.getInstance().getBoolean("ignoreIncompatiblePlugins"); for (int i = 0; i < files.length; i++) { // if it's a jar file, it might be a plugin if (files[i].endsWith(".jar")) { try { PluginJAR jar = null; String loc = pluginDir.getPath() + File.separatorChar + files[i]; jar = getPluginFromLocation(loc); if (jar == null || !jar.getLoaded()) { jar = new PluginJAR(pluginDir.getPath() + File.separatorChar + files[i]); } Properties props = jar.getProperties(); String name = props.getProperty("name"); if (props == null || props.getProperty("mainClass") == null || name == null) invalidPlugins.add(files[i]); else if (ignoreIncompatible && !checkPlatform (props)) { incompatiblePlugins.add(name); com.valhalla.Logger.debug("Incompatible plugin found: " + name + " (" + files[i] + ")"); } else { int version = Integer.parseInt(props .getProperty("APIVersion")); if (version != pluginAPIVersion) { invalidPlugins.add(name); } else { newAvailable.add(jar); } installedPlugins.add(props); } } catch (Exception ex) { com.valhalla.Logger.debug("Invalid plugin found: " + files[i]); } } } availablePlugins = newAvailable; } /** * Gets a resource as a stream * * @param resource * the resource to get * @return the stream */ public InputStream getResourceAsStream(String resource) { InputStream stream = null; stream = this.getClass().getClassLoader().getResourceAsStream(resource); if (stream != null) return stream; PluginJAR jar = getPluginThatContains(resource); if (jar != null) { // find the entry in the Jar file JarEntry entry = jar.getJarEntry(resource); stream = jar.getInputStream(entry); } else { com.valhalla.Logger.debug("Stream was null for " + resource); } return stream; } protected Hashtable getLoadedClasses() { return loadedClasses; } /** * Loads the Class out of the plugin file * * @param className * the class name to load * @param resolveIt * true to resolve the class (load dependancies) * @return the Class if it was found * @throws <code>ClassNotFoundException</code> if the class could not be * found in the system or any of the plugin files */ public synchronized Class loadClass(String className, boolean resolveIt) throws ClassNotFoundException { Class result = null; String origName = className; // if the Class was already loaded, return it result = (Class) loadedClasses.get(origName); if (result != null) return result; // check to see if it's a system class try { result = this.getClass().getClassLoader().loadClass(className); //result = super.findSystemClass( className ); return result; } catch (ClassNotFoundException exception) { } className = className.replaceAll("\\.", "/"); className += ".class"; // if the class name starts with "java", we will not load it // because of the security risks involved. A class in the package // java. or javax. will be able to access protected members of system // Classes, and this isn't good. if (className.startsWith("java")) throw new ClassNotFoundException(); PluginJAR jar = getPluginThatContains(className); if (jar == null) throw new ClassNotFoundException(); try { // find the entry in the Jar file JarEntry entry = jar.getJarEntry(className); InputStream stream = jar.getInputStream(entry); // read it into a class int len = (int) entry.getSize(); int offset = 0; int success = 0; byte[] contents = new byte[len]; while (success < len) { len -= success; offset += success; success = stream.read(contents, offset, len); if (success == -1) throw new ClassNotFoundException(); } stream.read(contents, 0, (int) entry.getSize()); // actually define the class result = defineClass(origName, contents, 0, contents.length); if (resolveIt) resolveClass(result); // mark this class as already loaded and put it in the cache loadedClasses.put(origName, result); return result; } catch (Exception e) { throw new ClassNotFoundException(className); } } /** * Checks whether the current platform (OS name and architecture) is * compatible with the given plugin's platform or not. * * @param pluginProps plugin properties * @return true if the plugin is compatible and false otherwise */ static boolean checkPlatform (Properties pluginProps) { // @todo it may be worth to introduce 'os.match' and 'arch.match' // plugin properties to perform more flexible regexp match String os = pluginProps.getProperty("os"); String arch = pluginProps.getProperty("arch"); boolean ok = os == null || os.equals("all") || System.getProperty("os.name").startsWith(os); if (ok) { ok = arch == null || arch.equals("all") || System.getProperty("os.arch").equals(arch); } return ok; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -