diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/net/java/games/util/Version.java | 104 | ||||
-rw-r--r-- | src/main/java/net/java/games/util/plugins/Plugin.java | 60 | ||||
-rw-r--r-- | src/main/java/net/java/games/util/plugins/PluginLoader.java | 169 | ||||
-rw-r--r-- | src/main/java/net/java/games/util/plugins/Plugins.java | 251 |
4 files changed, 584 insertions, 0 deletions
diff --git a/src/main/java/net/java/games/util/Version.java b/src/main/java/net/java/games/util/Version.java new file mode 100644 index 0000000..62bd4a1 --- /dev/null +++ b/src/main/java/net/java/games/util/Version.java @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* -Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* -Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* Neither the name of Sun Microsystems, Inc. or the names of contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS +* LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A +* RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. +* IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT +* OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR +* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, +* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS +* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for use in the +* design, construction, operation or maintenance of any nuclear facility. +*/ + +package net.java.games.util; + +/** + * The version and build number of this implementation. + * Version numbers for a release are of the form: w.x.y[-a]-z, where: + * <ul> + * <li> + * w - the major version number of the release. This number should + * start at 1. Typically, a bump in the major version number + * signifies that the release breaks backwards compatibility + * with some older release. + * </li> + * <li> + * x - minor version number. This number starts at 0. A bump in + * the minor version number signifies a release that has significant + * new functionality. + * </li> + * <li> + * y - minor-minor version number number. This number starts at 0. A + * bump in the minor-minor version number signifies that new bug + * fixes have been added to the build. + * </li> + * <li> + * a - an optional build designator followed by a digit. Valid build + * designators are: + * <ul> + * <li>alpha</li> + * <li>beta</li> + * </ul> + * </li> + * <li> + * z - build number. This is used to specify the build number of the + * release. This is usually only important to people that use + * the daily build of a project. The format is the lower-case + * letter 'b' followed by a two digit number. + * </li> + * </ul> + * + * For example, the following are all valid version strings: + * <ul> + * <li>1.1.2-b02</li> + * <li>1.3.5-alpha1-b19</li> + * <li>4.7.1-beta3-b20</li> + * </ul> + * + */ +public final class Version { + + /** + * Private constructor - no need for user to create + * an instance of this class. + */ + private Version() { + } + + /** + * Version string of this build. + */ + private static final String version = "1.0.0-b01"; + + /** + * Returns the verison string and build number of + * this implementation. See the class descritpion + * for the version string format. + * + * @return The version string of this implementation. + */ + public static String getVersion() { + return version; + } +} diff --git a/src/main/java/net/java/games/util/plugins/Plugin.java b/src/main/java/net/java/games/util/plugins/Plugin.java new file mode 100644 index 0000000..cfb533b --- /dev/null +++ b/src/main/java/net/java/games/util/plugins/Plugin.java @@ -0,0 +1,60 @@ +/* + * Plugin.java + * + * Created on April 18, 2003, 11:29 AM + */ + +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ + +package net.java.games.util.plugins; + +/** This is a marker interface used to mark plugins in a Jar file + * for retrieval by the Plugins class. In order for a class to be + * treated as a Plugin the following must be true: + * + * (1) The name of the class must end with "Plugin". + * (ie MedianCutFilterPlugin, DirectInput EnvrionmentPlugin) + * + * (2) The class must implement the Plugin interface. It can do + * so directly, through inheritence of either a superclass + * that implements this interface, or through the implementation + * of an interface that extends this interface. + * + * + * @author Jeffrey P. Kesselman + * + */ +public interface Plugin { + +} diff --git a/src/main/java/net/java/games/util/plugins/PluginLoader.java b/src/main/java/net/java/games/util/plugins/PluginLoader.java new file mode 100644 index 0000000..00545eb --- /dev/null +++ b/src/main/java/net/java/games/util/plugins/PluginLoader.java @@ -0,0 +1,169 @@ +/* + * PluginLodaer.java + * + * Created on April 18, 2003, 11:32 AM + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.util.plugins; + +/** + * + * @author jeff + */ +import java.io.*; +import java.net.*; + +/** This class is used internally by the Plugin system. + * End users of the system are unlikely to need to be aware + * of it. + * + * + * This is the class loader used to keep the namespaces of + * different plugins isolated from each other and from the + * main app code. One plugin loader is created per Jar + * file in the sub-directory tree of the plugin directory. + * + * In addition to isolating java classes this loader also isolates + * DLLs such that plugins with conflicting DLL names may be + * used by simply placing the plugin and its associated DLL + * in a sub-folder of its own. + * + * This class also currently implements methods for testing + * classes for inheritance of superclasses or interfaces. + * This code is genericly useful and should really be moved + * to a seperate ClassUtils class. + * @author Jeffrey Kesselman + */ +public class PluginLoader extends URLClassLoader { + static final boolean DEBUG = false; + File parentDir; + boolean localDLLs = true; + /** Creates a new instance of PluginLodaer + * If the system property "net.java.games.util.plugins.nolocalnative" is + * not set then the laoder will look for requried native libs in the + * same directory as the plugin jar. (Useful for handling name + * collision between plugins). If it IS set however, then it will + * fall back to the default way of loading natives. (Necessary for + * Java Web Start.) + * @param jf The JarFile to load the Plugins from. + * @throws MalformedURLException Will throw this exception if jf does not refer to a + * legitimate Jar file. + */ + public PluginLoader(File jf) throws MalformedURLException { + super(new URL[] {jf.toURL()}, + Thread.currentThread().getContextClassLoader()); + parentDir = jf.getParentFile(); + if (System.getProperty("net.java.games.util.plugins.nolocalnative") + !=null){ + localDLLs = false; + } + } + + /** This method is queried by the System.loadLibrary() + * code to find the actual native name and path to the + * native library to load. + * + * This subclass implementation of this method ensures that + * the native library will be loaded from, and only from, + * the parent directory of the Jar file this loader was + * created to support. This allows different Plugins + * with supporting DLLs of the same name to co-exist, each + * in their own subdirectory. + * + * Setting the global "localDLLs" by setting the property + * net.java.games.util.plugins.nolocalnative defeats this behavior. + * This is necessary for Java Web Start apps which have strong + * restrictions on where and how native libs can be loaded. + * + * @param libname The JNI name of the native library to locate. + * @return Returns a string describing the actual loation of the + * native library in the native file system. + */ + protected String findLibrary(String libname){ + if (localDLLs) { + String libpath = parentDir.getPath() + File.separator + + System.mapLibraryName(libname); + if (DEBUG) { + System.out.println("Returning libname of: " + libpath); + } + return libpath; + } else { + return super.findLibrary(libname); + } + } + + /** This function is called as part of scanning the Jar for + * plugins. It checks to make sure the class passed in is + * a legitimate plugin, which is to say that it meets + * the following criteria: + * + * (1) Is not itself an interface + * (2) Implements the Plugin marker interface either directly + * or through inheritance. + * + * interface, either + * @param pc The potential plug-in class to vette. + * @return Returns true if the class meets the criteria for a + * plugin. Otherwise returns false. + */ + public boolean attemptPluginDefine(Class pc){ + return ((!pc.isInterface()) && classImplementsPlugin(pc)); + } + + private boolean classImplementsPlugin(Class testClass){ + if (testClass == null) return false; // end of tree + if (DEBUG) { + System.out.println("testing class "+testClass.getName()); + } + Class[] implementedInterfaces = testClass.getInterfaces(); + for(int i=0;i<implementedInterfaces.length;i++){ + if (DEBUG) { + System.out.println("examining interface: "+implementedInterfaces[i]); + } + if (implementedInterfaces[i]==Plugin.class) { + if (DEBUG) { + System.out.println("returning true from classImplementsPlugin"); + } + return true; + } + } + for(int i=0;i<implementedInterfaces.length;i++){ + if (classImplementsPlugin(implementedInterfaces[i])){ + return true; + } + } + return classImplementsPlugin(testClass.getSuperclass()); + } + +} diff --git a/src/main/java/net/java/games/util/plugins/Plugins.java b/src/main/java/net/java/games/util/plugins/Plugins.java new file mode 100644 index 0000000..42f0837 --- /dev/null +++ b/src/main/java/net/java/games/util/plugins/Plugins.java @@ -0,0 +1,251 @@ +/* + * Plugins.java + * + * Created on April 18, 2003, 10:57 AM + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.util.plugins; + +/** + * + * @author jeff + */ + +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** This is the application interface to the Plugin system. + * One Plugins object should be created for each plug-in + * directory tree root. + * + * On creation the Plugins object will scan its assigned + * directory tree and examine all Jar files in that tree to + * see if they qualify as Plug-ins. + * + * The Plugin classes may then be retrived from the Plugins object by calling + * the appropriate get function (see below). + * + * If a plugin requires a native code library, that library must be present + * in the same directory as the plugin Jar file UNLESS the property + * "net.java.games.util.plugins.nolocalnative" is set. In that case + * it will fall abck to the VM or environment's default way of finding + * native libraries. (This is n ecessary for Java Web Start apps.) + * + */ +public class Plugins { + static final boolean DEBUG = true; + List pluginList= new ArrayList(); + + /** Creates a new instance of Plugins + * @param pluginRoot The root od the directory tree to scan for Jars + * containing plugins. + */ + public Plugins(File pluginRoot) throws IOException { + scanPlugins(pluginRoot); + } + + private void scanPlugins(File dir) throws IOException { + File[] files = dir.listFiles(); + if (files == null) { + throw new FileNotFoundException("Plugin directory "+dir.getName()+ + " not found."); + } + for(int i=0;i<files.length;i++){ + File f = files[i]; + if (f.getName().endsWith(".jar")) { // process JAR file + processJar(f); + } else if (f.isDirectory()) { + scanPlugins(f); // recurse + } + } + } + + + private void processJar(File f) { + try { + //JarFile jf = new JarFile(f); + if (DEBUG) { + System.out.println("Scanning jar: "+f.getName()); + } + PluginLoader loader = new PluginLoader(f); + JarFile jf = new JarFile(f); + for (Enumeration en = jf.entries();en.hasMoreElements();){ + JarEntry je = (JarEntry)en.nextElement(); + if (DEBUG) { + System.out.println("Examining file : "+je.getName()); + } + if (je.getName().endsWith("Plugin.class")) { + if (DEBUG) { + System.out.println("Found candidate class: "+je.getName()); + } + String cname = je.getName(); + cname = cname.substring(0,cname.length()-6); + cname = cname.replace('/','.'); // required by JDK1.5 + Class pc = loader.loadClass(cname); + if (loader.attemptPluginDefine(pc)) { + if (DEBUG) { + System.out.println("Adding class to plugins:"+pc.getName()); + } + pluginList.add(pc); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** This method returns all the Plugins found in the + * directory passed in at object creation time or any of its + * sub-directories. + * @return An array of Plugin objects + */ + public Class[] get(){ + Class[] pluginArray = new Class[pluginList.size()]; + return (Class[])pluginList.toArray(pluginArray); + } + + /** This method returns a sub-list of all the found Plugin + * classes that implement <B>any</B> of the passed in set of + * Interfaces (either directly or through inheritance.) + * @param interfaces A set of interfaces to match against the interfaces + * implemented by the plugin classes. + * @return The list of plugin classes that implement at least + * one member of the passed in set of interfaces. + */ + public Class[] getImplementsAny(Class[] interfaces){ + List matchList = new ArrayList(pluginList.size()); + Set interfaceSet = new HashSet(); + for(int i=0;i<interfaces.length;i++){ + interfaceSet.add(interfaces[i]); + } + for(Iterator i = pluginList.iterator();i.hasNext();){ + Class pluginClass = (Class)i.next(); + if (classImplementsAny(pluginClass,interfaceSet)){ + matchList.add(pluginClass); + } + } + Class[] pluginArray = new Class[matchList.size()]; + return (Class[])matchList.toArray(pluginArray); + } + + private boolean classImplementsAny(Class testClass,Set interfaces){ + if (testClass == null) return false; // end of tree + Class[] implementedInterfaces = testClass.getInterfaces(); + for(int i=0;i<implementedInterfaces.length;i++){ + if (interfaces.contains(implementedInterfaces[i])) { + return true; + } + } + for(int i=0;i<implementedInterfaces.length;i++){ + if (classImplementsAny(implementedInterfaces[i],interfaces)){ + return true; + } + } + return classImplementsAny(testClass.getSuperclass(),interfaces); + } + + /** This method returns a sub-list of all the found Plugin + * classes that implement <B>all</B> of the passed in set of + * Interfaces (either directly or through inheritance.) + * @param interfaces A set of interfaces to match against the interfaces + * implemented by the plugin classes. + * @return The list of plugin classes that implement at least + * one member of the passed in set of interfaces. + */ + public Class[] getImplementsAll(Class[] interfaces){ + List matchList = new ArrayList(pluginList.size()); + Set interfaceSet = new HashSet(); + for(int i=0;i<interfaces.length;i++){ + interfaceSet.add(interfaces[i]); + } + for(Iterator i = pluginList.iterator();i.hasNext();){ + Class pluginClass = (Class)i.next(); + if (classImplementsAll(pluginClass,interfaceSet)){ + matchList.add(pluginClass); + } + } + Class[] pluginArray = new Class[matchList.size()]; + return (Class[])matchList.toArray(pluginArray); + } + + private boolean classImplementsAll(Class testClass,Set interfaces){ + if (testClass == null) return false; // end of tree + Class[] implementedInterfaces = testClass.getInterfaces(); + for(int i=0;i<implementedInterfaces.length;i++){ + if (interfaces.contains(implementedInterfaces[i])) { + interfaces.remove(implementedInterfaces[i]); + if (interfaces.size() == 0) { // found them all + return true; + } + } + } + for(int i=0;i<implementedInterfaces.length;i++){ + if (classImplementsAll(implementedInterfaces[i],interfaces)){ + return true; + } + } + return classImplementsAll(testClass.getSuperclass(),interfaces); + } + + /** This method returns a sub-list of all the found Plugin + * classes that extend the passed in Class + * (either directly or through inheritance.) + * @param superclass The class to match. + * @return The list of plugin classes that extend the passed + * in class. + */ + public Class[] getExtends(Class superclass){ + List matchList = new ArrayList(pluginList.size()); + for(Iterator i = pluginList.iterator();i.hasNext();){ + Class pluginClass = (Class)i.next(); + if (classExtends(pluginClass,superclass)){ + matchList.add(pluginClass); + } + } + Class[] pluginArray = new Class[matchList.size()]; + return (Class[])matchList.toArray(pluginArray); + } + + private boolean classExtends(Class testClass,Class superclass){ + if (testClass == null) { // end of hirearchy + return false; + } + if (testClass == superclass) { + return true; + } + return classExtends(testClass.getSuperclass(),superclass); + } +} |