File Source: GlobalClassLoader.java

         /* 
    P/P   *  Method: com.dmdirc.plugins.GlobalClassLoader__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  import java.util.HashMap;
    29  import java.util.List;
    30  import java.util.Map;
    31  
    32  /**
    33   * This classloader knows about plugins and is used to store persistent classes.
    34   */
    35  public final class GlobalClassLoader extends ClassLoader {
    36  
    37  	/** Singleton instance of the GlobalClassLoader. */
    38  	private static GlobalClassLoader me;
    39  	
    40  	/** HashMap containing sources of Global class files. */
    41  	private Map<String,String> resourcesList = new HashMap<String,String>();
    42  
    43  	/**
    44  	 * Create a new GlobalClassLoader.
    45  	 */
    46  	private GlobalClassLoader() {
        		 /* 
    P/P 		  *  Method: void com.dmdirc.plugins.GlobalClassLoader()
        		  * 
        		  *  Postconditions:
        		  *    this.resourcesList == &amp;new HashMap(GlobalClassLoader#1)
        		  *    new HashMap(GlobalClassLoader#1) num objects == 1
        		  */
    47  		super();
    48  	}
    49  	
    50  	/**
    51  	 * Have we already loaded the given class name?
    52  	 *
    53  	 * @param name Name to check.
    54       * @return True if the class is loaded, false otherwise
    55  	 */
    56  	public boolean isClassLoaded(final String name) {
    57  		// Don't duplicate a class
        		 /* 
    P/P 		  *  Method: bool isClassLoaded(String)
        		  * 
        		  *  Postconditions:
        		  *    init'ed(return_value)
        		  */
    58  		final Class existing = findLoadedClass(name);
    59  		return existing != null;
    60  	}
    61  	
    62  	/**
    63  	 * Retrieves the singleton instance of the GlobalClassLoader.
    64  	 *
    65  	 * @return A singleton instance of GlobalClassLoader.
    66  	 */
    67  	public static final synchronized GlobalClassLoader getGlobalClassLoader() {
        		 /* 
    P/P 		  *  Method: GlobalClassLoader getGlobalClassLoader()
        		  * 
        		  *  Preconditions:
        		  *    init'ed(me)
        		  * 
        		  *  Postconditions:
        		  *    me == One-of{old me, &amp;new GlobalClassLoader(getGlobalClassLoader#1)}
        		  *    me != null
        		  *    return_value == me
        		  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects <= 1
        		  *    new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == &amp;new HashMap(GlobalClassLoader#1)
        		  *    new HashMap(GlobalClassLoader#1) num objects <= 1
        		  * 
        		  *  Test Vectors:
        		  *    me: Inverse{null}, Addr_Set{null}
        		  */
    68  		if (me == null) {
    69  			me = new GlobalClassLoader();
    70  		}
    71  		
    72  		return me;
    73  	}
    74  
    75  	/**
    76  	 * Load the plugin with the given className.
    77  	 *
    78  	 * @param name Class Name of plugin
    79  	 * @param pi The PluginInfo that contains this class
    80  	 * @return plugin class
    81  	 * @throws ClassNotFoundException if the class to be loaded could not be found.
    82  	 */
    83  	public Class<?> loadClass(final String name, final PluginInfo pi) throws ClassNotFoundException {
        		 /* 
    P/P 		  *  Method: Class loadClass(String, PluginInfo)
        		  * 
        		  *  Preconditions:
        		  *    pi != null
        		  *    init'ed(pi.metaData)
        		  *    (soft) pi.url != null
        		  *    (soft) this.resourcesList != null
        		  * 
        		  *  Postconditions:
        		  *    possibly_updated(pi.myResourceManager)
        		  *    init'ed(return_value)
        		  * 
        		  *  Test Vectors:
        		  *    java.util.Iterator:hasNext(...)@84: {0}, {1}
        		  *    java.util.Map:containsKey(...)@85: {1}, {0}
        		  */
    84  		for (String classname : pi.getPersistentClasses()) {
    85  			if (!resourcesList.containsKey(classname)) {
    86  				resourcesList.put(classname, pi.getFullFilename());
    87  			}
    88  		}
    89  		return loadClass(name);
    90  	}
    91  	
    92  	/**
    93  	 * Load the plugin with the given className.
    94  	 *
    95  	 * @param name Class Name of plugin
    96  	 * @return plugin class
    97  	 * @throws ClassNotFoundException if the class to be loaded could not be found.
    98  	 */
    99      @Override
   100  	public Class<?> loadClass(final String name) throws ClassNotFoundException {
   101  		try {
        			 /* 
    P/P 			  *  Method: Class loadClass(String)
        			  * 
        			  *  Preconditions:
        			  *    (soft) name != null
        			  *    (soft) init'ed(com/dmdirc/plugins/PluginManager.me)
        			  *    (soft) me != null
        			  *    (soft) this.resourcesList != null
        			  * 
        			  *  Presumptions:
        			  *    data.length <= 232-1
        			  *    getPluginClassLoader(...).pluginInfo.url@111 != null
        			  *    getPluginClassLoader(...).pluginInfo@111 != null
        			  *    getPluginManager(...).knownPlugins != null
        			  *    java.util.Iterator:next(...)@111 != null
        			  *    ...
        			  * 
        			  *  Postconditions:
        			  *    com/dmdirc/plugins/PluginManager.me == One-of{old com/dmdirc/plugins/PluginManager.me, &amp;new PluginManager(getPluginManager#1)}
        			  *    init'ed(com/dmdirc/plugins/PluginManager.me)
        			  *    java.lang.StringBuilder:toString(...)._tainted == 0
        			  *    init'ed(me)
        			  *    init'ed(return_value)
        			  *    new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
        			  *    init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
        			  *    new HashMap(GlobalClassLoader#1) num objects == 0
        			  *    new HashMap(PluginManager#2) num objects <= 1
        			  *    new Hashtable(PluginManager#1) num objects <= 1
        			  *    ...
        			  */
   102  			return super.loadClass(name);
   103  		} catch (ClassNotFoundException e) {
   104  			byte[] data = getClassData(name);
   105  			if (data != null) {
   106  				return defineClass(name, data);
   107  			}
   108  		}
   109  		
   110  		// Check the other plugins.
   111  		for (PluginInfo pi : PluginManager.getPluginManager().getPluginInfos()) {
   112  			List<String> classList = pi.getClassList();
   113  			if (classList.contains(name)) {
   114  				if (pi.getPluginClassLoader() != null) {
   115  					return pi.getPluginClassLoader().loadClass(name, false);
   116  				}
   117  			}
   118  		}
   119  		
   120  		return null;
   121  	}
   122  	
   123  	/**
   124  	 * Look in all known sources of persisant classes for file asked for.
   125  	 *
   126  	 * @param classname Class name to define.
   127  	 * @param data Data to define class with.
   128  	 */
   129  	public Class<?> defineClass(final String classname, final byte[] data) {
        		 /* 
    P/P 		  *  Method: Class defineClass(String, byte[])
        		  * 
        		  *  Preconditions:
        		  *    data != null
        		  *    data.length <= 232-1
        		  * 
        		  *  Postconditions:
        		  *    init'ed(return_value)
        		  */
   130  		return defineClass(classname, data, 0, data.length);
   131  	}
   132  	
   133  	/**
   134  	 * Get the requested class from its plugin jar.
   135  	 *
   136  	 * @param classname Class to look for.
   137  	 */
   138  	private byte[] getClassData(final String classname) {
   139  		try {
        			 /* 
    P/P 			  *  Method: byte[] getClassData(String)
        			  * 
        			  *  Preconditions:
        			  *    (soft) classname != null
        			  *    (soft) this.resourcesList != null
        			  * 
        			  *  Presumptions:
        			  *    com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager(...)@142 != null
        			  * 
        			  *  Postconditions:
        			  *    init'ed(return_value)
        			  */
   140  			final String jarname = resourcesList.get(classname);
   141  			if (jarname != null) {
   142  				ResourceManager rm = ResourceManager.getResourceManager("jar://"+jarname);
   143  				final String filename = classname.replace('.', '/')+".class";
   144  				if (rm.resourceExists(filename)) {
   145  					return rm.getResourceBytes(filename);
   146  				}
   147  			}
   148  		} catch (IOException e) {
   149  			// File might have been deleted, oh well.
   150  		}
   151  		return null;
   152  	}
   153  	
   154  }








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