1 18 19 package alt.jiapi.util; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.net.JarURLConnection ; 24 import java.net.MalformedURLException ; 25 import java.net.URL ; 26 import java.net.URLClassLoader ; 27 import java.security.CodeSource ; 28 import java.security.cert.Certificate ; 29 import java.util.Collections ; 30 import java.util.ArrayList ; 31 import java.util.HashMap ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.StringTokenizer ; 35 36 import org.apache.log4j.Category; 37 38 import alt.jiapi.InstrumentationContext; 39 import alt.jiapi.Runtime; 40 import alt.jiapi.reflect.JiapiClass; 41 import alt.jiapi.JiapiException; 42 43 54 public class InstrumentingClassLoader extends URLClassLoader { 55 private static Category log = Runtime.getLogCategory(InstrumentingClassLoader.class); 56 57 protected Map classes; 58 protected InstrumentationContext ctx; 59 60 63 public static ClassLoader createClassLoader() { 64 return createClassLoader((InstrumentationContext)null); 65 } 66 67 70 public static ClassLoader createClassLoader(InstrumentationContextProvider icp) throws JiapiException { 71 return createClassLoader(icp.getInstrumentationContext()); 72 } 73 74 77 public static ClassLoader createClassLoader(InstrumentationContextProvider icp, ClassLoader parent) throws JiapiException { 78 return createClassLoader(icp.getInstrumentationContext(), parent); 79 } 80 81 84 public static ClassLoader createClassLoader(InstrumentationContext ctx) { 85 return createClassLoader(ctx, getSystemClassLoader()); 86 } 87 88 91 public static ClassLoader createClassLoader(InstrumentationContext ctx, 92 ClassLoader parent) { 93 URL urls[] = getClassPathUrls(); 94 SecurityManager sm = System.getSecurityManager(); 95 if (sm != null) { 96 sm.checkCreateClassLoader(); 97 } 98 99 101 return new InstrumentingClassLoader(ctx, urls, parent); 102 } 103 104 protected InstrumentingClassLoader(InstrumentationContext ctx, URL [] urls, 105 ClassLoader parent) { 106 super(urls, parent); 107 this.ctx = ctx; 108 109 classes = Collections.synchronizedMap(new HashMap ()); 110 } 111 112 protected synchronized Class loadClass(String className, boolean resolve) 113 throws ClassNotFoundException { 114 116 Class cl = null; 117 JiapiClass jiapiClass = null; 118 log.debug("loadClass(" + className + ")"); 119 121 if (className.startsWith("java.") || className.startsWith("javax.") || 124 className.startsWith("sun.") || className.startsWith("alt.jiapi.")) { 125 return getParent().loadClass(className); 128 } 129 130 if ((cl = (Class ) classes.get(className)) == null) { 131 log.debug("cache miss: " + className); 132 SecurityManager sm = System.getSecurityManager(); 134 if (sm != null) { 135 int i = className.lastIndexOf('.'); 136 if (i != -1) { 137 sm.checkPackageAccess(className.substring(0, i)); 138 } 139 } 140 141 if (ctx == null) { 142 return bootstrap(className); 143 } 144 145 String path = className.replace('.', '/').concat(".class"); 147 URL location = super.findResource(path); 148 149 if (location == null) { 150 152 return getParent().loadClass(className); 153 } 154 155 try { 156 jiapiClass = ctx.getLoader().loadClass(className, location); 157 } 158 catch(java.io.IOException ioe) { 159 throw new ClassNotFoundException (className); 160 } 161 162 ctx.instrument(jiapiClass); 163 164 byte[] bytes = jiapiClass.getByteCode(); 165 166 if (System.getProperty("dump") != null) { 167 try { 168 jiapiClass.dump(new java.io.FileOutputStream (jiapiClass.getName() + ".dump")); 169 } 170 catch(Throwable t) { 171 } 172 } 173 174 if (bytes != null) { 175 CodeSource cs = createCodeSource(location); 176 cl = defineClass(className, bytes, 0, bytes.length, cs); 177 } 178 179 log.debug(cl + " was loaded with " + cl.getClassLoader()); 180 181 classes.put(className, cl); 186 } 187 188 if (resolve) { 189 resolveClass(cl); 190 } 191 192 return cl; 193 } 194 195 200 protected CodeSource createCodeSource(URL location) { 201 Certificate []certs = null; 202 if (location.getProtocol().equals("jar")) { 203 try { 204 JarURLConnection jarConnection = 205 (JarURLConnection ) location.openConnection(); 206 207 certs = jarConnection.getCertificates(); 208 location = jarConnection.getJarFileURL(); 209 } catch (IOException ioe) { 210 ioe.printStackTrace(); 211 throw new RuntimeException (ioe.getMessage()); 212 } 213 } 214 215 return new CodeSource (location, certs); 216 } 217 218 219 222 private static URL []getClassPathUrls() { 223 String string = System.getProperty("java.class.path"); 224 List urls = new ArrayList (); 225 if (string != null) { 226 StringTokenizer st = new StringTokenizer (string, 227 File.pathSeparator); 228 229 while (st.hasMoreTokens()) { 230 try { 231 urls.add((new File (st.nextToken())).toURL()); 232 } catch (IOException ioe) { 233 } 236 } 237 } 238 239 return ((URL []) urls.toArray(new URL [0])); 240 } 241 242 247 public void setContext(InstrumentationContext ctx) { 248 this.ctx = ctx; 249 } 250 251 public Class bootstrap(String className) throws ClassNotFoundException { 253 String s = className.replace('.', '/') + ".class"; 254 255 return findClass(s); 256 } 257 258 byte [] byteBuffer = new byte[65000]; 260 public Class findClass(String name) throws ClassNotFoundException { 261 log.debug("findClass(" + name + ")"); 262 Class c = null; 263 try { 265 URL url = findResource(name); 266 if (url == null) { 267 throw new ClassNotFoundException (name); 268 } 269 270 java.io.InputStream is = url.openStream(); 271 int count = 0; 272 while (is.available() > 0) { 273 int elemsRead = is.read(byteBuffer, count, is.available()); 274 if (elemsRead == -1) { 275 break; 276 } 277 count += elemsRead; 278 } 279 280 c = defineClass(name.substring(0, name.lastIndexOf('.')), 281 byteBuffer, 0, count); 282 } 283 catch (java.io.IOException e) { 284 e.printStackTrace(); 285 throw new ClassNotFoundException (name); 286 } 287 288 classes.put(c.getName(), c); 289 return c; 290 } 291 } 292 293 | Popular Tags |