1 22 package org.jboss.mx.loading; 23 24 import java.net.MalformedURLException ; 25 import java.net.URL ; 26 import java.net.URLClassLoader ; 27 import java.util.ArrayList ; 28 import java.util.Arrays ; 29 import java.util.Comparator ; 30 import java.util.HashMap ; 31 import java.util.HashSet ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 import java.util.Enumeration ; 35 import java.util.Map ; 36 import java.util.Set ; 37 import java.util.TreeSet ; 38 import java.util.Vector ; 39 import java.io.IOException ; 40 41 import javax.management.ListenerNotFoundException ; 42 import javax.management.MBeanNotificationInfo ; 43 import javax.management.Notification ; 44 import javax.management.NotificationBroadcaster ; 45 import javax.management.NotificationFilter ; 46 import javax.management.NotificationListener ; 47 import javax.management.MBeanRegistration ; 48 import javax.management.ObjectName ; 49 import javax.management.MBeanServer ; 50 51 import org.jboss.classloading.spi.ClassLoadingDomain; 52 import org.jboss.classloading.spi.DomainClassLoader; 53 import org.jboss.logging.Logger; 54 import org.jboss.mx.loading.LoadMgr3.PkgClassLoader; 55 import org.jboss.mx.util.JBossNotificationBroadcasterSupport; 56 import org.jboss.util.Classes; 57 58 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 59 import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet; 60 61 73 public class UnifiedLoaderRepositoryDCL extends LoaderRepositoryDomain 74 implements MBeanRegistration , NotificationBroadcaster , 75 UnifiedLoaderRepositoryDCLMBean 76 { 77 private static final Logger log = Logger.getLogger(UnifiedLoaderRepository3.class); 79 81 private static int addedCount; 82 83 85 88 private CopyOnWriteArraySet classLoaders = new CopyOnWriteArraySet(); 89 93 private HashSet dynamicClassLoaders = new HashSet (); 94 99 private HashMap nonUCLClassLoader = new HashMap (); 100 101 106 private HashSet classLoaderURLs = new HashSet (); 107 108 111 private ConcurrentReaderHashMap classes = new ConcurrentReaderHashMap(); 112 113 117 private HashMap loaderToClassesMap = new HashMap (); 118 119 123 private HashMap loaderToResourcesMap = new HashMap (); 124 125 129 private HashMap globalResources = new HashMap (); 130 131 135 private ConcurrentReaderHashMap packagesMap = new ConcurrentReaderHashMap(); 136 137 141 private HashMap <DomainClassLoader, List <String >> loaderToPackagesMap = new HashMap <DomainClassLoader, List <String >>(); 142 143 146 private long sequenceNumber = 0; 147 148 151 private final JBossNotificationBroadcasterSupport broadcaster = new JBossNotificationBroadcasterSupport(); 152 153 156 private MBeanNotificationInfo [] info; 157 158 159 161 public DomainClassLoader newClassLoader(final URL url, boolean addToRepository) 162 throws Exception 163 { 164 URL [] cp = {url}; 165 DomainClassLoaderUCLImpl ucl = new DomainClassLoaderUCLImpl(cp, this); 166 if (addToRepository) 167 this.registerClassLoader(ucl); 168 return ucl; 169 } 170 171 public DomainClassLoader newClassLoader(final URL url, final URL origURL, boolean addToRepository) 172 throws Exception 173 { 174 URL [] cp = {url}; 175 DomainClassLoaderUCLImpl ucl = new DomainClassLoaderUCLImpl(cp, this); 176 if (addToRepository) 177 this.registerClassLoader(ucl); 178 return ucl; 179 } 180 181 public ClassLoadingDomain getParent() 182 { 183 return null; 184 } 185 186 public int getCacheSize() 187 { 188 return classes.size(); 189 } 190 191 public int getClassLoadersSize() 192 { 193 return classLoaders.size(); 194 } 195 196 public void flush() 197 { 198 synchronized (classes) 199 { 200 classes.clear(); 201 } 202 } 203 204 public Class getCachedClass(String classname) 205 { 206 return (Class ) classes.get(classname); 207 } 208 209 211 public Class loadClass(String name, boolean resolve, DomainClassLoader cl) 212 throws ClassNotFoundException 213 { 214 return this.loadClassFromClassLoader(name, resolve, cl); 215 } 216 217 220 public Set getPackageClassLoaders(String className) 221 { 222 String pkgName = ClassLoaderUtils.getPackageName(className); 223 Set pkgSet = (Set ) packagesMap.get(pkgName); 224 if (dynamicClassLoaders.size() > 0) 225 { 226 if (pkgSet == null) 227 pkgSet = ClassLoaderUtils.newPackageSet(); 228 pkgSet.addAll(dynamicClassLoaders); 229 } 230 return pkgSet; 231 } 232 233 private String getResourcePackageName(String rsrcName) 234 { 235 int index = rsrcName.lastIndexOf('/'); 236 String pkgName = rsrcName; 237 if (index > 0) 238 pkgName = rsrcName.substring(0, index); 239 return pkgName.replace('/', '.'); 240 } 241 242 246 public Class loadClassFromCache(String name) 247 { 248 Class cls = null; 249 synchronized (classes) 250 { 251 cls = (Class ) classes.get(name); 252 } 253 return cls; 254 } 255 256 261 public void cacheLoadedClass(String name, Class cls, DomainClassLoader cl) 262 { 263 synchronized (classes) 264 { 265 Object prevClass = classes.put(name, cls); 267 if (log.isTraceEnabled()) 268 { 269 log.trace("cacheLoadedClass, classname: " + name + ", class: " + cls 270 + ", ucl: " + cl + ", prevClass: " + prevClass); 271 } 272 273 HashSet loadedClasses = (HashSet ) loaderToClassesMap.get(cl); 276 if (loadedClasses == null) 277 { 278 loadedClasses = new HashSet (); 279 loaderToClassesMap.put(cl, loadedClasses); 280 } 281 loadedClasses.add(name); 282 } 283 } 284 285 Class loadClassFromClassLoader(String name, boolean resolve, DomainClassLoader cl) 286 { 287 try 288 { 289 Class cls = cl.loadClassLocally(name, resolve); 290 cacheLoadedClass(name, cls, cl); 291 return cls; 292 } 293 catch (ClassNotFoundException x) 294 { 295 } 297 return null; 298 } 299 300 303 public URL getResource(String name, DomainClassLoader cl) 304 { 305 URL resource = getResourceFromCache(name, cl); 308 309 if (resource != null) 311 return resource; 312 313 resource = getResourceFromClassLoader(name, cl); 315 316 if (resource != null) 318 return resource; 319 320 resource = getResourceFromGlobalCache(name); 322 323 if (resource != null) 325 return resource; 326 327 resource = getResourceFromRepository(name, cl); 329 330 if (resource != null) 332 return resource; 333 334 return null; 336 } 337 338 345 public void getResources(String name, DomainClassLoader cl, List urls) 346 { 347 Iterator iter = classLoaders.iterator(); 349 while (iter.hasNext() == true) 350 { 351 DomainClassLoader nextCL = (DomainClassLoader) iter.next(); 352 if (nextCL instanceof DomainClassLoader) 353 { 354 DomainClassLoader ucl = (DomainClassLoader) nextCL; 355 try 356 { 357 Enumeration <URL > resURLs = ucl.findResourcesLocally(name); 358 while (resURLs.hasMoreElements()) 359 { 360 Object res = resURLs.nextElement(); 361 urls.add(res); 362 } 363 } 364 catch (IOException ignore) 365 { 366 } 367 } 368 } 369 } 370 public Enumeration <URL > findResources(String name) 371 { 372 Vector <URL > resources = new Vector <URL >(); 373 getResources(name, null, resources); 374 return resources.elements(); 375 } 376 377 385 private URL getResourceFromCache(String name, DomainClassLoader cl) 386 { 387 URL resource = null; 388 synchronized (loaderToResourcesMap) 389 { 390 if (loaderToResourcesMap.containsKey(cl)) 391 { 392 HashMap resources = (HashMap ) loaderToResourcesMap.get(cl); 393 resource = (URL ) resources.get(name); 394 } 395 } 396 return resource; 397 } 398 399 private URL getResourceFromClassLoader(String name, DomainClassLoader cl) 400 { 401 URL resource = null; 402 if (cl instanceof DomainClassLoader) 403 { 404 DomainClassLoader ucl = (DomainClassLoader) cl; 405 resource = ucl.loadResourceLocally(name); 406 cacheLoadedResource(name, resource, cl); 407 } 408 return resource; 409 } 410 411 416 protected URL getResourceFromGlobalCache(String name) 417 { 418 ResourceInfo ri = null; 419 synchronized (loaderToResourcesMap) 420 { 421 ri = (ResourceInfo) globalResources.get(name); 422 } 423 URL resource = null; 424 if (ri != null) 425 resource = ri.url; 426 return resource; 427 } 428 429 protected URL getResourceFromRepository(String name, DomainClassLoader cl) 430 { 431 String pkgName = getResourcePackageName(name); 433 Iterator i = null; 434 Set pkgSet = (Set ) this.packagesMap.get(pkgName); 435 if (pkgSet != null) 436 { 437 i = pkgSet.iterator(); 438 } 439 if (i == null) 440 { 441 i = classLoaders.iterator(); 443 } 444 445 URL url = null; 446 while (i.hasNext() == true) 447 { 448 DomainClassLoader classloader = (DomainClassLoader) i.next(); 449 if (classloader.equals(cl)) 450 { 451 continue; 452 } 453 454 if (classloader instanceof DomainClassLoader) 455 { 456 url = ((DomainClassLoader) classloader).loadResourceLocally(name); 457 if (url != null) 458 { 459 cacheLoadedResource(name, url, classloader); 460 cacheGlobalResource(name, url, classloader); 461 break; 462 } 463 else 464 { 465 } 467 } 468 } 469 return url; 470 } 471 472 477 private void cacheLoadedResource(String name, URL url, DomainClassLoader cl) 478 { 479 synchronized (loaderToResourcesMap) 482 { 483 HashMap resources = (HashMap ) loaderToResourcesMap.get(cl); 484 if (resources == null) 485 { 486 resources = new HashMap (); 487 loaderToResourcesMap.put(cl, resources); 488 } 489 resources.put(name, url); 490 } 491 } 492 493 498 private void cacheGlobalResource(String name, URL url, DomainClassLoader cl) 499 { 500 synchronized (loaderToResourcesMap) 501 { 502 globalResources.put(name, new ResourceInfo(url, cl)); 503 } 504 } 505 506 510 public URL [] getURLs() 511 { 512 HashSet classpath = new HashSet (); 513 Set tmp = classLoaders; 514 for (Iterator iter = tmp.iterator(); iter.hasNext();) 515 { 516 Object obj = iter.next(); 517 if (obj instanceof DomainClassLoader) 518 { 519 DomainClassLoader cl = (DomainClassLoader) obj; 520 URL [] urls = cl.getClasspath(); 521 int length = urls != null ? urls.length : 0; 522 for (int u = 0; u < length; u++) 523 { 524 URL path = urls[u]; 525 classpath.add(path); 526 } 527 } 528 } 530 URL [] cp = new URL [classpath.size()]; 531 classpath.toArray(cp); 532 return cp; 533 } 534 535 539 public String displayClassInfo(String className) 540 { 541 544 String classRsrcName = className.replace('.', '/') + ".class"; 545 546 int count = 0; 547 Class loadedClass = this.loadClassFromCache(className); 548 StringBuffer results = new StringBuffer (className + " Information\n"); 549 if (loadedClass != null) 550 { 551 results.append("Repository cache version:"); 552 Classes.displayClassInfo(loadedClass, results); 553 } 554 else 555 { 556 results.append("Not loaded in repository cache\n"); 557 } 558 Set tmp = classLoaders; 559 for (Iterator iter = tmp.iterator(); iter.hasNext();) 560 { 561 URLClassLoader cl = (URLClassLoader ) iter.next(); 562 URL classURL = cl.findResource(classRsrcName); 563 if (classURL != null) 564 { 565 results.append("\n\n### Instance" + count + " found in UCL: " + cl + "\n"); 566 count++; 567 } 568 } 569 570 ClassLoader tcl = Thread.currentThread().getContextClassLoader(); 572 URLClassLoader [] stack = ClassLoaderUtils.getClassLoaderStack(tcl); 573 for (int s = 0; s < stack.length; s++) 574 { 575 URLClassLoader cl = stack[s]; 576 URL classURL = cl.findResource(classRsrcName); 577 if (classURL != null) 578 { 579 results.append("\n\n### Instance" + count + " via UCL: " + cl + "\n"); 580 count++; 581 } 582 } 583 584 return results.toString(); 585 } 586 587 589 594 public Class loadClass(String className) throws ClassNotFoundException 595 { 596 ClassLoader scl = Thread.currentThread().getContextClassLoader(); 598 DomainClassLoader ucl = null; 599 if (classLoaders.size() > 0) 600 ucl = (DomainClassLoader) this.classLoaders.iterator().next(); 601 try 602 { 603 if (ucl != null) 604 return loadClass(className, false, ucl); 605 } 606 catch (ClassNotFoundException ignore) 607 { 608 } 610 611 try 612 { 613 return scl.loadClass(className); 615 } 616 catch (ClassNotFoundException e) 617 { 618 } 620 621 Class clazz = getNativeClassForName(className); 623 if (clazz != null) return clazz; 624 625 throw new ClassNotFoundException (className); 626 } 627 628 637 public Class loadClassWithout(DomainClassLoader loader, String className) 638 throws ClassNotFoundException 639 { 640 throw new ClassNotFoundException ("NYI"); 641 } 642 643 649 public DomainClassLoader getWrappingClassLoader(DomainClassLoader cl) 650 { 651 synchronized (classLoaders) 652 { 653 return (DomainClassLoader) nonUCLClassLoader.get(cl); 654 } 655 } 656 657 659 public void addClassLoader(DomainClassLoader loader) 660 { 661 addDomainClassLoader((DomainClassLoaderUCLImpl) loader); 663 } 664 665 public boolean addClassLoaderURL(DomainClassLoader cl, URL url) 666 { 667 DomainClassLoader ucl = (DomainClassLoader) cl; 668 boolean added = false; 669 synchronized (classLoaders) 670 { 671 String query = url.getQuery(); 673 if (query != null) 674 { 675 String ext = url.toExternalForm(); 676 String ext2 = ext.substring(0, ext.length() - query.length() - 1); 677 try 678 { 679 url = new URL (ext2); 680 } 681 catch (MalformedURLException e) 682 { 683 log.warn("Failed to strip query from: " + url, e); 684 } 685 } 686 687 if (classLoaderURLs.contains(url) == false) 689 { 690 updatePackageMap(ucl); 691 classLoaderURLs.add(url); 692 added = true; 693 if (query != null && query.indexOf("dynamic=true") >= 0) 695 dynamicClassLoaders.add(ucl); 696 } 697 } 698 return added; 699 } 700 701 705 private void addDomainClassLoader(DomainClassLoaderUCLImpl cl) 706 { 707 cl.setDomain(this); 708 boolean added = false; 709 synchronized (classLoaders) 710 { 711 boolean exists = false; 712 URL [] cp = cl.getClasspath(); 713 classLoaderURLs.addAll(Arrays.asList(cp)); 714 added = classLoaders.add(cl); 715 if (added) 716 { 717 log.debug("Adding " + cl); 718 addedCount++; 719 cl.setAddedOrder(addedCount); 720 updatePackageMap(cl); 721 } 722 else 723 { 724 log.debug("Skipping duplicate " + cl); 725 } 726 } 727 } 728 729 732 private synchronized void updatePackageMap(DomainClassLoader cl) 733 { 734 boolean trace = log.isTraceEnabled(); 735 try 736 { 737 PackageMapper listener = new PackageMapper(cl); 738 URL [] cp = cl.getClasspath(); 739 for(URL url : cp) 740 { 741 ClassLoaderUtils.updatePackageMap(url, listener); 742 } 743 } 744 catch (Exception e) 745 { 746 if (log.isTraceEnabled()) 747 log.trace("Failed to update pkgs for cl=" + cl, e); 748 else 749 log.debug("Failed to update pkgs for cl=" + cl, e); 750 } 751 } 752 753 756 public void removeClassLoader(DomainClassLoader loader) 757 { 758 ArrayList removeNotifications = new ArrayList (); 759 DomainClassLoader cl = loader; 760 synchronized (classLoaders) 761 { 762 if ((loader instanceof DomainClassLoader) == false) 763 { 764 cl = (DomainClassLoader) nonUCLClassLoader.remove(loader); 765 } 766 if (cl instanceof DomainClassLoader) 767 { 768 DomainClassLoader ucl = (DomainClassLoader) cl; 769 if (getTranslator() != null) 770 getTranslator().unregisterClassLoader(ucl); 771 URL [] urls = ucl.getClasspath(); 772 for (int u = 0; u < urls.length; u++) 773 classLoaderURLs.remove(urls[u]); 774 } 775 boolean dynamic = dynamicClassLoaders.remove(cl); 776 boolean removed = classLoaders.remove(cl); 777 log.debug("UnifiedLoaderRepository removed(" + removed + ") " + cl); 778 779 HashSet loadedClasses = null; 781 boolean hasLoadedClasses = false; 782 synchronized (classes) 783 { 784 hasLoadedClasses = loaderToClassesMap.containsKey(cl); 785 if (hasLoadedClasses) 786 loadedClasses = (HashSet ) loaderToClassesMap.remove(cl); 787 if (loadedClasses != null) 789 { 790 for (Iterator iter = loadedClasses.iterator(); iter.hasNext();) 792 { 793 String className = (String ) iter.next(); 794 Notification n = new Notification (CLASS_REMOVED, this, 795 getNextSequenceNumber(), className); 796 removeNotifications.add(n); 797 } 798 799 for (Iterator i = loadedClasses.iterator(); i.hasNext();) 801 { 802 String cls = (String ) i.next(); 803 this.classes.remove(cls); 804 } 805 } 806 } 807 808 synchronized (loaderToResourcesMap) 810 { 811 if (loaderToResourcesMap.containsKey(cl)) 812 { 813 HashMap resources = (HashMap ) loaderToResourcesMap.remove(cl); 814 815 if (resources != null) 817 { 818 for (Iterator i = resources.keySet().iterator(); i.hasNext();) 819 { 820 String name = (String ) i.next(); 821 ResourceInfo ri = (ResourceInfo) globalResources.get(name); 822 if (ri != null && ri.cl == cl) 823 globalResources.remove(name); 824 } 825 } 826 } 827 } 828 829 if (dynamic == false) 831 { 832 List <String > pkgNames = loaderToPackagesMap.remove(cl); 833 if( pkgNames != null ) 834 { 835 for(String pkgName : pkgNames) 836 { 837 Set pkgSet = (Set ) packagesMap.get(pkgName); 838 if (pkgSet != null) 839 { 840 pkgSet.remove(cl); 841 if (pkgSet.isEmpty()) 842 packagesMap.remove(pkgName); 843 } 844 } 845 } 846 } 847 else 848 { 849 loaderToPackagesMap.remove(cl); 851 for (Iterator i = packagesMap.entrySet().iterator(); i.hasNext();) 852 { 853 Map.Entry entry = (Map.Entry ) i.next(); 854 Set pkgSet = (Set ) entry.getValue(); 855 pkgSet.remove(cl); 856 if (pkgSet.isEmpty()) 857 i.remove(); 858 } 859 } 860 } 861 862 for (int n = 0; n < removeNotifications.size(); n++) 864 { 865 Notification msg = (Notification ) removeNotifications.get(n); 866 broadcaster.sendNotification(msg); 867 } 868 869 Notification msg = new Notification (CLASSLOADER_REMOVED, this, getNextSequenceNumber()); 870 msg.setUserData(cl); 871 broadcaster.sendNotification(msg); 872 } 873 874 883 public LoaderRepositoryDomain registerClassLoader(DomainClassLoader ucl) 884 { 885 addClassLoader(ucl); 886 Notification msg = new Notification (CLASSLOADER_ADDED, this, getNextSequenceNumber()); 887 msg.setUserData(ucl); 888 broadcaster.sendNotification(msg); 889 890 return this; 891 } 892 893 896 public LoaderRepositoryDomain getInstance() 897 { 898 return this; 899 } 900 901 903 911 public void addNotificationListener(NotificationListener listener, 912 NotificationFilter filter, Object handback) throws IllegalArgumentException 913 { 914 broadcaster.addNotificationListener(listener, filter, handback); 915 } 916 917 921 public MBeanNotificationInfo [] getNotificationInfo() 922 { 923 if (info == null) 924 { 925 info = new MBeanNotificationInfo []{ 926 new MBeanNotificationInfo (new String []{"CLASSLOADER_ADDED"}, 927 "javax.management.Notification", 928 "Notification that a classloader has been added to the extensible classloader"), 929 new MBeanNotificationInfo (new String []{"CLASS_REMOVED"}, 930 "javax.management.Notification", 931 "Notification that a class has been removed from the extensible classloader") 932 933 }; 934 } 935 return info; 936 } 937 938 944 public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException 945 { 946 broadcaster.removeNotificationListener(listener); 947 } 948 949 public ObjectName preRegister(MBeanServer server, ObjectName name) 951 throws Exception 952 { 953 return name; 954 } 955 956 public void postRegister(Boolean registrationDone) 957 { 958 } 959 960 public void preDeregister() 961 throws Exception 962 { 963 } 964 965 public void postDeregister() 966 { 967 log.debug("postDeregister, clearing all references"); 968 classLoaders.clear(); 969 dynamicClassLoaders.clear(); 970 nonUCLClassLoader.clear(); 971 classLoaderURLs.clear(); 972 classes.clear(); 973 loaderToClassesMap.clear(); 974 loaderToResourcesMap.clear(); 975 globalResources.clear(); 976 packagesMap.clear(); 977 loaderToPackagesMap.clear(); 978 } 979 980 985 String [] getPackageNames(DomainClassLoaderUCLImpl loader) 986 { 987 List <String > pkgNames = loaderToPackagesMap.get(loader); 988 String [] tmp = {}; 989 if( pkgNames != null ) 990 { 991 tmp = new String [pkgNames.size()]; 992 pkgNames.toArray(tmp); 993 } 994 return tmp; 995 } 996 997 private synchronized long getNextSequenceNumber() 998 { 999 return sequenceNumber++; 1000 } 1001 1002 1005 private static class DomainClassLoaderUCLImplComparator implements Comparator 1006 { 1007 1012 public int compare(Object o1, Object o2) 1013 { 1014 if (o1 instanceof PkgClassLoader) 1015 { 1016 PkgClassLoader pkg1 = (PkgClassLoader) o1; 1017 PkgClassLoader pkg2 = (PkgClassLoader) o2; 1018 RepositoryClassLoader rcl1 = pkg1.ucl; 1019 RepositoryClassLoader rcl2 = pkg2.ucl; 1020 int test = (pkg1.order - pkg2.order); 1022 if (test != 0) 1023 return test; 1024 else 1025 return rcl1.getAddedOrder() - rcl2.getAddedOrder(); 1026 } 1027 else 1028 { 1029 DomainClassLoaderUCLImpl rcl1 = (DomainClassLoaderUCLImpl) o1; 1030 DomainClassLoaderUCLImpl rcl2 = (DomainClassLoaderUCLImpl) o2; 1031 return rcl1.getAddedOrder() - rcl2.getAddedOrder(); 1032 1033 1036 1039 } 1046 } 1047 } 1048 1049 class PackageMapper implements ClassLoaderUtils.PkgNameListener 1050 { 1051 private DomainClassLoader loader; 1052 PackageMapper(DomainClassLoader loader) 1053 { 1054 this.loader = loader; 1055 } 1056 public void addPackage(String pkgName) 1057 { 1058 if( pkgName.startsWith("META-INF") || pkgName.startsWith("WEB-INF") ) 1060 return; 1061 1062 Set <DomainClassLoader> pkgSet = (Set <DomainClassLoader>) packagesMap.get(pkgName); 1063 if( pkgSet == null ) 1064 { 1065 pkgSet = new TreeSet <DomainClassLoader>(new DomainClassLoaderUCLImplComparator()); 1066 packagesMap.put(pkgName, pkgSet); 1067 } 1068 if( pkgSet.contains(loader) == false ) 1069 { 1070 pkgSet.add((DomainClassLoader)loader); 1071 List <String > loaderPkgNames = loaderToPackagesMap.get(loader); 1072 if( loaderPkgNames == null ) 1073 { 1074 loaderPkgNames = new ArrayList <String >(); 1075 loaderToPackagesMap.put((DomainClassLoader)loader, loaderPkgNames); 1076 } 1077 loaderPkgNames.add(pkgName); 1078 1079 if( pkgSet.size() > 1 ) 1081 { 1082 log.debug("Multiple class loaders found for pkg: "+pkgName); 1083 } 1084 if( log.isTraceEnabled() ) 1085 log.trace("Indexed pkg: "+pkgName+", UCL: "+loader); 1086 } 1087 } 1088 } 1089} 1090 | Popular Tags |