1 2 package org.quilt.cl; 3 4 import java.io.ByteArrayInputStream ; 5 import java.io.ByteArrayOutputStream ; 6 import java.io.File ; 7 import java.io.InputStream ; 8 import java.io.IOException ; 9 import java.lang.reflect.Constructor ; 10 import java.net.MalformedURLException ; 11 import java.net.URL ; 12 import java.net.URLClassLoader ; 13 import java.util.Hashtable ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 import java.util.Map ; 17 import java.util.Vector ; 18 19 import org.apache.bcel.classfile.ClassParser; 20 import org.apache.bcel.classfile.JavaClass; 21 22 import org.apache.bcel.classfile.Field; 24 import org.apache.bcel.classfile.Method; 25 27 import org.quilt.reg.QuiltRegistry; 28 29 49 public class QuiltClassLoader extends URLClassLoader { 50 51 52 public static final char FILE_PATH_DELIM_CHAR = File.separatorChar; 53 public static final String FILE_PATH_DELIM_STR = File.separator; 54 public static final char CLASSPATH_DELIM_CHAR = File.pathSeparatorChar; 55 public static final String CLASSPATH_DELIM_STR = File.pathSeparator; 56 57 62 public static final String [] DELEGATED = 63 {"java.", "javax.", "junit.", "org.apache.bcel.", 64 "org.apache.tools.ant.", "org.quilt.", "sun."}; 65 66 67 private String [] dels = DELEGATED; 68 69 private List delegated = new Vector (); 70 74 private List excluded = new Vector (); 75 76 82 private List included = new Vector (); 83 84 88 private List classPath = new Vector (); 89 90 94 private ClassLoader parent = null; 95 96 97 public static final String SYNTH_PREFIX = "test.data.Test"; 98 private String synthPrefix = SYNTH_PREFIX; 99 private boolean synthEnabled = false; 100 101 102 public ClassTransformer xformer = null; 103 104 List cxf = new Vector (); 105 106 List mxf = new Vector (); 107 108 List gxf = new Vector (); 109 110 List regList = new Vector (); 111 112 113 public QuiltClassLoader (URL [] cp, String [] inc) { 114 this(cp, null, null, inc, null); 115 } 116 125 public QuiltClassLoader (URL [] cp, ClassLoader parent, 126 String [] del, String [] inc, String [] exc) { 127 super(cp == null ? new URL [0] : cp, parent); 128 129 if (cp != null) { 130 for (int i = 0; i < cp.length; i++) { 131 classPath.add(cp[i]); 132 } 133 } 134 if (parent == null) { 135 this.parent = getSystemClassLoader(); 136 } else { 137 this.parent = parent; 138 } 139 for (int i = 0; i < dels.length; i++) { 140 delegated.add( dels[i] ); 141 } 142 if (del != null) { 143 for (int i = 0; i < del.length; i++ ) { 144 delegated.add(del[i]); 145 } 146 } 147 if (inc != null) { 148 for (int i = 0; i < inc.length; i++) { 149 included.add(inc[i]); 150 } 151 } 152 if (exc != null) { 153 for (int i = 0; i < exc.length; i++) { 154 excluded.add(exc[i]); 155 } 156 } 157 } 158 159 private boolean delegateTheClass (final String name) { 160 if (name.equals("org.quilt.QIC")) { 161 return false; 162 } 163 for (int i = 0; i < delegated.size(); i++) { 164 if (name.startsWith( (String )delegated.get(i)) ) { 165 return true; 166 } 167 } 168 return false; 169 } 170 171 private boolean instrumentTheClass (final String name) { 172 if (name.equals("org.quilt.QIC")) { 173 return false; 174 } 175 for (int i = 0; i < excluded.size(); i++) { 176 if ( name.startsWith ( (String )excluded.get(i) ) ) { 177 return false; 178 } 179 } 180 for (int i = 0; i < included.size(); i++) { 181 if ( name.startsWith ( (String )included.get(i) ) ) { 182 return true; 183 } 184 } 185 return false; 186 } 187 191 public static String classFileName (final String className) { 192 return className.replace('.', FILE_PATH_DELIM_CHAR) + ".class"; 193 } 194 200 public synchronized Class loadClass (String name) 201 throws ClassNotFoundException { 202 if (name == null) { 203 throw new IllegalArgumentException ("null class name"); 204 } 205 if (delegateTheClass(name)) { 206 return parent.loadClass(name); 210 } 211 Class c = findLoadedClass (name); 212 if (c != null) { 213 return c; 214 } 215 if (xformer == null) { 216 xformer = new ClassTransformer( cxf, mxf, gxf ); 217 } 218 return findClass (name); 219 } 220 229 protected Class findClass (String name) 230 throws ClassNotFoundException { 231 boolean instIt = instrumentTheClass(name) 234 && (cxf.size() > 0 || mxf.size() > 0 || gxf.size() > 0); 235 byte [] b = null; 236 if ( name.startsWith ( synthPrefix )) { 237 JavaClass jc = ClassFactory.getInstance() 238 .makeClass(name, classFileName(name)) 239 .getJavaClass(); 240 if (instIt) { 241 jc = xformer.xform(jc); 242 } 243 b = jc.getBytes(); } else { 245 try { 249 b = getClassData (name); 250 if (instIt) { 251 JavaClass jc = new ClassParser ( 257 new ByteArrayInputStream (b), classFileName(name) ) 258 .parse(); 259 JavaClass temp = xformer.xform (jc); 260 267 273 282 b = temp.getBytes(); 284 } 285 } catch (IOException e) { 286 e.printStackTrace(); throw new ClassNotFoundException (name, e); 288 } 289 } 290 291 return defineClass (name, b, 0, b.length); 293 } 294 295 public String urlsToString(){ 296 StringBuffer sb = new StringBuffer () .append("classpath:\n"); 297 URL [] urls = getURLs(); 298 for (int k = 0; k < urls.length; k++) { 299 sb.append(" ").append(k).append(" ") 300 .append(urls[k]).append("\n"); 301 } 302 return sb.toString(); 303 } 304 305 protected byte[] getClassData (String className) 306 throws IOException { 307 URL fileURL = findResource ( classFileName(className) ); 308 if (fileURL == null) { 310 System.err.println("QCL.getClassData mapping " + className 311 + " to " + classFileName(className) ); 312 System.err.println(" findResource returned null\n" 313 + urlsToString()); 314 } 315 if (fileURL == null) { 317 throw new IOException ("null fileURL for " + className); 319 } 320 InputStream ins = fileURL.openStream(); 321 ByteArrayOutputStream outs = new ByteArrayOutputStream (65536); 322 byte [] buffer = new byte [4096]; 323 int count; 324 while ( (count = ins.read(buffer)) != -1 ) { 325 outs.write(buffer, 0, count); 326 } 327 return outs.toByteArray(); 328 } 329 330 335 public void addPath (URL url) { 336 classPath.add(url); 337 } 338 339 public URL [] getClassPath() { 340 URL [] myURLs = new URL [ classPath.size() ]; 341 return (URL []) (classPath.toArray(myURLs)); 342 } 343 348 public static final String THIS_DIR = "." + FILE_PATH_DELIM_STR; 349 public static final String UP_DIR = ".." + FILE_PATH_DELIM_STR; 350 public static final int THIS_DIR_LEN = THIS_DIR.length(); 351 public static final int UP_DIR_LEN = UP_DIR.length(); 352 353 357 public static String domainToFileName (String name) { 358 int startNdx; 360 for (startNdx = 0; startNdx < name.length(); ) { 361 if ( name.substring(startNdx).startsWith(THIS_DIR)) { 362 startNdx += THIS_DIR_LEN; 363 } else if (name.substring(startNdx).startsWith(UP_DIR)) { 364 startNdx += UP_DIR_LEN; 365 } else { 366 break; 367 } 368 } 369 int endNdx; 371 if ( name.endsWith(".jar") ){ 372 endNdx = name.length() - 4; 373 } else { 374 endNdx = name.length(); 375 } 376 377 StringBuffer sb = new StringBuffer (); 378 if (startNdx > 0) { 379 sb.append(name.substring(0, startNdx)); 380 } 381 sb.append(name.substring(startNdx, endNdx) 382 .replace('.', FILE_PATH_DELIM_CHAR)); 383 if (endNdx != name.length()) { 384 sb.append(".jar"); 385 } 386 return sb.toString(); 387 } 388 391 public static URL [] cpToURLs (String cp ) { 392 URL [] urls; 393 if (cp == null) { 394 urls = new URL [0]; 395 } else { 396 String [] elements = cp.split(":"); 397 List urlList = new Vector (); 398 int urlCount = 0; 399 for (int i = 0; i < elements.length; i++) { 400 String noDots = domainToFileName(elements[i]); 401 boolean foundJar = noDots.endsWith(".jar"); 402 File file = new File (noDots); 403 String urlForm = "file://" + file.getAbsolutePath(); 404 if (!foundJar && !urlForm.endsWith(FILE_PATH_DELIM_STR)) { 405 urlForm += FILE_PATH_DELIM_STR; 406 } 407 try { 408 URL candidate = new URL (urlForm); 409 urlCount++; urlList.add(candidate); 411 } catch (MalformedURLException e) { 412 System.err.println ("WARNING: ignoring malformed URL " 413 + urlForm); 414 } 415 } 416 urls = new URL [urlCount]; 417 for (int k = 0; k < urls.length; k++) { 418 urls[k] = (URL ) urlList.get(k); 419 } 420 } 421 return urls; 422 } 423 429 public void setClassPath (String cp) { 430 classPath.clear(); 431 URL [] urls = cpToURLs(cp); 432 for (int i = 0; i < urls.length; i++) { 433 classPath.add(urls[i]); 434 addURL( urls[i] ); 435 } 436 } 444 449 public void addDelegated (final String prefix) { 450 delegated.add(prefix); 451 } 452 456 public String [] getDelegated() { 457 String [] myDels = new String [ delegated.size() ]; 458 return (String []) (delegated.toArray(myDels)); 459 } 460 461 467 public void addExcluded (final String prefix) { 468 excluded.add(prefix); 469 } 470 474 public String [] getExcluded() { 475 String [] myExc = new String [ excluded.size() ]; 476 return (String []) (excluded.toArray(myExc)); 477 } 478 483 public void setExcluded(String s) { 484 excluded.clear(); 485 if (s != null) { 486 String [] newExc = s.split(","); 487 for (int i = 0; i < newExc.length; i++) { 488 excluded.add ( newExc[i] ); 489 } 490 } 491 } 492 498 public void addIncluded (final String prefix) { 499 included.add(prefix); 500 } 501 505 public String [] getIncluded() { 506 String [] myInc = new String [ included.size() ]; 507 return (String []) (included.toArray(myInc)); 508 } 509 514 public void setIncluded(String s) { 515 included.clear(); 516 if (s != null) { 517 String [] newInc = s.split(","); 518 for (int i = 0; i < newInc.length; i++) { 519 included.add ( newInc[i] ); 520 } 521 } 522 } 523 524 public boolean getSynthEnabled() { 525 return synthEnabled; 526 } 527 528 public void setSynthEnabled (boolean b) { 529 synthEnabled = b; 530 } 531 532 535 public String getSynthPrefix() { 536 return synthPrefix; 537 } 538 539 public void addClassXformer( ClassXformer xf) { 540 cxf.add (xf); 541 } 542 543 public void addMethodXformer (MethodXformer xf) { 544 mxf.add (xf); 545 } 546 547 public void addGraphXformer (GraphXformer xf) { 548 gxf.add (xf); 549 } 550 551 552 public Map regMap = new Hashtable (); 553 554 555 public QuiltRegistry getRegistry (String regName) { 556 QuiltRegistry qr = null; 557 if (regMap.containsKey(regName)) { 558 qr = (QuiltRegistry) regMap.get (regName); 559 } 560 return qr; 561 } 562 568 public QuiltRegistry addQuiltRegistry (String regName) { 569 QuiltRegistry qr = null; 570 if (regMap.containsKey(regName)) { 571 qr = (QuiltRegistry) regMap.get(regName); 572 } else try { 573 Class o = Class.forName(regName, false, parent); 574 Constructor con = o.getConstructor( new Class [] { 575 QuiltClassLoader.class }); 576 qr = (QuiltRegistry)con.newInstance(new Object [] {this}); 577 regList.add(qr); 578 regMap.put (regName, qr); 579 } catch (Exception e) { 580 System.out.println ( 581 "\nQuiltClassLoader.addQuiltRegistry:" 582 + "\n EXCEPTION while trying to add " + regName 583 + "\n Is it on the parent's CLASSPATH?" 584 + "\n Exception: " + e); 585 } 586 return qr; 587 } 588 592 public String getReport() { 593 StringBuffer sb = new StringBuffer (); 594 if (!regList.isEmpty()) { 595 Iterator i = regList.iterator(); 596 while (i.hasNext()) { 597 QuiltRegistry reg = (QuiltRegistry)i.next(); 598 sb.append(reg.getReport()); 599 } 600 } 601 return sb.toString(); 602 } 603 } 604 | Popular Tags |