File Source: PluginClassLoader.java

         /* 
    P/P   *  Method: com.dmdirc.plugins.PluginClassLoader__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.plugins;
    24  
    25  import com.dmdirc.util.resourcemanager.ResourceManager;
    26  
    27  import java.io.IOException;
    28  
    29  public class PluginClassLoader extends ClassLoader {
    30  	/** The plugin Info object for the plugin we are loading. */
    31  	final PluginInfo pluginInfo;
    32  	
    33  	/**
    34  	 * Create a new PluginClassLoader.
    35  	 *
    36  	 * @param info PluginInfo this classloader will be for
    37  	 */
    38  	public PluginClassLoader(final PluginInfo info) {
        		 /* 
    P/P 		  *  Method: void com.dmdirc.plugins.PluginClassLoader(PluginInfo)
        		  * 
        		  *  Postconditions:
        		  *    this.pluginInfo == info
        		  *    init'ed(this.pluginInfo)
        		  */
    39  		super();
    40  		pluginInfo = info;
    41  	}
    42  	
    43  	/**
    44  	 * Create a new PluginClassLoader.
    45  	 *
    46  	 * @param info PluginInfo this classloader will be for
    47  	 * @param parent Parent ClassLoader
    48  	 */
    49  	private PluginClassLoader(final PluginInfo info, final PluginClassLoader parent) {
        		 /* 
    P/P 		  *  Method: void com.dmdirc.plugins.PluginClassLoader(PluginInfo, PluginClassLoader)
        		  * 
        		  *  Postconditions:
        		  *    this.pluginInfo == info
        		  *    init'ed(this.pluginInfo)
        		  */
    50  		super(parent);
    51  		pluginInfo = info;
    52  	}
    53  	
    54  	/**
    55  	 * Get a PluginClassLoader that is a subclassloader of this one.
    56  	 *
    57       * @param info PluginInfo the new classloader will be for
    58       * @return A classloader configured with this one as its parent
    59  	 */
    60  	public PluginClassLoader getSubClassLoader(final PluginInfo info) {
        		 /* 
    P/P 		  *  Method: PluginClassLoader getSubClassLoader(PluginInfo)
        		  * 
        		  *  Postconditions:
        		  *    return_value == &new PluginClassLoader(getSubClassLoader#1)
        		  *    new PluginClassLoader(getSubClassLoader#1) num objects == 1
        		  *    return_value.pluginInfo == info
        		  *    init'ed(return_value.pluginInfo)
        		  */
    61  		return (new PluginClassLoader(info, this));
    62  	}
    63  	
    64  	/**
    65  	 * Load the plugin with the given className
    66  	 *
    67  	 * @param name Class Name of plugin
    68  	 * @return plugin class
    69  	 * @throws ClassNotFoundException if the class to be loaded could not be found.
    70  	 */
    71      @Override
    72  	public Class<?> loadClass(final String name) throws ClassNotFoundException {
        		 /* 
    P/P 		  *  Method: Class loadClass(String)
        		  * 
        		  *  Preconditions:
        		  *    (soft) com/dmdirc/plugins/GlobalClassLoader.me.resourcesList != null
        		  *    (soft) name != null
        		  *    (soft) com/dmdirc/plugins/GlobalClassLoader.me != null
        		  *    (soft) init'ed(this.pluginInfo.myResourceManager)
        		  *    (soft) this.pluginInfo != null
        		  *    (soft) init'ed(this.pluginInfo.metaData)
        		  *    (soft) this.pluginInfo.url != null
        		  * 
        		  *  Postconditions:
        		  *    init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
        		  *    init'ed(return_value)
        		  *    init'ed(this.pluginInfo.myResourceManager)
        		  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
        		  *    init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
        		  *    new HashMap(GlobalClassLoader#1) num objects == 0
        		  */
    73  		return loadClass(name, true);
    74  	}
    75  	
    76  	/**
    77  	 * Have we already loaded the given class name?
    78  	 *
    79  	 * @param name Name to check.
    80       * @param checkGlobal Should we check if the GCL has loaded it aswell?
    81       * @return True if the specified class is loaded, false otherwise
    82  	 */
    83  	public boolean isClassLoaded(final String name, final boolean checkGlobal) {
    84  		// Don't duplicate a class
        		 /* 
    P/P 		  *  Method: bool isClassLoaded(String, bool)
        		  * 
        		  *  Preconditions:
        		  *    (soft) init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
        		  * 
        		  *  Postconditions:
        		  *    com/dmdirc/plugins/GlobalClassLoader.me == One-of{old com/dmdirc/plugins/GlobalClassLoader.me, &amp;new GlobalClassLoader(getGlobalClassLoader#1)}
        		  *    init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
        		  *    init'ed(return_value)
        		  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects <= 1
        		  *    init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
        		  *    new HashMap(GlobalClassLoader#1) num objects <= 1
        		  */
    85  		final Class existing = findLoadedClass(name);
    86  		final boolean gcl = (checkGlobal) ? GlobalClassLoader.getGlobalClassLoader().isClassLoaded(name) : false;
    87  		return (existing != null || gcl);
    88  	}
    89  	
    90  	/**
    91  	 * Load the plugin with the given className
    92  	 *
    93  	 * @param name Class Name of plugin
    94  	 * @param askGlobal Ask the gobal class loaded for this class if we can't find it?
    95  	 * @return plugin class
    96  	 * @throws ClassNotFoundException if the class to be loaded could not be found.
    97  	 */
    98      @Override
    99  	public Class<?> loadClass(final String name, final boolean askGlobal) throws ClassNotFoundException {
        		 /* 
    P/P 		  *  Method: Class loadClass(String, bool)
        		  * 
        		  *  Preconditions:
        		  *    (soft) com/dmdirc/plugins/GlobalClassLoader.me.resourcesList != null
        		  *    (soft) name != null
        		  *    (soft) com/dmdirc/plugins/GlobalClassLoader.me != null
        		  *    (soft) init'ed(this.pluginInfo.myResourceManager)
        		  *    (soft) this.pluginInfo != null
        		  *    (soft) init'ed(this.pluginInfo.metaData)
        		  *    (soft) this.pluginInfo.url != null
        		  * 
        		  *  Presumptions:
        		  *    com.dmdirc.plugins.PluginClassLoader:defineClass(...)@156 != null
        		  *    com.dmdirc.plugins.PluginClassLoader:getParent(...).pluginInfo.url@103 != null
        		  *    com.dmdirc.plugins.PluginClassLoader:getParent(...).pluginInfo@103 != null
        		  *    com.dmdirc.plugins.PluginClassLoader:getParent(...)@103 != null
        		  *    com.dmdirc.util.resourcemanager.ResourceManager:getResourceBytes(...)@147 != null
        		  *    ...
        		  * 
        		  *  Postconditions:
        		  *    init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
        		  *    init'ed(return_value)
        		  *    init'ed(this.pluginInfo.myResourceManager)
        		  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects <= 1
        		  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
        		  *    init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
        		  *    possibly_updated(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
        		  *    new HashMap(GlobalClassLoader#1) num objects <= 1
        		  *    new HashMap(GlobalClassLoader#1) num objects == 0
        		  * 
        		  *  Test Vectors:
        		  *    askGlobal: {0}, {1}
        		  *    com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(...)@121: {1}, {0}
        		  */
   100  		Class< ? > loadedClass = null;
   101  		if (getParent() instanceof PluginClassLoader) {
   102  			try {
   103  				loadedClass = ((PluginClassLoader)getParent()).loadClass(name, false);
   104  				if (loadedClass != null) {
   105  					return loadedClass;
   106  				}
   107  			} catch (ClassNotFoundException cnfe) {
   108  				/* Parent doesn't have the class, load ourself */
   109  			}
   110  		}
   111  		
   112  		ResourceManager res;
   113  		try {
   114  			res = pluginInfo.getResourceManager();
   115  		} catch (IOException ioe) {
   116  			throw new ClassNotFoundException("Error with resourcemanager", ioe);
   117  		}
   118  	
   119  		final String fileName = name.replace('.', '/')+".class";
   120  		try {
   121  			if (pluginInfo.isPersistent(name) || !res.resourceExists(fileName)) {
   122  				if (!pluginInfo.isPersistent(name) && askGlobal) {
   123  					return GlobalClassLoader.getGlobalClassLoader().loadClass(name);
   124  				} else {
   125  					// Try to load class from previous load.
   126  					try {
   127  						if (askGlobal) {
   128  							return GlobalClassLoader.getGlobalClassLoader().loadClass(name, pluginInfo);
   129  						}
   130  					} catch (ClassNotFoundException e) {
   131  						/* Class doesn't exist, we load it ourself below */
   132  					}
   133  				}
   134  			}
   135  		} catch (NoClassDefFoundError e) {
   136  			throw new ClassNotFoundException("Error loading '"+name+"' (wanted by "+pluginInfo.getName()+") -> "+e.getMessage(), e);
   137  		}
   138  		
   139  		
   140  		// Don't duplicate a class
   141  		if (isClassLoaded(name, false)) { return findLoadedClass(name); }
   142  		
   143  		// We are ment to be loading this one!
   144  		byte[] data = null;
   145  		
   146  		if (res.resourceExists(fileName)) {
   147  			data = res.getResourceBytes(fileName);
   148  		} else {
   149  			throw new ClassNotFoundException("Resource '"+name+"' (wanted by "+pluginInfo.getName()+") does not exist.");
   150  		}
   151  		
   152  		try {
   153  			if (pluginInfo.isPersistent(name)) {
   154  				GlobalClassLoader.getGlobalClassLoader().defineClass(name, data);
   155  			} else {
   156  				loadedClass = defineClass(name, data, 0, data.length);
   157  			}
   158  		} catch (NoClassDefFoundError e) {
   159  			throw new ClassNotFoundException(e.getMessage(), e);
   160  		}
   161  		
   162  		if (loadedClass == null) {
   163  			throw new ClassNotFoundException("Could not load " + name);
   164  		} else {
   165  			resolveClass(loadedClass);
   166  		}
   167  		
   168  		return loadedClass;
   169  	}
   170  }








SofCheck Inspector Build Version : 2.17854
PluginClassLoader.java 2009-Jun-25 01:54:24
PluginClassLoader.class 2009-Sep-02 17:04:13