1 22 package org.jboss.mx.loading; 23 24 import java.io.BufferedReader ; 25 import java.io.File ; 26 import java.io.FileFilter ; 27 import java.io.FileInputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.InputStreamReader ; 31 import java.net.URL ; 32 import java.net.URLClassLoader ; 33 import java.util.ArrayList ; 34 import java.util.Arrays ; 35 import java.util.Comparator ; 36 import java.util.HashSet ; 37 import java.util.LinkedList ; 38 import java.util.Map ; 39 import java.util.Set ; 40 import java.util.TreeSet ; 41 import java.util.zip.ZipEntry ; 42 import java.util.zip.ZipInputStream ; 43 import java.security.CodeSource ; 44 import java.security.ProtectionDomain ; 45 import java.lang.reflect.Method ; 46 47 import org.jboss.logging.Logger; 48 import org.jboss.mx.loading.LoadMgr3.PkgClassLoader; 49 50 55 public class ClassLoaderUtils 56 { 57 private static Logger log = Logger.getLogger(ClassLoaderUtils.class); 58 59 60 private static final Comparator repositoryClassLoaderComparator = new RepositoryClassLoaderComparator(); 61 62 68 public static void displayClassInfo(Class clazz, StringBuffer results) 69 { 70 ClassLoader cl = clazz.getClassLoader(); 72 results.append("\n"+clazz.getName()+"("+Integer.toHexString(clazz.hashCode())+").ClassLoader="+cl); 73 ClassLoader parent = cl; 74 while( parent != null ) 75 { 76 results.append("\n.."+parent); 77 URL [] urls = getClassLoaderURLs(parent); 78 int length = urls != null ? urls.length : 0; 79 for(int u = 0; u < length; u ++) 80 { 81 results.append("\n...."+urls[u]); 82 } 83 if( parent != null ) 84 parent = parent.getParent(); 85 } 86 CodeSource clazzCS = clazz.getProtectionDomain().getCodeSource(); 87 if( clazzCS != null ) 88 results.append("\n++++CodeSource: "+clazzCS); 89 else 90 results.append("\n++++Null CodeSource"); 91 92 results.append("\nImplemented Interfaces:"); 93 Class [] ifaces = clazz.getInterfaces(); 94 for(int i = 0; i < ifaces.length; i ++) 95 { 96 Class iface = ifaces[i]; 97 results.append("\n++"+iface+"("+Integer.toHexString(iface.hashCode())+")"); 98 ClassLoader loader = ifaces[i].getClassLoader(); 99 results.append("\n++++ClassLoader: "+loader); 100 ProtectionDomain pd = ifaces[i].getProtectionDomain(); 101 CodeSource cs = pd.getCodeSource(); 102 if( cs != null ) 103 results.append("\n++++CodeSource: "+cs); 104 else 105 results.append("\n++++Null CodeSource"); 106 } 107 } 108 109 113 public static URL [] getClassLoaderURLs(ClassLoader cl) 114 { 115 URL [] urls = {}; 116 try 117 { 118 Class returnType = urls.getClass(); 119 Class [] parameterTypes = {}; 120 Class clClass = cl.getClass(); 121 Method getURLs = clClass.getMethod("getURLs", parameterTypes); 122 if( returnType.isAssignableFrom(getURLs.getReturnType()) ) 123 { 124 Object [] args = {}; 125 urls = (URL []) getURLs.invoke(cl, args); 126 } 127 if( urls == null || urls.length == 0 ) 128 { 129 Method getCp = clClass.getMethod("getClasspath", parameterTypes); 130 if( returnType.isAssignableFrom(getCp.getReturnType()) ) 131 { 132 Object [] args = {}; 133 urls = (URL []) getCp.invoke(cl, args); 134 } 135 } 136 } 137 catch(Exception ignore) 138 { 139 } 140 return urls; 141 } 142 143 144 150 public static URLClassLoader [] getClassLoaderStack(ClassLoader cl) 151 { 152 ArrayList stack = new ArrayList (); 153 while( cl != null ) 154 { 155 if( cl instanceof URLClassLoader ) 156 { 157 stack.add(cl); 158 } 159 cl = cl.getParent(); 160 } 161 URLClassLoader [] ucls = new URLClassLoader [stack.size()]; 162 stack.toArray(ucls); 163 return ucls; 164 } 165 166 172 public static String getJarClassName(String className) 173 { 174 String jarClassName = className.replace('.', '/'); 175 return jarClassName + ".class"; 176 } 177 178 181 public static String getPackageName(String className) 182 { 183 int startIndex = 0; 184 if( className.length() > 0 && className.charAt(0) == '[' ) 186 { 187 startIndex = className.indexOf('L') + 1; 189 } 190 String pkgName = ""; 192 int endIndex = className.lastIndexOf('.'); 193 if( endIndex > 0 ) 194 pkgName = className.substring(startIndex, endIndex); 195 return pkgName; 196 } 197 198 201 public static String getResourceName(String className) 202 { 203 int startIndex = 0; 204 if( className.length() > 0 && className.charAt(0) == '[' ) 206 { 207 startIndex = className.indexOf('L') + 1; 209 } 210 String resName = ""; 212 int endIndex = className.lastIndexOf('.'); 213 if( endIndex > 0 ) 214 resName = className.substring(startIndex, endIndex); 215 return resName.replace('.', '/'); 216 } 217 218 223 public static Set newPackageSet() 224 { 225 return new TreeSet (repositoryClassLoaderComparator); 226 } 227 228 234 public static Set clonePackageSet(Object toClone) 235 { 236 TreeSet original = (TreeSet ) toClone; 237 return (Set ) original.clone(); 238 } 239 240 248 public static void updatePackageMap(URL url, PkgNameListener listener) 249 throws Exception 250 { 251 ClassPathIterator cpi = new ClassPathIterator(url); 252 updatePackageMap(cpi, listener); 253 } 254 255 263 public static String [] updateClassNamesMap(Object cl, 264 Map classNamesMap, URL url, String [] prevClassNames) 265 throws Exception 266 { 267 ClassPathIterator cpi = new ClassPathIterator(url); 268 HashSet classNameSet = null; 269 if (prevClassNames == null) 270 classNameSet = new HashSet (); 271 else 272 classNameSet = new HashSet (Arrays.asList(prevClassNames)); 273 return updateClassNamesMap(cl, classNamesMap, cpi, classNameSet); 274 } 275 276 static void updatePackageMap(ClassPathIterator cpi, PkgNameListener listener) 277 throws Exception 278 { 279 ClassPathEntry entry; 280 while( (entry = cpi.getNextEntry()) != null ) 281 { 282 String name = entry.getName(); 283 if( name.equals("META-INF/INDEX.LIST") ) 285 { 286 readJarIndex(cpi, listener); 287 break; 289 } 290 291 if( entry.isDirectory() == true ) 293 continue; 294 295 String pkgName = entry.toPackageName(); 296 listener.addPackage(pkgName); 297 } 298 cpi.close(); 299 } 300 301 static String [] updateClassNamesMap(Object cl, Map classNamesMap, 302 ClassPathIterator cpi, HashSet classNameSet) 303 throws Exception 304 { 305 boolean trace = log.isTraceEnabled(); 306 ClassPathEntry entry; 307 while( (entry = cpi.getNextEntry()) != null ) 308 { 309 String name = entry.getName(); 310 if( entry.isDirectory() == true ) 312 continue; 313 if( name.endsWith(".class") == false ) 315 continue; 316 317 addClass(name, classNamesMap, cl, trace); 318 classNameSet.add(name); 319 } 320 cpi.close(); 321 322 String [] classNames = new String [classNameSet.size()]; 324 classNameSet.toArray(classNames); 325 return classNames; 326 } 327 328 331 private static void readJarIndex(ClassPathIterator cpi, PkgNameListener listener) 332 throws Exception 333 { 334 boolean trace = log.isTraceEnabled(); 335 InputStream zis = cpi.getInputStream(); 336 BufferedReader br = new BufferedReader (new InputStreamReader (zis)); 337 String line; 338 while( (line = br.readLine()) != null ) 340 { 341 if( line.length() == 0 ) 342 break; 343 } 344 345 String jarName = br.readLine(); 347 if( trace ) 348 log.trace("Reading INDEX.LIST for jar: "+jarName); 349 while( (line = br.readLine()) != null ) 350 { 351 if( line.length() == 0 ) 352 break; 353 String pkgName = line.replace('/', '.'); 354 listener.addPackage(pkgName); 355 } 356 br.close(); 357 } 358 359 365 private static void addClass(String jarClassName, Map classNamesMap, 366 Object cl, boolean trace) 367 { 368 LinkedList ucls = (LinkedList ) classNamesMap.get(jarClassName); 369 if( ucls == null ) 370 { 371 ucls = new LinkedList (); 372 ucls.add(cl); 373 classNamesMap.put(jarClassName, ucls); 374 } 375 else 376 { 377 boolean uclIsMapped = ucls.contains(cl); 378 if( uclIsMapped == false ) 379 { 380 log.debug("Multiple class loaders found for class: "+jarClassName 381 + ", duplicate UCL: "+cl); 382 ucls.add(cl); 383 } 384 } 385 if( trace ) 386 log.trace("Indexed class: "+jarClassName+", UCL: "+ucls.get(0)); 387 } 388 389 public static interface PkgNameListener 390 { 391 public void addPackage(String name); 392 } 393 394 396 static class FileIterator 397 { 398 LinkedList subDirectories = new LinkedList (); 399 FileFilter filter; 400 File [] currentListing; 401 int index = 0; 402 403 FileIterator(File start) 404 { 405 String name = start.getName(); 406 boolean isWar = name.endsWith(".war"); 408 if( isWar ) 409 currentListing = new File [0]; 410 else 411 currentListing = start.listFiles(); 412 } 413 FileIterator(File start, FileFilter filter) 414 { 415 String name = start.getName(); 416 boolean isWar = name.endsWith(".war"); 418 if( isWar ) 419 currentListing = new File [0]; 420 else 421 currentListing = start.listFiles(filter); 422 this.filter = filter; 423 } 424 425 File getNextEntry() 426 { 427 File next = null; 428 if( index >= currentListing.length && subDirectories.size() > 0 ) 429 { 430 do 431 { 432 File nextDir = (File ) subDirectories.removeFirst(); 433 currentListing = nextDir.listFiles(filter); 434 } while( currentListing.length == 0 && subDirectories.size() > 0 ); 435 index = 0; 436 } 437 if( index < currentListing.length ) 438 { 439 next = currentListing[index ++]; 440 if( next.isDirectory() ) 441 subDirectories.addLast(next); 442 } 443 return next; 444 } 445 } 446 447 449 static class ClassPathEntry 450 { 451 String name; 452 ZipEntry zipEntry; 453 File fileEntry; 454 455 ClassPathEntry(ZipEntry zipEntry) 456 { 457 this.zipEntry = zipEntry; 458 this.name = zipEntry.getName(); 459 } 460 ClassPathEntry(File fileEntry, int rootLength) 461 { 462 this.fileEntry = fileEntry; 463 this.name = fileEntry.getPath().substring(rootLength); 464 } 465 466 String getName() 467 { 468 return name; 469 } 470 472 String toPackageName() 473 { 474 String pkgName = name; 475 char separatorChar = zipEntry != null ? '/' : File.separatorChar; 476 int index = name.lastIndexOf(separatorChar); 477 if( index > 0 ) 478 { 479 pkgName = name.substring(0, index); 480 pkgName = pkgName.replace(separatorChar, '.'); 481 } 482 else 483 { 484 pkgName = ""; 486 } 487 return pkgName; 488 } 489 490 boolean isDirectory() 491 { 492 boolean isDirectory = false; 493 if( zipEntry != null ) 494 isDirectory = zipEntry.isDirectory(); 495 else 496 isDirectory = fileEntry.isDirectory(); 497 return isDirectory; 498 } 499 } 500 501 503 static class ClassPathIterator 504 { 505 ZipInputStream zis; 506 FileIterator fileIter; 507 File file; 508 int rootLength; 509 510 ClassPathIterator(URL url) throws IOException 511 { 512 String protocol = url != null ? url.getProtocol() : null; 513 if( protocol == null ) 514 { 515 } 516 else if( protocol.equals("file") ) 517 { 518 File tmp = new File (url.getFile()); 519 if( tmp.isDirectory() ) 520 { 521 rootLength = tmp.getPath().length() + 1; 522 fileIter = new FileIterator(tmp); 523 } 524 else 525 { 526 InputStream is = new FileInputStream (tmp); 528 zis = new ZipInputStream (is); 529 } 530 } 531 else 532 { 533 InputStream is = url.openStream(); 535 zis = new ZipInputStream (is); 536 } 537 } 538 539 ClassPathEntry getNextEntry() throws IOException 540 { 541 ClassPathEntry entry = null; 542 if( zis != null ) 543 { 544 ZipEntry zentry = zis.getNextEntry(); 545 if( zentry != null ) 546 entry = new ClassPathEntry(zentry); 547 } 548 else if( fileIter != null ) 549 { 550 File fentry = fileIter.getNextEntry(); 551 if( fentry != null ) 552 entry = new ClassPathEntry(fentry, rootLength); 553 file = fentry; 554 } 555 556 return entry; 557 } 558 559 InputStream getInputStream() throws IOException 560 { 561 InputStream is = zis; 562 if( zis == null ) 563 { 564 is = new FileInputStream (file); 565 } 566 return is; 567 } 568 569 void close() throws IOException 570 { 571 if( zis != null ) 572 zis.close(); 573 } 574 575 } 576 577 580 private static class RepositoryClassLoaderComparator implements Comparator 581 { 582 587 public int compare(Object o1, Object o2) 588 { 589 if (o1 instanceof PkgClassLoader) 590 { 591 PkgClassLoader pkg1 = (PkgClassLoader) o1; 592 PkgClassLoader pkg2 = (PkgClassLoader) o2; 593 RepositoryClassLoader rcl1 = pkg1.ucl; 594 RepositoryClassLoader rcl2 = pkg2.ucl; 595 int test = (pkg1.order - pkg2.order); 597 if (test != 0) 598 return test; 599 else 600 return rcl1.getAddedOrder() - rcl2.getAddedOrder(); 601 } 602 else 603 { 604 RepositoryClassLoader rcl1 = (RepositoryClassLoader) o1; 605 RepositoryClassLoader rcl2 = (RepositoryClassLoader) o2; 606 return rcl1.getAddedOrder() - rcl2.getAddedOrder(); 607 608 611 614 } 621 } 622 } 623 } 624 | Popular Tags |