1 22 package org.jboss.mx.loading; 23 24 import java.io.ByteArrayOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.net.MalformedURLException ; 28 import java.net.URL ; 29 import java.net.URLClassLoader ; 30 import java.security.CodeSource ; 31 import java.security.PermissionCollection ; 32 import java.security.Policy ; 33 import java.security.ProtectionDomain ; 34 import java.security.cert.Certificate ; 35 import java.util.Enumeration ; 36 import java.util.HashSet ; 37 import java.util.Vector ; 38 import java.util.Collections ; 39 import java.util.Set ; 40 41 import javax.management.MalformedObjectNameException ; 42 import javax.management.ObjectName ; 43 44 import org.jboss.classloading.spi.ClassLoadingDomain; 45 import org.jboss.classloading.spi.DomainClassLoader; 46 import org.jboss.classloading.spi.Translator; 47 import org.jboss.logging.Logger; 48 import org.jboss.util.collection.SoftSet; 49 50 import EDU.oswego.cs.dl.util.concurrent.ReentrantLock; 51 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 52 53 63 public abstract class LegacyDomainClassLoader extends URLClassLoader 64 implements DomainClassLoader 65 { 66 68 69 private static final Logger log = Logger.getLogger(LegacyDomainClassLoader.class); 70 71 72 private static final URL [] EMPTY_URL_ARRAY = {}; 73 74 76 77 protected LoaderRepositoryDomain domain = null; 78 79 protected Exception unregisterTrace; 80 81 82 private int addedOrder; 83 84 85 protected ClassLoader parent = null; 86 87 88 private Set classBlackList = Collections.synchronizedSet(new SoftSet()); 89 90 private Set resourceBlackList = Collections.synchronizedSet(new HashSet ()); 91 92 private ConcurrentReaderHashMap resourceCache = new ConcurrentReaderHashMap(); 93 94 95 protected ReentrantLock loadLock = new ReentrantLock(); 96 97 98 protected int loadClassDepth; 99 100 102 104 110 protected LegacyDomainClassLoader(URL [] urls, ClassLoader parent) 111 { 112 super(urls, parent); 113 this.parent = parent; 114 String mode = ClassToStringAction.getProperty("org.jboss.mx.loading.blacklistMode", null); 116 if( mode == null || mode.equalsIgnoreCase("HashSet") ) 117 { 118 classBlackList = Collections.synchronizedSet(new HashSet ()); 119 resourceBlackList = Collections.synchronizedSet(new HashSet ()); 120 } 121 else if( mode.equalsIgnoreCase("SoftSet") ) 122 { 123 classBlackList = Collections.synchronizedSet(new SoftSet()); 124 resourceBlackList = Collections.synchronizedSet(new SoftSet()); 125 } 126 } 127 128 130 135 public abstract ObjectName getObjectName() throws MalformedObjectNameException ; 136 137 public ClassLoadingDomain getDomain() 138 { 139 return domain; 140 } 141 public void setDomain(ClassLoadingDomain domain) 142 { 143 log.debug("setDomain, domain="+domain+", cl=" + this); 144 this.domain = (LoaderRepositoryDomain) domain; 145 } 146 147 152 public int getAddedOrder() 153 { 154 return addedOrder; 155 } 156 157 162 public void setAddedOrder(int addedOrder) 163 { 164 this.addedOrder = addedOrder; 165 } 166 167 170 public Class loadClassLocally(String name, boolean resolve) 171 throws ClassNotFoundException 172 { 173 boolean trace = log.isTraceEnabled(); 174 if( trace ) 175 log.trace("loadClassLocally, " + this + " name=" + name); 176 Class result = null; 177 try 178 { 179 if (isClassBlackListed(name)) 180 { 181 if( trace ) 182 log.trace("Class in blacklist, name="+name); 183 throw new ClassNotFoundException ("Class Not Found(blacklist): " + name); 184 } 185 186 try 187 { 188 result = super.loadClass(name, resolve); 189 return result; 190 } 191 catch (ClassNotFoundException cnfe) 192 { 193 addToClassBlackList(name); 194 if( name.charAt(0) == '[' ) 196 { 197 result = Class.forName(name, true, this); 198 removeFromClassBlackList(name); 199 return result; 200 } 201 if( trace ) 202 log.trace("CFNE: Adding to blacklist: "+name); 203 throw cnfe; 204 } 205 } 206 finally 207 { 208 if (trace) 209 { 210 if (result != null) 211 log.trace("loadClassLocally, " + this + " name=" + name + " class=" + result + " cl=" + result.getClassLoader()); 212 else 213 log.trace("loadClassLocally, " + this + " name=" + name + " not found"); 214 } 215 } 216 } 217 218 221 public URL getResourceLocally(String name) 222 { 223 URL resURL = (URL ) resourceCache.get(name); 224 if (resURL != null) 225 return resURL; 226 if (isResourceBlackListed(name)) 227 return null; 228 resURL = super.getResource(name); 229 if( log.isTraceEnabled() == true ) 230 log.trace("getResourceLocally("+this+"), name="+name+", resURL:"+resURL); 231 if (resURL == null) 232 addToResourceBlackList(name); 233 else 234 resourceCache.put(name, resURL); 235 return resURL; 236 } 237 public URL loadResourceLocally(String name) 238 { 239 return getResourceLocally(name); 240 } 241 242 247 public URL getURL() 248 { 249 URL [] urls = super.getURLs(); 250 if (urls.length > 0) 251 return urls[0]; 252 else 253 return null; 254 } 255 256 public void unregister() 257 { 258 log.debug("Unregistering cl=" + this); 259 if (domain != null) 260 domain.removeClassLoader(this); 261 clearBlacklists(); 262 resourceCache.clear(); 263 domain = null; 264 this.unregisterTrace = new Exception (); 265 } 266 267 273 public URL [] getClasspath() 274 { 275 return super.getURLs(); 276 } 277 278 283 public void addToClassBlackList(String name) 284 { 285 classBlackList.add(name); 286 } 287 288 293 public void removeFromClassBlackList(String name) 294 { 295 classBlackList.remove(name); 296 } 297 298 304 public boolean isClassBlackListed(String name) 305 { 306 return classBlackList.contains(name); 307 } 308 309 312 public void clearClassBlackList() 313 { 314 classBlackList.clear(); 315 } 316 317 322 public void addToResourceBlackList(String name) 323 { 324 resourceBlackList.add(name); 325 } 326 327 332 public void removeFromResourceBlackList(String name) 333 { 334 resourceBlackList.remove(name); 335 } 336 337 343 public boolean isResourceBlackListed(String name) 344 { 345 return resourceBlackList.contains(name); 346 } 347 348 351 public void clearResourceBlackList() 352 { 353 resourceBlackList.clear(); 354 } 355 356 359 public void clearBlacklists() 360 { 361 clearClassBlackList(); 362 clearResourceBlackList(); 363 } 364 365 366 368 375 public Class loadClass(String name, boolean resolve) 376 throws ClassNotFoundException 377 { 378 boolean trace = log.isTraceEnabled(); 379 if (trace) 380 log.trace("loadClass " + this + " name=" + name+", loadClassDepth="+loadClassDepth); 381 Class clazz = null; 382 try 383 { 384 if (domain != null) 385 { 386 clazz = domain.getCachedClass(name); 387 if (clazz != null) 388 { 389 if( log.isTraceEnabled() ) 390 { 391 StringBuffer buffer = new StringBuffer ("Loaded class from cache, "); 392 ClassToStringAction.toString(clazz, buffer); 393 log.trace(buffer.toString()); 394 } 395 return clazz; 396 } 397 } 398 clazz = loadClassImpl(name, resolve, Integer.MAX_VALUE); 399 return clazz; 400 } 401 finally 402 { 403 if (trace) 404 { 405 if (clazz != null) 406 log.trace("loadClass " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader()); 407 else 408 log.trace("loadClass " + this + " name=" + name + " not found"); 409 } 410 } 411 } 412 413 420 public Class loadClassBefore(String name) 421 throws ClassNotFoundException 422 { 423 boolean trace = log.isTraceEnabled(); 424 if (trace) 425 log.trace("loadClassBefore " + this + " name=" + name); 426 Class clazz = null; 427 try 428 { 429 clazz = loadClassImpl(name, false, addedOrder); 430 return clazz; 431 } 432 finally 433 { 434 if (trace) 435 { 436 if (clazz != null) 437 log.trace("loadClassBefore " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader()); 438 else 439 log.trace("loadClassBefore " + this + " name=" + name + " not found"); 440 } 441 } 442 } 443 444 public abstract Class loadClassImpl(String name, boolean resolve, int stopAt) 445 throws ClassNotFoundException ; 446 447 451 public URL getResource(String name) 452 { 453 if (domain != null) 454 return domain.getResource(name, this); 455 return null; 456 } 457 458 465 public Enumeration <URL > findResources(String name) throws IOException 466 { 467 Vector <URL > resURLs = new Vector <URL >(); 468 if( domain == null ) 469 { 470 String msg = "Invalid use of destroyed classloader, UCL destroyed at:"; 471 IOException e = new IOException (msg); 472 e.initCause(this.unregisterTrace); 473 throw e; 474 } 475 domain.getResources(name, this, resURLs); 476 return resURLs.elements(); 477 } 478 479 482 public Enumeration findResourcesLocally(String name) throws IOException 483 { 484 return super.findResources(name); 485 } 486 487 494 protected Class findClass(String name) throws ClassNotFoundException 495 { 496 boolean trace = log.isTraceEnabled(); 497 if( trace ) 498 log.trace("findClass, name="+name); 499 if (isClassBlackListed(name)) 500 { 501 if( trace ) 502 log.trace("Class in blacklist, name="+name); 503 throw new ClassNotFoundException ("Class Not Found(blacklist): " + name); 504 } 505 506 Translator translator = domain.getTranslator(); 507 if (translator != null) 508 { 509 try 511 { 512 URL classUrl = getClassURL(name); 514 byte[] rawcode = loadByteCode(classUrl); 515 URL codeSourceUrl = getCodeSourceURL(name, classUrl); 516 ProtectionDomain pd = getProtectionDomain(codeSourceUrl); 517 byte[] bytecode = translator.transform(this, name, null, pd, rawcode); 518 if( bytecode == null ) 520 bytecode = rawcode; 521 definePackage(name); 523 return defineClass(name, bytecode, 0, bytecode.length, pd); 524 } 525 catch(ClassNotFoundException e) 526 { 527 throw e; 528 } 529 catch (Throwable ex) 530 { 531 throw new ClassNotFoundException (name, ex); 532 } 533 } 534 535 Class clazz = null; 536 try 537 { 538 clazz = findClassLocally(name); 539 } 540 catch(ClassNotFoundException e) 541 { 542 if( trace ) 543 log.trace("CFNE: Adding to blacklist: "+name); 544 addToClassBlackList(name); 545 throw e; 546 } 547 return clazz; 548 } 549 550 556 protected Class findClassLocally(String name) throws ClassNotFoundException 557 { 558 return super.findClass(name); 559 } 560 561 567 protected void definePackage(String className) 568 { 569 int i = className.lastIndexOf('.'); 570 if (i == -1) 571 return; 572 573 try 574 { 575 definePackage(className.substring(0, i), null, null, null, null, null, null, null); 576 } 577 catch (IllegalArgumentException alreadyDone) 578 { 579 } 580 } 581 582 585 public void addURL(URL url) 586 { 587 if( url == null ) 588 throw new IllegalArgumentException ("url cannot be null"); 589 590 if( domain.addClassLoaderURL(this, url) == true ) 591 { 592 log.debug("Added url: "+url+", to ucl: "+this); 593 String query = url.getQuery(); 595 if( query != null ) 596 { 597 String ext = url.toExternalForm(); 598 String ext2 = ext.substring(0, ext.length() - query.length() - 1); 599 try 600 { 601 url = new URL (ext2); 602 } 603 catch(MalformedURLException e) 604 { 605 log.warn("Failed to strip query from: "+url, e); 606 } 607 } 608 super.addURL(url); 609 clearBlacklists(); 610 } 611 else if( log.isTraceEnabled() ) 612 { 613 log.trace("Ignoring duplicate url: "+url+", for ucl: "+this); 614 } 615 } 616 617 public Package getPackage(String name) 618 { 619 return super.getPackage(name); 620 } 621 622 public Package [] getPackages() 623 { 624 return super.getPackages(); 625 } 626 627 629 635 public final boolean equals(Object other) 636 { 637 return super.equals(other); 638 } 639 640 646 public final int hashCode() 647 { 648 return super.hashCode(); 649 } 650 651 654 public String toString() 655 { 656 return super.toString() + "{ url=" + getURL() + " }"; 657 } 658 659 661 666 protected boolean attempt(long waitMS) 667 { 668 boolean acquired = false; 669 boolean trace = log.isTraceEnabled(); 670 boolean threadWasInterrupted = Thread.interrupted(); 672 try 673 { 674 acquired = loadLock.attempt(waitMS); 675 } 676 catch(InterruptedException e) 677 { 678 } 679 finally 680 { 681 if( threadWasInterrupted ) 683 Thread.currentThread().interrupt(); 684 } 685 if( trace ) 686 log.trace("attempt("+loadLock.holds()+") was: "+acquired+" for :"+this); 687 return acquired; 688 } 689 690 694 protected void acquire() 695 { 696 boolean threadWasInterrupted = Thread.interrupted(); 698 try 699 { 700 loadLock.acquire(); 701 } 702 catch(InterruptedException e) 703 { 704 } 705 finally 706 { 707 if( threadWasInterrupted ) 709 Thread.currentThread().interrupt(); 710 } 711 if( log.isTraceEnabled() ) 712 log.trace("acquired("+loadLock.holds()+") for :"+this); 713 } 714 717 protected void release() 718 { 719 if( log.isTraceEnabled() ) 720 log.trace("release("+loadLock.holds()+") for :"+this); 721 loadLock.release(); 722 if( log.isTraceEnabled() ) 723 log.trace("released, holds: "+loadLock.holds()); 724 } 725 726 734 protected byte[] loadByteCode(String classname) 735 throws ClassNotFoundException , IOException 736 { 737 byte[] bytecode = null; 738 URL classURL = getClassURL(classname); 739 740 InputStream is = null; 742 try 743 { 744 is = classURL.openStream(); 745 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 746 byte[] tmp = new byte[1024]; 747 int read = 0; 748 while( (read = is.read(tmp)) > 0 ) 749 { 750 baos.write(tmp, 0, read); 751 } 752 bytecode = baos.toByteArray(); 753 } 754 finally 755 { 756 if( is != null ) 757 is.close(); 758 } 759 760 return bytecode; 761 } 762 763 771 protected byte[] loadByteCode(URL classURL) 772 throws ClassNotFoundException , IOException 773 { 774 byte[] bytecode = null; 775 InputStream is = null; 777 try 778 { 779 is = classURL.openStream(); 780 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 781 byte[] tmp = new byte[1024]; 782 int read = 0; 783 while( (read = is.read(tmp)) > 0 ) 784 { 785 baos.write(tmp, 0, read); 786 } 787 bytecode = baos.toByteArray(); 788 } 789 finally 790 { 791 if( is != null ) 792 is.close(); 793 } 794 795 return bytecode; 796 } 797 798 804 protected ProtectionDomain getProtectionDomain(URL codesourceUrl) 805 { 806 Certificate certs[] = null; 807 CodeSource cs = new CodeSource (codesourceUrl, certs); 808 PermissionCollection permissions = Policy.getPolicy().getPermissions(cs); 809 if (log.isTraceEnabled()) 810 log.trace("getProtectionDomain, url=" + codesourceUrl + 811 " codeSource=" + cs + " permissions=" + permissions); 812 return new ProtectionDomain (cs, permissions); 813 } 814 815 817 819 private URL getCodeSourceURL(String classname, URL classURL) throws java.net.MalformedURLException 820 { 821 String classRsrcName = classname.replace('.', '/') + ".class"; 822 String urlAsString = classURL.toString(); 823 int idx = urlAsString.indexOf(classRsrcName); 824 if (idx == -1) return classURL; 825 urlAsString = urlAsString.substring(0, idx); 826 return new URL (urlAsString); 827 } 828 829 private URL getClassURL(String classname) throws ClassNotFoundException 830 { 831 String classRsrcName = classname.replace('.', '/') + ".class"; 832 URL classURL = this.getResourceLocally(classRsrcName); 833 if( classURL == null ) 834 { 835 String msg = "Failed to find: "+classname+" as resource: "+classRsrcName; 836 throw new ClassNotFoundException (msg); 837 } 838 return classURL; 839 } 840 841 } 843 | Popular Tags |