1 52 53 package com.go.trove.util; 54 55 import java.io.OutputStream ; 56 import java.io.ByteArrayOutputStream ; 57 import java.io.ByteArrayInputStream ; 58 import java.io.File ; 59 import java.io.InputStream ; 60 import java.io.FileInputStream ; 61 import java.io.IOException ; 62 import java.lang.ref.*; 63 import java.net.URL ; 64 import java.net.URLConnection ; 65 import java.net.URLStreamHandler ; 66 import java.util.*; 67 import java.util.zip.GZIPInputStream ; 68 import java.util.zip.GZIPOutputStream ; 69 70 81 public class ClassInjector extends ClassLoader { 82 private static Map cShared = new NullKeyMap(new IdentityMap()); 83 84 87 public static ClassInjector getInstance() { 88 return getInstance(null); 89 } 90 91 94 public static ClassInjector getInstance(ClassLoader loader) { 95 ClassInjector injector = null; 96 97 synchronized (cShared) { 98 Reference ref = (Reference)cShared.get(loader); 99 if (ref != null) { 100 injector = (ClassInjector)ref.get(); 101 } 102 if (injector == null) { 103 injector = new ClassInjector(loader); 104 cShared.put(loader, new WeakReference(injector)); 105 } 106 return injector; 107 } 108 } 109 110 private ClassLoader mSuperLoader; 112 113 private File [] mRootClassDirs; 114 private String mRootPackage; 115 116 private Map mDefined = Collections.synchronizedMap(new HashMap()); 118 119 private Map mGZippedBytecode; 121 122 private URLStreamHandler mFaker; 123 124 128 public ClassInjector() { 129 this(null, (File [])null, null); 130 } 131 132 139 public ClassInjector(ClassLoader parent) { 140 this(parent, (File [])null, null); 141 } 142 143 150 public ClassInjector(File rootClassDir, String rootPackage) { 151 this(null, (rootClassDir == null) ? null : new File []{rootClassDir}, 152 rootPackage); 153 } 154 155 161 public ClassInjector(ClassLoader parent, 162 File rootClassDir, String rootPackage) { 163 this(parent, (rootClassDir == null) ? null : new File []{rootClassDir}, 164 rootPackage); 165 } 166 167 175 public ClassInjector(File [] rootClassDirs, String rootPackage) { 176 this(null, rootClassDirs, rootPackage); 177 } 178 179 186 public ClassInjector(ClassLoader parent, 187 File [] rootClassDirs, 188 String rootPackage) { 189 this(parent, rootClassDirs, rootPackage, false); 190 } 191 192 201 public ClassInjector(ClassLoader parent, 202 File [] rootClassDirs, 203 String rootPackage, 204 boolean keepRawBytecode) { 205 super(); 206 if (parent == null) { 207 parent = getClass().getClassLoader(); 208 } 209 mSuperLoader = parent; 210 if (rootClassDirs != null) { 211 mRootClassDirs = (File [])rootClassDirs.clone(); 212 } 213 if (rootPackage != null && !rootPackage.endsWith(".")) { 214 rootPackage += '.'; 215 } 216 mRootPackage = rootPackage; 217 218 if (keepRawBytecode) { 219 mGZippedBytecode = Collections.synchronizedMap(new HashMap()); 220 } 221 } 222 223 229 public OutputStream getStream(String name) { 230 return new Stream (name); 231 } 232 233 public URL getResource(String name) { 234 235 if (mGZippedBytecode != null) { 236 if (mGZippedBytecode.containsKey(name)) { 237 try { 238 return new URL ("file", null, -1, name, getURLFaker()); 239 } 240 catch (Exception e) { 241 e.printStackTrace(); 242 } 243 System.out.println("created URL for " + name); 244 } 245 } 246 return mSuperLoader.getResource(name); 247 } 248 249 private URLStreamHandler getURLFaker() { 250 if (mFaker == null) { 251 mFaker = new URLFaker(); 252 } 253 return mFaker; 254 } 255 256 protected Class loadClass(String name, boolean resolve) 257 throws ClassNotFoundException { 258 259 Class clazz = findLoadedClass(name); 260 261 if (clazz == null) { 262 synchronized (this) { 263 clazz = findLoadedClass(name); 264 265 if (clazz == null) { 266 clazz = loadFromFile(name); 267 268 if (clazz == null) { 269 if (mSuperLoader != null) { 270 clazz = mSuperLoader.loadClass(name); 271 } 272 else { 273 clazz = findSystemClass(name); 274 } 275 276 if (clazz == null) { 277 throw new ClassNotFoundException (name); 278 } 279 } 280 } 281 } 282 } 283 284 if (resolve) { 285 resolveClass(clazz); 286 } 287 288 return clazz; 289 } 290 291 protected void define(String name, byte[] data) { 292 defineClass(name, data, 0, data.length); 293 if (mGZippedBytecode != null) { 294 try { 295 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 296 GZIPOutputStream gz = new GZIPOutputStream (baos); 297 gz.write(data,0,data.length); 298 gz.close(); 299 mGZippedBytecode.put(name.replace('.','/') + ".class", 300 baos.toByteArray()); 301 } 302 catch (IOException ioe) { 303 ioe.printStackTrace(); 304 } 305 } 306 } 307 308 private Class loadFromFile(String name) throws ClassNotFoundException { 309 if (mRootClassDirs == null) { 310 return null; 311 } 312 313 String fileName = name; 314 315 if (mRootPackage != null) { 316 if (fileName.startsWith(mRootPackage)) { 317 fileName = fileName.substring(mRootPackage.length()); 318 } 319 else { 320 return null; 321 } 322 } 323 324 fileName = fileName.replace('.', File.separatorChar); 325 ClassNotFoundException error = null; 326 327 for (int i=0; i<mRootClassDirs.length; i++) { 328 File file = new File (mRootClassDirs[i], fileName + ".class"); 329 330 if (file.exists()) { 331 try { 332 byte[] buffer = new byte[(int)file.length()]; 333 int avail = buffer.length; 334 int offset = 0; 335 InputStream in = new FileInputStream (file); 336 337 int len = -1; 338 while ( (len = in.read(buffer, offset, avail)) > 0 ) { 339 offset += len; 340 341 if ( (avail -= len) <= 0 ) { 342 avail = buffer.length; 343 byte[] newBuffer = new byte[avail * 2]; 344 System.arraycopy(buffer, 0, newBuffer, 0, avail); 345 buffer = newBuffer; 346 } 347 } 348 349 in.close(); 350 351 return defineClass(name, buffer, 0, offset); 352 } 353 catch (IOException e) { 354 if (error == null) { 355 error = new ClassNotFoundException  356 (fileName + ": " + e.toString()); 357 } 358 } 359 } 360 } 361 362 if (error != null) { 363 throw error; 364 } 365 else { 366 return null; 367 } 368 } 369 370 private class Stream extends ByteArrayOutputStream { 371 private String mName; 372 373 public Stream(String name) { 374 super(1024); 375 mName = name; 376 } 377 378 public void close() { 379 synchronized (mDefined) { 380 if (mDefined.get(mName) == null) { 381 define(mName, toByteArray()); 382 mDefined.put(mName, mName); 383 } 384 } 385 } 386 } 387 388 private class URLFaker extends URLStreamHandler { 389 390 protected URLConnection openConnection(URL u) throws IOException { 391 return new ClassInjector.ResourceConnection(u); 392 } 393 } 394 395 private class ResourceConnection extends URLConnection { 396 397 String resourceName; 398 public ResourceConnection(URL u) { 399 super(u); 400 resourceName = u.getFile(); 401 } 402 403 public void connect() {} 405 406 public InputStream getInputStream() throws IOException { 407 408 try { 409 if (mGZippedBytecode != null) { 410 411 if (mGZippedBytecode.get(resourceName) != null) { 412 return new GZIPInputStream (new ByteArrayInputStream  413 ((byte[])mGZippedBytecode.get(resourceName))); 414 } 415 else { 416 System.out.println(resourceName + " not found in bytecode map."); 417 } 418 } 419 else { 420 System.out.println("no bytecode map configured in "+ ClassInjector.this); 421 } 422 } 423 catch (Exception e) { 424 e.printStackTrace(); 425 } 426 427 return null; 428 } 429 } 430 } 431
| Popular Tags
|