src/share/classes/sun/rmi/server/LoaderHandler.java

Print this page




  95 
  96     /** table of class loaders that use codebase property for annotation */
  97     private static final Map<ClassLoader, Void> codebaseLoaders =
  98         Collections.synchronizedMap(new IdentityHashMap<ClassLoader, Void>(5));
  99     static {
 100         for (ClassLoader codebaseLoader = ClassLoader.getSystemClassLoader();
 101              codebaseLoader != null;
 102              codebaseLoader = codebaseLoader.getParent())
 103         {
 104             codebaseLoaders.put(codebaseLoader, null);
 105         }
 106     }
 107 
 108     /**
 109      * table mapping codebase URL path and context class loader pairs
 110      * to class loader instances.  Entries hold class loaders with weak
 111      * references, so this table does not prevent loaders from being
 112      * garbage collected.
 113      */
 114     private static final HashMap<LoaderKey, LoaderEntry> loaderTable
 115         = new HashMap<LoaderKey, LoaderEntry>(5);
 116 
 117     /** reference queue for cleared class loader entries */
 118     private static final ReferenceQueue<Loader> refQueue
 119         = new ReferenceQueue<Loader>();
 120 
 121     /*
 122      * Disallow anyone from creating one of these.
 123      */
 124     private LoaderHandler() {}
 125 
 126     /**
 127      * Returns an array of URLs initialized with the value of the
 128      * java.rmi.server.codebase property as the URL path.
 129      */
 130     private static synchronized URL[] getDefaultCodebaseURLs()
 131         throws MalformedURLException
 132     {
 133         /*
 134          * If it hasn't already been done, convert the codebase property
 135          * into an array of URLs; this may throw a MalformedURLException.
 136          */
 137         if (codebaseURLs == null) {
 138             if (codebaseProperty != null) {
 139                 codebaseURLs = pathToURLs(codebaseProperty);
 140             } else {
 141                 codebaseURLs = new URL[0];
 142             }
 143         }
 144         return codebaseURLs;
 145     }
 146 
 147     /**
 148      * Load a class from a network location (one or more URLs),
 149      * but first try to resolve the named class through the given
 150      * "default loader".
 151      */
 152     public static Class loadClass(String codebase, String name,
 153                                   ClassLoader defaultLoader)
 154         throws MalformedURLException, ClassNotFoundException
 155     {
 156         if (loaderLog.isLoggable(Log.BRIEF)) {
 157             loaderLog.log(Log.BRIEF,
 158                 "name = \"" + name + "\", " +
 159                 "codebase = \"" + (codebase != null ? codebase : "") + "\"" +
 160                 (defaultLoader != null ?
 161                  ", defaultLoader = " + defaultLoader : ""));
 162         }
 163 
 164         URL[] urls;
 165         if (codebase != null) {
 166             urls = pathToURLs(codebase);
 167         } else {
 168             urls = getDefaultCodebaseURLs();
 169         }
 170 
 171         if (defaultLoader != null) {
 172             try {
 173                 Class c = Class.forName(name, false, defaultLoader);
 174                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 175                     loaderLog.log(Log.VERBOSE,
 176                         "class \"" + name + "\" found via defaultLoader, " +
 177                         "defined by " + c.getClassLoader());
 178                 }
 179                 return c;
 180             } catch (ClassNotFoundException e) {
 181             }
 182         }
 183 
 184         return loadClass(urls, name);
 185     }
 186 
 187     /**
 188      * Returns the class annotation (representing the location for
 189      * a class) that RMI will use to annotate the call stream when
 190      * marshalling objects of the given class.
 191      */
 192     public static String getClassAnnotation(Class cl) {
 193         String name = cl.getName();
 194 
 195         /*
 196          * Class objects for arrays of primitive types never need an
 197          * annotation, because they never need to be (or can be) downloaded.
 198          *
 199          * REMIND: should we (not) be annotating classes that are in
 200          * "java.*" packages?
 201          */
 202         int nameLength = name.length();
 203         if (nameLength > 0 && name.charAt(0) == '[') {
 204             // skip past all '[' characters (see bugid 4211906)
 205             int i = 1;
 206             while (nameLength > i && name.charAt(i) == '[') {
 207                 i++;
 208             }
 209             if (nameLength > i && name.charAt(i) != 'L') {
 210                 return null;
 211             }
 212         }


 244                      * we must verify that the current access control context
 245                      * has permission to know all of these URLs.
 246                      */
 247                     SecurityManager sm = System.getSecurityManager();
 248                     if (sm != null) {
 249                         Permissions perms = new Permissions();
 250                         for (int i = 0; i < urls.length; i++) {
 251                             Permission p =
 252                                 urls[i].openConnection().getPermission();
 253                             if (p != null) {
 254                                 if (!perms.implies(p)) {
 255                                     sm.checkPermission(p);
 256                                     perms.add(p);
 257                                 }
 258                             }
 259                         }
 260                     }
 261 
 262                     annotation = urlsToPath(urls);
 263                 }
 264             } catch (SecurityException e) {
 265                 /*
 266                  * If access was denied to the knowledge of the class
 267                  * loader's URLs, fall back to the default behavior.
 268                  */
 269             } catch (IOException e) {
 270                 /*
 271                  * This shouldn't happen, although it is declared to be
 272                  * thrown by openConnection() and getPermission().  If it
 273                  * does happen, forget about this class loader's URLs and
 274                  * fall back to the default behavior.
 275                  */
 276             }
 277         }
 278 
 279         if (annotation != null) {
 280             return annotation;
 281         } else {
 282             return codebaseProperty;    // REMIND: does this make sense??
 283         }
 284     }
 285 
 286     /**
 287      * Returns a classloader that loads classes from the given codebase URL
 288      * path.  The parent classloader of the returned classloader is the
 289      * context class loader.
 290      */
 291     public static ClassLoader getClassLoader(String codebase)
 292         throws MalformedURLException


 341             URL[] urls = ((Loader) loader).getURLs();
 342             if (urls.length > 0) {
 343                 return urls[0];
 344             }
 345         }
 346         return null;
 347     }
 348 
 349     /**
 350      * Register a class loader as one whose classes should always be
 351      * annotated with the value of the "java.rmi.server.codebase" property.
 352      */
 353     public static void registerCodebaseLoader(ClassLoader loader) {
 354         codebaseLoaders.put(loader, null);
 355     }
 356 
 357     /**
 358      * Load a class from the RMI class loader corresponding to the given
 359      * codebase URL path in the current execution context.
 360      */
 361     private static Class loadClass(URL[] urls, String name)
 362         throws ClassNotFoundException
 363     {
 364         ClassLoader parent = getRMIContextClassLoader();
 365         if (loaderLog.isLoggable(Log.VERBOSE)) {
 366             loaderLog.log(Log.VERBOSE,
 367                 "(thread context class loader: " + parent + ")");
 368         }
 369 
 370         /*
 371          * If no security manager is set, disable access to RMI class
 372          * loaders and simply delegate request to the parent loader
 373          * (see bugid 4140511).
 374          */
 375         SecurityManager sm = System.getSecurityManager();
 376         if (sm == null) {
 377             try {
 378                 Class c = Class.forName(name, false, parent);
 379                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 380                     loaderLog.log(Log.VERBOSE,
 381                         "class \"" + name + "\" found via " +
 382                         "thread context class loader " +
 383                         "(no security manager: codebase disabled), " +
 384                         "defined by " + c.getClassLoader());
 385                 }
 386                 return c;
 387             } catch (ClassNotFoundException e) {
 388                 if (loaderLog.isLoggable(Log.BRIEF)) {
 389                     loaderLog.log(Log.BRIEF,
 390                         "class \"" + name + "\" not found via " +
 391                         "thread context class loader " +
 392                         "(no security manager: codebase disabled)", e);
 393                 }
 394                 throw new ClassNotFoundException(e.getMessage() +
 395                     " (no security manager: RMI class loader disabled)",
 396                     e.getException());
 397             }
 398         }


 407             if (loader != null) {
 408                 /*
 409                  * Verify that the caller has permission to access this loader.
 410                  */
 411                 loader.checkPermissions();
 412             }
 413         } catch (SecurityException e) {
 414             /*
 415              * If the current access control context does not have permission
 416              * to access all of the URLs in the codebase path, wrap the
 417              * resulting security exception in a ClassNotFoundException, so
 418              * the caller can handle this outcome just like any other class
 419              * loading failure (see bugid 4146529).
 420              */
 421             try {
 422                 /*
 423                  * But first, check to see if the named class could have been
 424                  * resolved without the security-offending codebase anyway;
 425                  * if so, return successfully (see bugids 4191926 & 4349670).
 426                  */
 427                 Class c = Class.forName(name, false, parent);
 428                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 429                     loaderLog.log(Log.VERBOSE,
 430                         "class \"" + name + "\" found via " +
 431                         "thread context class loader " +
 432                         "(access to codebase denied), " +
 433                         "defined by " + c.getClassLoader());
 434                 }
 435                 return c;
 436             } catch (ClassNotFoundException unimportant) {
 437                 /*
 438                  * Presumably the security exception is the more important
 439                  * exception to report in this case.
 440                  */
 441                 if (loaderLog.isLoggable(Log.BRIEF)) {
 442                     loaderLog.log(Log.BRIEF,
 443                         "class \"" + name + "\" not found via " +
 444                         "thread context class loader " +
 445                         "(access to codebase denied)", e);
 446                 }
 447                 throw new ClassNotFoundException(
 448                     "access to class loader denied", e);
 449             }
 450         }
 451 
 452         try {
 453             Class c = Class.forName(name, false, loader);
 454             if (loaderLog.isLoggable(Log.VERBOSE)) {
 455                 loaderLog.log(Log.VERBOSE,
 456                     "class \"" + name + "\" " + "found via codebase, " +
 457                     "defined by " + c.getClassLoader());
 458             }
 459             return c;
 460         } catch (ClassNotFoundException e) {
 461             if (loaderLog.isLoggable(Log.BRIEF)) {
 462                 loaderLog.log(Log.BRIEF,
 463                     "class \"" + name + "\" not found via codebase", e);
 464             }
 465             throw e;
 466         }
 467     }
 468 
 469     /**
 470      * Define and return a dynamic proxy class in a class loader with
 471      * URLs supplied in the given location.  The proxy class will
 472      * implement interface classes named by the given array of
 473      * interface names.
 474      */
 475     public static Class loadProxyClass(String codebase, String[] interfaces,
 476                                        ClassLoader defaultLoader)
 477         throws MalformedURLException, ClassNotFoundException
 478     {
 479         if (loaderLog.isLoggable(Log.BRIEF)) {
 480             loaderLog.log(Log.BRIEF,
 481                 "interfaces = " + Arrays.asList(interfaces) + ", " +
 482                 "codebase = \"" + (codebase != null ? codebase : "") + "\"" +
 483                 (defaultLoader != null ?
 484                  ", defaultLoader = " + defaultLoader : ""));
 485         }
 486 
 487         /*
 488          * This method uses a fairly complex algorithm to load the
 489          * proxy class and its interface classes in order to maximize
 490          * the likelihood that the proxy's codebase annotation will be
 491          * preserved.  The algorithm is (assuming that all of the
 492          * proxy interface classes are public):
 493          *
 494          * If the default loader is not null, try to load the proxy
 495          * interfaces through that loader. If the interfaces can be


 520         ClassLoader parent = getRMIContextClassLoader();
 521         if (loaderLog.isLoggable(Log.VERBOSE)) {
 522             loaderLog.log(Log.VERBOSE,
 523                 "(thread context class loader: " + parent + ")");
 524         }
 525 
 526         URL[] urls;
 527         if (codebase != null) {
 528             urls = pathToURLs(codebase);
 529         } else {
 530             urls = getDefaultCodebaseURLs();
 531         }
 532 
 533         /*
 534          * If no security manager is set, disable access to RMI class
 535          * loaders and use the would-de parent instead.
 536          */
 537         SecurityManager sm = System.getSecurityManager();
 538         if (sm == null) {
 539             try {
 540                 Class c = loadProxyClass(interfaces, defaultLoader, parent,
 541                                          false);
 542                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 543                     loaderLog.log(Log.VERBOSE,
 544                         "(no security manager: codebase disabled) " +
 545                         "proxy class defined by " + c.getClassLoader());
 546                 }
 547                 return c;
 548             } catch (ClassNotFoundException e) {
 549                 if (loaderLog.isLoggable(Log.BRIEF)) {
 550                     loaderLog.log(Log.BRIEF,
 551                         "(no security manager: codebase disabled) " +
 552                         "proxy class resolution failed", e);
 553                 }
 554                 throw new ClassNotFoundException(e.getMessage() +
 555                     " (no security manager: RMI class loader disabled)",
 556                     e.getException());
 557             }
 558         }
 559 
 560         /*


 567             if (loader != null) {
 568                 /*
 569                  * Verify that the caller has permission to access this loader.
 570                  */
 571                 loader.checkPermissions();
 572             }
 573         } catch (SecurityException e) {
 574             /*
 575              * If the current access control context does not have permission
 576              * to access all of the URLs in the codebase path, wrap the
 577              * resulting security exception in a ClassNotFoundException, so
 578              * the caller can handle this outcome just like any other class
 579              * loading failure (see bugid 4146529).
 580              */
 581             try {
 582                 /*
 583                  * But first, check to see if the proxy class could have been
 584                  * resolved without the security-offending codebase anyway;
 585                  * if so, return successfully (see bugids 4191926 & 4349670).
 586                  */
 587                 Class c = loadProxyClass(interfaces, defaultLoader, parent,
 588                                          false);
 589                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 590                     loaderLog.log(Log.VERBOSE,
 591                         "(access to codebase denied) " +
 592                         "proxy class defined by " + c.getClassLoader());
 593                 }
 594                 return c;
 595             } catch (ClassNotFoundException unimportant) {
 596                 /*
 597                  * Presumably the security exception is the more important
 598                  * exception to report in this case.
 599                  */
 600                 if (loaderLog.isLoggable(Log.BRIEF)) {
 601                     loaderLog.log(Log.BRIEF,
 602                         "(access to codebase denied) " +
 603                         "proxy class resolution failed", e);
 604                 }
 605                 throw new ClassNotFoundException(
 606                     "access to class loader denied", e);
 607             }
 608         }
 609 
 610         try {
 611             Class c = loadProxyClass(interfaces, defaultLoader, loader, true);
 612             if (loaderLog.isLoggable(Log.VERBOSE)) {
 613                 loaderLog.log(Log.VERBOSE,
 614                               "proxy class defined by " + c.getClassLoader());
 615             }
 616             return c;
 617         } catch (ClassNotFoundException e) {
 618             if (loaderLog.isLoggable(Log.BRIEF)) {
 619                 loaderLog.log(Log.BRIEF,
 620                               "proxy class resolution failed", e);
 621             }
 622             throw e;
 623         }
 624     }
 625 
 626     /**
 627      * Define a proxy class in the default loader if appropriate.
 628      * Define the class in an RMI class loader otherwise.  The proxy
 629      * class will implement classes which are named in the supplied
 630      * interfaceNames.
 631      */
 632     private static Class loadProxyClass(String[] interfaceNames,
 633                                         ClassLoader defaultLoader,
 634                                         ClassLoader codebaseLoader,
 635                                         boolean preferCodebase)
 636         throws ClassNotFoundException
 637     {
 638         ClassLoader proxyLoader = null;
 639         Class[] classObjs = new Class[interfaceNames.length];
 640         boolean[] nonpublic = { false };
 641 
 642       defaultLoaderCase:
 643         if (defaultLoader != null) {
 644             try {
 645                 proxyLoader =
 646                     loadProxyInterfaces(interfaceNames, defaultLoader,
 647                                         classObjs, nonpublic);
 648                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 649                     ClassLoader[] definingLoaders =
 650                         new ClassLoader[classObjs.length];
 651                     for (int i = 0; i < definingLoaders.length; i++) {
 652                         definingLoaders[i] = classObjs[i].getClassLoader();
 653                     }
 654                     loaderLog.log(Log.VERBOSE,
 655                         "proxy interfaces found via defaultLoader, " +
 656                         "defined by " + Arrays.asList(definingLoaders));
 657                 }
 658             } catch (ClassNotFoundException e) {
 659                 break defaultLoaderCase;


 675                                           classObjs, nonpublic);
 676         if (loaderLog.isLoggable(Log.VERBOSE)) {
 677             ClassLoader[] definingLoaders = new ClassLoader[classObjs.length];
 678             for (int i = 0; i < definingLoaders.length; i++) {
 679                 definingLoaders[i] = classObjs[i].getClassLoader();
 680             }
 681             loaderLog.log(Log.VERBOSE,
 682                 "proxy interfaces found via codebase, " +
 683                 "defined by " + Arrays.asList(definingLoaders));
 684         }
 685         if (!nonpublic[0]) {
 686             proxyLoader = codebaseLoader;
 687         }
 688         return loadProxyClass(proxyLoader, classObjs);
 689     }
 690 
 691     /**
 692      * Define a proxy class in the given class loader.  The proxy
 693      * class will implement the given interfaces Classes.
 694      */
 695     private static Class loadProxyClass(ClassLoader loader, Class[] interfaces)
 696         throws ClassNotFoundException
 697     {
 698         try {
 699             return Proxy.getProxyClass(loader, interfaces);
 700         } catch (IllegalArgumentException e) {
 701             throw new ClassNotFoundException(
 702                 "error creating dynamic proxy class", e);
 703         }
 704     }
 705 
 706     /*
 707      * Load Class objects for the names in the interfaces array fron
 708      * the given class loader.
 709      *
 710      * We pass classObjs and nonpublic arrays to avoid needing a
 711      * multi-element return value.  nonpublic is an array to enable
 712      * the method to take a boolean argument by reference.
 713      *
 714      * nonpublic array is needed to signal when the return value of
 715      * this method should be used as the proxy class loader.  Because
 716      * null represents a valid class loader, that value is
 717      * insufficient to signal that the return value should not be used
 718      * as the proxy class loader.
 719      */
 720     private static ClassLoader loadProxyInterfaces(String[] interfaces,
 721                                                    ClassLoader loader,
 722                                                    Class[] classObjs,
 723                                                    boolean[] nonpublic)
 724         throws ClassNotFoundException
 725     {
 726         /* loader of a non-public interface class */
 727         ClassLoader nonpublicLoader = null;
 728 
 729         for (int i = 0; i < interfaces.length; i++) {
 730             Class cl =
 731                 (classObjs[i] = Class.forName(interfaces[i], false, loader));
 732 
 733             if (!Modifier.isPublic(cl.getModifiers())) {
 734                 ClassLoader current = cl.getClassLoader();
 735                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 736                     loaderLog.log(Log.VERBOSE,
 737                         "non-public interface \"" + interfaces[i] +
 738                         "\" defined by " + current);
 739                 }
 740                 if (!nonpublic[0]) {
 741                     nonpublicLoader = current;
 742                     nonpublic[0] = true;
 743                 } else if (current != nonpublicLoader) {
 744                     throw new IllegalAccessError(
 745                         "non-public interfaces defined in different " +
 746                         "class loaders");
 747                 }
 748             }
 749         }
 750         return nonpublicLoader;


 761         synchronized (pathToURLsCache) {
 762             Object[] v = pathToURLsCache.get(path);
 763             if (v != null) {
 764                 return ((URL[])v[0]);
 765             }
 766         }
 767         StringTokenizer st = new StringTokenizer(path); // divide by spaces
 768         URL[] urls = new URL[st.countTokens()];
 769         for (int i = 0; st.hasMoreTokens(); i++) {
 770             urls[i] = new URL(st.nextToken());
 771         }
 772         synchronized (pathToURLsCache) {
 773             pathToURLsCache.put(path,
 774                                 new Object[] {urls, new SoftReference<String>(path)});
 775         }
 776         return urls;
 777     }
 778 
 779     /** map from weak(key=string) to [URL[], soft(key)] */
 780     private static final Map<String, Object[]> pathToURLsCache
 781         = new WeakHashMap<String, Object[]>(5);
 782 
 783     /**
 784      * Convert an array of URL objects into a corresponding string
 785      * containing a space-separated list of URLs.
 786      *
 787      * Note that if the array has zero elements, the return value is
 788      * null, not the empty string.
 789      */
 790     private static String urlsToPath(URL[] urls) {
 791         if (urls.length == 0) {
 792             return null;
 793         } else if (urls.length == 1) {
 794             return urls[0].toExternalForm();
 795         } else {
 796             StringBuffer path = new StringBuffer(urls[0].toExternalForm());
 797             for (int i = 1; i < urls.length; i++) {
 798                 path.append(' ');
 799                 path.append(urls[i].toExternalForm());
 800             }
 801             return path.toString();


1154              * class loader.
1155              */
1156             annotation = urlsToPath(urls);
1157         }
1158 
1159         /**
1160          * Return the string to be annotated with all classes loaded from
1161          * this class loader.
1162          */
1163         public String getClassAnnotation() {
1164             return annotation;
1165         }
1166 
1167         /**
1168          * Check that the current access control context has all of the
1169          * permissions necessary to load classes from this loader.
1170          */
1171         private void checkPermissions() {
1172             SecurityManager sm = System.getSecurityManager();
1173             if (sm != null) {           // should never be null?
1174                 Enumeration enum_ = permissions.elements();
1175                 while (enum_.hasMoreElements()) {
1176                     sm.checkPermission((Permission) enum_.nextElement());
1177                 }
1178             }
1179         }
1180 
1181         /**
1182          * Return the permissions to be granted to code loaded from the
1183          * given code source.
1184          */
1185         protected PermissionCollection getPermissions(CodeSource codesource) {
1186             PermissionCollection perms = super.getPermissions(codesource);
1187             /*
1188              * Grant the same permissions that URLClassLoader would grant.
1189              */
1190             return perms;
1191         }
1192 
1193         /**
1194          * Return a string representation of this loader (useful for
1195          * debugging).
1196          */


  95 
  96     /** table of class loaders that use codebase property for annotation */
  97     private static final Map<ClassLoader, Void> codebaseLoaders =
  98         Collections.synchronizedMap(new IdentityHashMap<ClassLoader, Void>(5));
  99     static {
 100         for (ClassLoader codebaseLoader = ClassLoader.getSystemClassLoader();
 101              codebaseLoader != null;
 102              codebaseLoader = codebaseLoader.getParent())
 103         {
 104             codebaseLoaders.put(codebaseLoader, null);
 105         }
 106     }
 107 
 108     /**
 109      * table mapping codebase URL path and context class loader pairs
 110      * to class loader instances.  Entries hold class loaders with weak
 111      * references, so this table does not prevent loaders from being
 112      * garbage collected.
 113      */
 114     private static final HashMap<LoaderKey, LoaderEntry> loaderTable
 115         = new HashMap<>(5);
 116 
 117     /** reference queue for cleared class loader entries */
 118     private static final ReferenceQueue<Loader> refQueue
 119         = new ReferenceQueue<>();
 120 
 121     /*
 122      * Disallow anyone from creating one of these.
 123      */
 124     private LoaderHandler() {}
 125 
 126     /**
 127      * Returns an array of URLs initialized with the value of the
 128      * java.rmi.server.codebase property as the URL path.
 129      */
 130     private static synchronized URL[] getDefaultCodebaseURLs()
 131         throws MalformedURLException
 132     {
 133         /*
 134          * If it hasn't already been done, convert the codebase property
 135          * into an array of URLs; this may throw a MalformedURLException.
 136          */
 137         if (codebaseURLs == null) {
 138             if (codebaseProperty != null) {
 139                 codebaseURLs = pathToURLs(codebaseProperty);
 140             } else {
 141                 codebaseURLs = new URL[0];
 142             }
 143         }
 144         return codebaseURLs;
 145     }
 146 
 147     /**
 148      * Load a class from a network location (one or more URLs),
 149      * but first try to resolve the named class through the given
 150      * "default loader".
 151      */
 152     public static Class<?> loadClass(String codebase, String name,
 153                                   ClassLoader defaultLoader)
 154         throws MalformedURLException, ClassNotFoundException
 155     {
 156         if (loaderLog.isLoggable(Log.BRIEF)) {
 157             loaderLog.log(Log.BRIEF,
 158                 "name = \"" + name + "\", " +
 159                 "codebase = \"" + (codebase != null ? codebase : "") + "\"" +
 160                 (defaultLoader != null ?
 161                  ", defaultLoader = " + defaultLoader : ""));
 162         }
 163 
 164         URL[] urls;
 165         if (codebase != null) {
 166             urls = pathToURLs(codebase);
 167         } else {
 168             urls = getDefaultCodebaseURLs();
 169         }
 170 
 171         if (defaultLoader != null) {
 172             try {
 173                 Class<?> c = Class.forName(name, false, defaultLoader);
 174                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 175                     loaderLog.log(Log.VERBOSE,
 176                         "class \"" + name + "\" found via defaultLoader, " +
 177                         "defined by " + c.getClassLoader());
 178                 }
 179                 return c;
 180             } catch (ClassNotFoundException e) {
 181             }
 182         }
 183 
 184         return loadClass(urls, name);
 185     }
 186 
 187     /**
 188      * Returns the class annotation (representing the location for
 189      * a class) that RMI will use to annotate the call stream when
 190      * marshalling objects of the given class.
 191      */
 192     public static String getClassAnnotation(Class<?> cl) {
 193         String name = cl.getName();
 194 
 195         /*
 196          * Class objects for arrays of primitive types never need an
 197          * annotation, because they never need to be (or can be) downloaded.
 198          *
 199          * REMIND: should we (not) be annotating classes that are in
 200          * "java.*" packages?
 201          */
 202         int nameLength = name.length();
 203         if (nameLength > 0 && name.charAt(0) == '[') {
 204             // skip past all '[' characters (see bugid 4211906)
 205             int i = 1;
 206             while (nameLength > i && name.charAt(i) == '[') {
 207                 i++;
 208             }
 209             if (nameLength > i && name.charAt(i) != 'L') {
 210                 return null;
 211             }
 212         }


 244                      * we must verify that the current access control context
 245                      * has permission to know all of these URLs.
 246                      */
 247                     SecurityManager sm = System.getSecurityManager();
 248                     if (sm != null) {
 249                         Permissions perms = new Permissions();
 250                         for (int i = 0; i < urls.length; i++) {
 251                             Permission p =
 252                                 urls[i].openConnection().getPermission();
 253                             if (p != null) {
 254                                 if (!perms.implies(p)) {
 255                                     sm.checkPermission(p);
 256                                     perms.add(p);
 257                                 }
 258                             }
 259                         }
 260                     }
 261 
 262                     annotation = urlsToPath(urls);
 263                 }
 264             } catch (SecurityException | IOException e) {
 265                 /*
 266                  * SecurityException: If access was denied to the knowledge of 
 267                  * the class loader's URLs, fall back to the default behavior.
 268                  *
 269                  * IOException: This shouldn't happen, although it is declared
 270                  * to be thrown by openConnection() and getPermission().  If it


 271                  * does happen, forget about this class loader's URLs and
 272                  * fall back to the default behavior.
 273                  */
 274             }
 275         }
 276 
 277         if (annotation != null) {
 278             return annotation;
 279         } else {
 280             return codebaseProperty;    // REMIND: does this make sense??
 281         }
 282     }
 283 
 284     /**
 285      * Returns a classloader that loads classes from the given codebase URL
 286      * path.  The parent classloader of the returned classloader is the
 287      * context class loader.
 288      */
 289     public static ClassLoader getClassLoader(String codebase)
 290         throws MalformedURLException


 339             URL[] urls = ((Loader) loader).getURLs();
 340             if (urls.length > 0) {
 341                 return urls[0];
 342             }
 343         }
 344         return null;
 345     }
 346 
 347     /**
 348      * Register a class loader as one whose classes should always be
 349      * annotated with the value of the "java.rmi.server.codebase" property.
 350      */
 351     public static void registerCodebaseLoader(ClassLoader loader) {
 352         codebaseLoaders.put(loader, null);
 353     }
 354 
 355     /**
 356      * Load a class from the RMI class loader corresponding to the given
 357      * codebase URL path in the current execution context.
 358      */
 359     private static Class<?> loadClass(URL[] urls, String name)
 360         throws ClassNotFoundException
 361     {
 362         ClassLoader parent = getRMIContextClassLoader();
 363         if (loaderLog.isLoggable(Log.VERBOSE)) {
 364             loaderLog.log(Log.VERBOSE,
 365                 "(thread context class loader: " + parent + ")");
 366         }
 367 
 368         /*
 369          * If no security manager is set, disable access to RMI class
 370          * loaders and simply delegate request to the parent loader
 371          * (see bugid 4140511).
 372          */
 373         SecurityManager sm = System.getSecurityManager();
 374         if (sm == null) {
 375             try {
 376                 Class<?> c = Class.forName(name, false, parent);
 377                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 378                     loaderLog.log(Log.VERBOSE,
 379                         "class \"" + name + "\" found via " +
 380                         "thread context class loader " +
 381                         "(no security manager: codebase disabled), " +
 382                         "defined by " + c.getClassLoader());
 383                 }
 384                 return c;
 385             } catch (ClassNotFoundException e) {
 386                 if (loaderLog.isLoggable(Log.BRIEF)) {
 387                     loaderLog.log(Log.BRIEF,
 388                         "class \"" + name + "\" not found via " +
 389                         "thread context class loader " +
 390                         "(no security manager: codebase disabled)", e);
 391                 }
 392                 throw new ClassNotFoundException(e.getMessage() +
 393                     " (no security manager: RMI class loader disabled)",
 394                     e.getException());
 395             }
 396         }


 405             if (loader != null) {
 406                 /*
 407                  * Verify that the caller has permission to access this loader.
 408                  */
 409                 loader.checkPermissions();
 410             }
 411         } catch (SecurityException e) {
 412             /*
 413              * If the current access control context does not have permission
 414              * to access all of the URLs in the codebase path, wrap the
 415              * resulting security exception in a ClassNotFoundException, so
 416              * the caller can handle this outcome just like any other class
 417              * loading failure (see bugid 4146529).
 418              */
 419             try {
 420                 /*
 421                  * But first, check to see if the named class could have been
 422                  * resolved without the security-offending codebase anyway;
 423                  * if so, return successfully (see bugids 4191926 & 4349670).
 424                  */
 425                 Class<?> c = Class.forName(name, false, parent);
 426                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 427                     loaderLog.log(Log.VERBOSE,
 428                         "class \"" + name + "\" found via " +
 429                         "thread context class loader " +
 430                         "(access to codebase denied), " +
 431                         "defined by " + c.getClassLoader());
 432                 }
 433                 return c;
 434             } catch (ClassNotFoundException unimportant) {
 435                 /*
 436                  * Presumably the security exception is the more important
 437                  * exception to report in this case.
 438                  */
 439                 if (loaderLog.isLoggable(Log.BRIEF)) {
 440                     loaderLog.log(Log.BRIEF,
 441                         "class \"" + name + "\" not found via " +
 442                         "thread context class loader " +
 443                         "(access to codebase denied)", e);
 444                 }
 445                 throw new ClassNotFoundException(
 446                     "access to class loader denied", e);
 447             }
 448         }
 449 
 450         try {
 451             Class<?> c = Class.forName(name, false, loader);
 452             if (loaderLog.isLoggable(Log.VERBOSE)) {
 453                 loaderLog.log(Log.VERBOSE,
 454                     "class \"" + name + "\" " + "found via codebase, " +
 455                     "defined by " + c.getClassLoader());
 456             }
 457             return c;
 458         } catch (ClassNotFoundException e) {
 459             if (loaderLog.isLoggable(Log.BRIEF)) {
 460                 loaderLog.log(Log.BRIEF,
 461                     "class \"" + name + "\" not found via codebase", e);
 462             }
 463             throw e;
 464         }
 465     }
 466 
 467     /**
 468      * Define and return a dynamic proxy class in a class loader with
 469      * URLs supplied in the given location.  The proxy class will
 470      * implement interface classes named by the given array of
 471      * interface names.
 472      */
 473     public static Class<?> loadProxyClass(String codebase, String[] interfaces,
 474                                        ClassLoader defaultLoader)
 475         throws MalformedURLException, ClassNotFoundException
 476     {
 477         if (loaderLog.isLoggable(Log.BRIEF)) {
 478             loaderLog.log(Log.BRIEF,
 479                 "interfaces = " + Arrays.asList(interfaces) + ", " +
 480                 "codebase = \"" + (codebase != null ? codebase : "") + "\"" +
 481                 (defaultLoader != null ?
 482                  ", defaultLoader = " + defaultLoader : ""));
 483         }
 484 
 485         /*
 486          * This method uses a fairly complex algorithm to load the
 487          * proxy class and its interface classes in order to maximize
 488          * the likelihood that the proxy's codebase annotation will be
 489          * preserved.  The algorithm is (assuming that all of the
 490          * proxy interface classes are public):
 491          *
 492          * If the default loader is not null, try to load the proxy
 493          * interfaces through that loader. If the interfaces can be


 518         ClassLoader parent = getRMIContextClassLoader();
 519         if (loaderLog.isLoggable(Log.VERBOSE)) {
 520             loaderLog.log(Log.VERBOSE,
 521                 "(thread context class loader: " + parent + ")");
 522         }
 523 
 524         URL[] urls;
 525         if (codebase != null) {
 526             urls = pathToURLs(codebase);
 527         } else {
 528             urls = getDefaultCodebaseURLs();
 529         }
 530 
 531         /*
 532          * If no security manager is set, disable access to RMI class
 533          * loaders and use the would-de parent instead.
 534          */
 535         SecurityManager sm = System.getSecurityManager();
 536         if (sm == null) {
 537             try {
 538                 Class<?> c = loadProxyClass(interfaces, defaultLoader, parent,
 539                                          false);
 540                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 541                     loaderLog.log(Log.VERBOSE,
 542                         "(no security manager: codebase disabled) " +
 543                         "proxy class defined by " + c.getClassLoader());
 544                 }
 545                 return c;
 546             } catch (ClassNotFoundException e) {
 547                 if (loaderLog.isLoggable(Log.BRIEF)) {
 548                     loaderLog.log(Log.BRIEF,
 549                         "(no security manager: codebase disabled) " +
 550                         "proxy class resolution failed", e);
 551                 }
 552                 throw new ClassNotFoundException(e.getMessage() +
 553                     " (no security manager: RMI class loader disabled)",
 554                     e.getException());
 555             }
 556         }
 557 
 558         /*


 565             if (loader != null) {
 566                 /*
 567                  * Verify that the caller has permission to access this loader.
 568                  */
 569                 loader.checkPermissions();
 570             }
 571         } catch (SecurityException e) {
 572             /*
 573              * If the current access control context does not have permission
 574              * to access all of the URLs in the codebase path, wrap the
 575              * resulting security exception in a ClassNotFoundException, so
 576              * the caller can handle this outcome just like any other class
 577              * loading failure (see bugid 4146529).
 578              */
 579             try {
 580                 /*
 581                  * But first, check to see if the proxy class could have been
 582                  * resolved without the security-offending codebase anyway;
 583                  * if so, return successfully (see bugids 4191926 & 4349670).
 584                  */
 585                 Class<?> c = loadProxyClass(interfaces, defaultLoader, parent,
 586                                          false);
 587                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 588                     loaderLog.log(Log.VERBOSE,
 589                         "(access to codebase denied) " +
 590                         "proxy class defined by " + c.getClassLoader());
 591                 }
 592                 return c;
 593             } catch (ClassNotFoundException unimportant) {
 594                 /*
 595                  * Presumably the security exception is the more important
 596                  * exception to report in this case.
 597                  */
 598                 if (loaderLog.isLoggable(Log.BRIEF)) {
 599                     loaderLog.log(Log.BRIEF,
 600                         "(access to codebase denied) " +
 601                         "proxy class resolution failed", e);
 602                 }
 603                 throw new ClassNotFoundException(
 604                     "access to class loader denied", e);
 605             }
 606         }
 607 
 608         try {
 609             Class<?> c = loadProxyClass(interfaces, defaultLoader, loader, true);
 610             if (loaderLog.isLoggable(Log.VERBOSE)) {
 611                 loaderLog.log(Log.VERBOSE,
 612                               "proxy class defined by " + c.getClassLoader());
 613             }
 614             return c;
 615         } catch (ClassNotFoundException e) {
 616             if (loaderLog.isLoggable(Log.BRIEF)) {
 617                 loaderLog.log(Log.BRIEF,
 618                               "proxy class resolution failed", e);
 619             }
 620             throw e;
 621         }
 622     }
 623 
 624     /**
 625      * Define a proxy class in the default loader if appropriate.
 626      * Define the class in an RMI class loader otherwise.  The proxy
 627      * class will implement classes which are named in the supplied
 628      * interfaceNames.
 629      */
 630     private static Class<?> loadProxyClass(String[] interfaceNames,
 631                                         ClassLoader defaultLoader,
 632                                         ClassLoader codebaseLoader,
 633                                         boolean preferCodebase)
 634         throws ClassNotFoundException
 635     {
 636         ClassLoader proxyLoader = null;
 637         Class<?>[] classObjs = new Class<?>[interfaceNames.length];
 638         boolean[] nonpublic = { false };
 639 
 640       defaultLoaderCase:
 641         if (defaultLoader != null) {
 642             try {
 643                 proxyLoader =
 644                     loadProxyInterfaces(interfaceNames, defaultLoader,
 645                                         classObjs, nonpublic);
 646                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 647                     ClassLoader[] definingLoaders =
 648                         new ClassLoader[classObjs.length];
 649                     for (int i = 0; i < definingLoaders.length; i++) {
 650                         definingLoaders[i] = classObjs[i].getClassLoader();
 651                     }
 652                     loaderLog.log(Log.VERBOSE,
 653                         "proxy interfaces found via defaultLoader, " +
 654                         "defined by " + Arrays.asList(definingLoaders));
 655                 }
 656             } catch (ClassNotFoundException e) {
 657                 break defaultLoaderCase;


 673                                           classObjs, nonpublic);
 674         if (loaderLog.isLoggable(Log.VERBOSE)) {
 675             ClassLoader[] definingLoaders = new ClassLoader[classObjs.length];
 676             for (int i = 0; i < definingLoaders.length; i++) {
 677                 definingLoaders[i] = classObjs[i].getClassLoader();
 678             }
 679             loaderLog.log(Log.VERBOSE,
 680                 "proxy interfaces found via codebase, " +
 681                 "defined by " + Arrays.asList(definingLoaders));
 682         }
 683         if (!nonpublic[0]) {
 684             proxyLoader = codebaseLoader;
 685         }
 686         return loadProxyClass(proxyLoader, classObjs);
 687     }
 688 
 689     /**
 690      * Define a proxy class in the given class loader.  The proxy
 691      * class will implement the given interfaces Classes.
 692      */
 693     private static Class<?> loadProxyClass(ClassLoader loader, Class[] interfaces)
 694         throws ClassNotFoundException
 695     {
 696         try {
 697             return Proxy.getProxyClass(loader, interfaces);
 698         } catch (IllegalArgumentException e) {
 699             throw new ClassNotFoundException(
 700                 "error creating dynamic proxy class", e);
 701         }
 702     }
 703 
 704     /*
 705      * Load Class objects for the names in the interfaces array fron
 706      * the given class loader.
 707      *
 708      * We pass classObjs and nonpublic arrays to avoid needing a
 709      * multi-element return value.  nonpublic is an array to enable
 710      * the method to take a boolean argument by reference.
 711      *
 712      * nonpublic array is needed to signal when the return value of
 713      * this method should be used as the proxy class loader.  Because
 714      * null represents a valid class loader, that value is
 715      * insufficient to signal that the return value should not be used
 716      * as the proxy class loader.
 717      */
 718     private static ClassLoader loadProxyInterfaces(String[] interfaces,
 719                                                    ClassLoader loader,
 720                                                    Class[] classObjs,
 721                                                    boolean[] nonpublic)
 722         throws ClassNotFoundException
 723     {
 724         /* loader of a non-public interface class */
 725         ClassLoader nonpublicLoader = null;
 726 
 727         for (int i = 0; i < interfaces.length; i++) {
 728             Class<?> cl =
 729                 (classObjs[i] = Class.forName(interfaces[i], false, loader));
 730 
 731             if (!Modifier.isPublic(cl.getModifiers())) {
 732                 ClassLoader current = cl.getClassLoader();
 733                 if (loaderLog.isLoggable(Log.VERBOSE)) {
 734                     loaderLog.log(Log.VERBOSE,
 735                         "non-public interface \"" + interfaces[i] +
 736                         "\" defined by " + current);
 737                 }
 738                 if (!nonpublic[0]) {
 739                     nonpublicLoader = current;
 740                     nonpublic[0] = true;
 741                 } else if (current != nonpublicLoader) {
 742                     throw new IllegalAccessError(
 743                         "non-public interfaces defined in different " +
 744                         "class loaders");
 745                 }
 746             }
 747         }
 748         return nonpublicLoader;


 759         synchronized (pathToURLsCache) {
 760             Object[] v = pathToURLsCache.get(path);
 761             if (v != null) {
 762                 return ((URL[])v[0]);
 763             }
 764         }
 765         StringTokenizer st = new StringTokenizer(path); // divide by spaces
 766         URL[] urls = new URL[st.countTokens()];
 767         for (int i = 0; st.hasMoreTokens(); i++) {
 768             urls[i] = new URL(st.nextToken());
 769         }
 770         synchronized (pathToURLsCache) {
 771             pathToURLsCache.put(path,
 772                                 new Object[] {urls, new SoftReference<String>(path)});
 773         }
 774         return urls;
 775     }
 776 
 777     /** map from weak(key=string) to [URL[], soft(key)] */
 778     private static final Map<String, Object[]> pathToURLsCache
 779         = new WeakHashMap<>(5);
 780 
 781     /**
 782      * Convert an array of URL objects into a corresponding string
 783      * containing a space-separated list of URLs.
 784      *
 785      * Note that if the array has zero elements, the return value is
 786      * null, not the empty string.
 787      */
 788     private static String urlsToPath(URL[] urls) {
 789         if (urls.length == 0) {
 790             return null;
 791         } else if (urls.length == 1) {
 792             return urls[0].toExternalForm();
 793         } else {
 794             StringBuffer path = new StringBuffer(urls[0].toExternalForm());
 795             for (int i = 1; i < urls.length; i++) {
 796                 path.append(' ');
 797                 path.append(urls[i].toExternalForm());
 798             }
 799             return path.toString();


1152              * class loader.
1153              */
1154             annotation = urlsToPath(urls);
1155         }
1156 
1157         /**
1158          * Return the string to be annotated with all classes loaded from
1159          * this class loader.
1160          */
1161         public String getClassAnnotation() {
1162             return annotation;
1163         }
1164 
1165         /**
1166          * Check that the current access control context has all of the
1167          * permissions necessary to load classes from this loader.
1168          */
1169         private void checkPermissions() {
1170             SecurityManager sm = System.getSecurityManager();
1171             if (sm != null) {           // should never be null?
1172                 Enumeration<Permission> enum_ = permissions.elements();
1173                 while (enum_.hasMoreElements()) {
1174                     sm.checkPermission(enum_.nextElement());
1175                 }
1176             }
1177         }
1178 
1179         /**
1180          * Return the permissions to be granted to code loaded from the
1181          * given code source.
1182          */
1183         protected PermissionCollection getPermissions(CodeSource codesource) {
1184             PermissionCollection perms = super.getPermissions(codesource);
1185             /*
1186              * Grant the same permissions that URLClassLoader would grant.
1187              */
1188             return perms;
1189         }
1190 
1191         /**
1192          * Return a string representation of this loader (useful for
1193          * debugging).
1194          */