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 == &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, &new GlobalClassLoader(getGlobalClassLoader#1)}
* me != null
* return_value == me
* new GlobalClassLoader(getGlobalClassLoader#1) num objects <= 1
* new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == &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, &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 |