1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import java.io.Closeable; 29 import java.io.File; 30 import java.io.FilePermission; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.security.AccessControlContext; 34 import java.security.AccessController; 35 import java.security.CodeSigner; 36 import java.security.CodeSource; 37 import java.security.Permission; 38 import java.security.PermissionCollection; 39 import java.security.PrivilegedAction; 40 import java.security.PrivilegedExceptionAction; 41 import java.security.SecureClassLoader; 42 import java.util.Enumeration; 43 import java.util.List; 44 import java.util.NoSuchElementException; 45 import java.util.Objects; 46 import java.util.Set; 47 import java.util.WeakHashMap; 48 import java.util.jar.Attributes; 49 import java.util.jar.Attributes.Name; 50 import java.util.jar.JarFile; 51 import java.util.jar.Manifest; 52 import sun.misc.Resource; 53 import sun.misc.URLClassPath; 54 import sun.net.www.ParseUtil; 55 import sun.security.util.SecurityConstants; 56 57 /** 58 * This class loader is used to load classes and resources from a search 59 * path of URLs referring to both JAR files and directories. Any URL that 60 * ends with a '/' is assumed to refer to a directory. Otherwise, the URL 61 * is assumed to refer to a JAR file which will be opened as needed. 62 * <p> 63 * The AccessControlContext of the thread that created the instance of 64 * URLClassLoader will be used when subsequently loading classes and 65 * resources. 66 * <p> 67 * The classes that are loaded are by default granted permission only to 68 * access the URLs specified when the URLClassLoader was created. 69 * 70 * @author David Connelly 71 * @since 1.2 72 */ 73 public class URLClassLoader extends SecureClassLoader implements Closeable { 74 /* The search path for classes and resources */ 75 private final URLClassPath ucp; 76 77 /* The context to be used when loading classes and resources */ 78 private final AccessControlContext acc; 79 80 /** 81 * Constructs a new URLClassLoader for the given URLs. The URLs will be 82 * searched in the order specified for classes and resources after first 83 * searching in the specified parent class loader. Any URL that ends with 84 * a '/' is assumed to refer to a directory. Otherwise, the URL is assumed 85 * to refer to a JAR file which will be downloaded and opened as needed. 86 * 87 * <p>If there is a security manager, this method first 88 * calls the security manager's {@code checkCreateClassLoader} method 89 * to ensure creation of a class loader is allowed. 90 * 91 * @param urls the URLs from which to load classes and resources 92 * @param parent the parent class loader for delegation 93 * @exception SecurityException if a security manager exists and its 94 * {@code checkCreateClassLoader} method doesn't allow 95 * creation of a class loader. 96 * @exception NullPointerException if {@code urls} is {@code null}. 97 * @see SecurityManager#checkCreateClassLoader 98 */ URLClassLoader(URL[] urls, ClassLoader parent)99 public URLClassLoader(URL[] urls, ClassLoader parent) { 100 super(parent); 101 // this is to make the stack depth consistent with 1.1 102 SecurityManager security = System.getSecurityManager(); 103 if (security != null) { 104 security.checkCreateClassLoader(); 105 } 106 this.acc = AccessController.getContext(); 107 ucp = new URLClassPath(urls, acc); 108 } 109 URLClassLoader(URL[] urls, ClassLoader parent, AccessControlContext acc)110 URLClassLoader(URL[] urls, ClassLoader parent, 111 AccessControlContext acc) { 112 super(parent); 113 // this is to make the stack depth consistent with 1.1 114 SecurityManager security = System.getSecurityManager(); 115 if (security != null) { 116 security.checkCreateClassLoader(); 117 } 118 this.acc = acc; 119 ucp = new URLClassPath(urls, acc); 120 } 121 122 /** 123 * Constructs a new URLClassLoader for the specified URLs using the 124 * default delegation parent {@code ClassLoader}. The URLs will 125 * be searched in the order specified for classes and resources after 126 * first searching in the parent class loader. Any URL that ends with 127 * a '/' is assumed to refer to a directory. Otherwise, the URL is 128 * assumed to refer to a JAR file which will be downloaded and opened 129 * as needed. 130 * 131 * <p>If there is a security manager, this method first 132 * calls the security manager's {@code checkCreateClassLoader} method 133 * to ensure creation of a class loader is allowed. 134 * 135 * @param urls the URLs from which to load classes and resources 136 * 137 * @exception SecurityException if a security manager exists and its 138 * {@code checkCreateClassLoader} method doesn't allow 139 * creation of a class loader. 140 * @exception NullPointerException if {@code urls} is {@code null}. 141 * @see SecurityManager#checkCreateClassLoader 142 */ URLClassLoader(URL[] urls)143 public URLClassLoader(URL[] urls) { 144 super(); 145 // this is to make the stack depth consistent with 1.1 146 SecurityManager security = System.getSecurityManager(); 147 if (security != null) { 148 security.checkCreateClassLoader(); 149 } 150 this.acc = AccessController.getContext(); 151 ucp = new URLClassPath(urls, acc); 152 } 153 URLClassLoader(URL[] urls, AccessControlContext acc)154 URLClassLoader(URL[] urls, AccessControlContext acc) { 155 super(); 156 // this is to make the stack depth consistent with 1.1 157 SecurityManager security = System.getSecurityManager(); 158 if (security != null) { 159 security.checkCreateClassLoader(); 160 } 161 this.acc = acc; 162 ucp = new URLClassPath(urls, acc); 163 } 164 165 /** 166 * Constructs a new URLClassLoader for the specified URLs, parent 167 * class loader, and URLStreamHandlerFactory. The parent argument 168 * will be used as the parent class loader for delegation. The 169 * factory argument will be used as the stream handler factory to 170 * obtain protocol handlers when creating new jar URLs. 171 * 172 * <p>If there is a security manager, this method first 173 * calls the security manager's {@code checkCreateClassLoader} method 174 * to ensure creation of a class loader is allowed. 175 * 176 * @param urls the URLs from which to load classes and resources 177 * @param parent the parent class loader for delegation 178 * @param factory the URLStreamHandlerFactory to use when creating URLs 179 * 180 * @exception SecurityException if a security manager exists and its 181 * {@code checkCreateClassLoader} method doesn't allow 182 * creation of a class loader. 183 * @exception NullPointerException if {@code urls} is {@code null}. 184 * @see SecurityManager#checkCreateClassLoader 185 */ URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)186 public URLClassLoader(URL[] urls, ClassLoader parent, 187 URLStreamHandlerFactory factory) { 188 super(parent); 189 // this is to make the stack depth consistent with 1.1 190 SecurityManager security = System.getSecurityManager(); 191 if (security != null) { 192 security.checkCreateClassLoader(); 193 } 194 acc = AccessController.getContext(); 195 ucp = new URLClassPath(urls, factory, acc); 196 } 197 198 /* A map (used as a set) to keep track of closeable local resources 199 * (either JarFiles or FileInputStreams). We don't care about 200 * Http resources since they don't need to be closed. 201 * 202 * If the resource is coming from a jar file 203 * we keep a (weak) reference to the JarFile object which can 204 * be closed if URLClassLoader.close() called. Due to jar file 205 * caching there will typically be only one JarFile object 206 * per underlying jar file. 207 * 208 * For file resources, which is probably a less common situation 209 * we have to keep a weak reference to each stream. 210 */ 211 212 private WeakHashMap<Closeable,Void> 213 closeables = new WeakHashMap<>(); 214 215 /** 216 * Returns an input stream for reading the specified resource. 217 * If this loader is closed, then any resources opened by this method 218 * will be closed. 219 * 220 * <p> The search order is described in the documentation for {@link 221 * #getResource(String)}. </p> 222 * 223 * @param name 224 * The resource name 225 * 226 * @return An input stream for reading the resource, or {@code null} 227 * if the resource could not be found 228 * 229 * @since 1.7 230 */ getResourceAsStream(String name)231 public InputStream getResourceAsStream(String name) { 232 URL url = getResource(name); 233 try { 234 if (url == null) { 235 return null; 236 } 237 URLConnection urlc = url.openConnection(); 238 InputStream is = urlc.getInputStream(); 239 if (urlc instanceof JarURLConnection) { 240 JarURLConnection juc = (JarURLConnection)urlc; 241 JarFile jar = juc.getJarFile(); 242 synchronized (closeables) { 243 if (!closeables.containsKey(jar)) { 244 closeables.put(jar, null); 245 } 246 } 247 } else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) { 248 synchronized (closeables) { 249 closeables.put(is, null); 250 } 251 } 252 return is; 253 } catch (IOException e) { 254 return null; 255 } 256 } 257 258 /** 259 * Closes this URLClassLoader, so that it can no longer be used to load 260 * new classes or resources that are defined by this loader. 261 * Classes and resources defined by any of this loader's parents in the 262 * delegation hierarchy are still accessible. Also, any classes or resources 263 * that are already loaded, are still accessible. 264 * <p> 265 * In the case of jar: and file: URLs, it also closes any files 266 * that were opened by it. If another thread is loading a 267 * class when the {@code close} method is invoked, then the result of 268 * that load is undefined. 269 * <p> 270 * The method makes a best effort attempt to close all opened files, 271 * by catching {@link IOException}s internally. Unchecked exceptions 272 * and errors are not caught. Calling close on an already closed 273 * loader has no effect. 274 * <p> 275 * @exception IOException if closing any file opened by this class loader 276 * resulted in an IOException. Any such exceptions are caught internally. 277 * If only one is caught, then it is re-thrown. If more than one exception 278 * is caught, then the second and following exceptions are added 279 * as suppressed exceptions of the first one caught, which is then re-thrown. 280 * 281 * @exception SecurityException if a security manager is set, and it denies 282 * {@link RuntimePermission}{@code ("closeClassLoader")} 283 * 284 * @since 1.7 285 */ close()286 public void close() throws IOException { 287 SecurityManager security = System.getSecurityManager(); 288 if (security != null) { 289 security.checkPermission(new RuntimePermission("closeClassLoader")); 290 } 291 List<IOException> errors = ucp.closeLoaders(); 292 293 // now close any remaining streams. 294 295 synchronized (closeables) { 296 Set<Closeable> keys = closeables.keySet(); 297 for (Closeable c : keys) { 298 try { 299 c.close(); 300 } catch (IOException ioex) { 301 errors.add(ioex); 302 } 303 } 304 closeables.clear(); 305 } 306 307 if (errors.isEmpty()) { 308 return; 309 } 310 311 IOException firstex = errors.remove(0); 312 313 // Suppress any remaining exceptions 314 315 for (IOException error: errors) { 316 firstex.addSuppressed(error); 317 } 318 throw firstex; 319 } 320 321 /** 322 * Appends the specified URL to the list of URLs to search for 323 * classes and resources. 324 * <p> 325 * If the URL specified is {@code null} or is already in the 326 * list of URLs, or if this loader is closed, then invoking this 327 * method has no effect. 328 * 329 * @param url the URL to be added to the search path of URLs 330 */ addURL(URL url)331 protected void addURL(URL url) { 332 ucp.addURL(url); 333 } 334 335 /** 336 * Returns the search path of URLs for loading classes and resources. 337 * This includes the original list of URLs specified to the constructor, 338 * along with any URLs subsequently appended by the addURL() method. 339 * @return the search path of URLs for loading classes and resources. 340 */ getURLs()341 public URL[] getURLs() { 342 return ucp.getURLs(); 343 } 344 345 /** 346 * Finds and loads the class with the specified name from the URL search 347 * path. Any URLs referring to JAR files are loaded and opened as needed 348 * until the class is found. 349 * 350 * @param name the name of the class 351 * @return the resulting class 352 * @exception ClassNotFoundException if the class could not be found, 353 * or if the loader is closed. 354 * @exception NullPointerException if {@code name} is {@code null}. 355 */ findClass(final String name)356 protected Class<?> findClass(final String name) 357 throws ClassNotFoundException 358 { 359 final Class<?> result; 360 try { 361 result = AccessController.doPrivileged( 362 new PrivilegedExceptionAction<Class<?>>() { 363 public Class<?> run() throws ClassNotFoundException { 364 String path = name.replace('.', '/').concat(".class"); 365 Resource res = ucp.getResource(path, false); 366 if (res != null) { 367 try { 368 return defineClass(name, res); 369 } catch (IOException e) { 370 throw new ClassNotFoundException(name, e); 371 } 372 } else { 373 return null; 374 } 375 } 376 }, acc); 377 } catch (java.security.PrivilegedActionException pae) { 378 throw (ClassNotFoundException) pae.getException(); 379 } 380 if (result == null) { 381 throw new ClassNotFoundException(name); 382 } 383 return result; 384 } 385 386 /* 387 * Retrieve the package using the specified package name. 388 * If non-null, verify the package using the specified code 389 * source and manifest. 390 */ getAndVerifyPackage(String pkgname, Manifest man, URL url)391 private Package getAndVerifyPackage(String pkgname, 392 Manifest man, URL url) { 393 Package pkg = getPackage(pkgname); 394 if (pkg != null) { 395 // Package found, so check package sealing. 396 if (pkg.isSealed()) { 397 // Verify that code source URL is the same. 398 if (!pkg.isSealed(url)) { 399 throw new SecurityException( 400 "sealing violation: package " + pkgname + " is sealed"); 401 } 402 } else { 403 // Make sure we are not attempting to seal the package 404 // at this code source URL. 405 if ((man != null) && isSealed(pkgname, man)) { 406 throw new SecurityException( 407 "sealing violation: can't seal package " + pkgname + 408 ": already loaded"); 409 } 410 } 411 } 412 return pkg; 413 } 414 415 // Also called by VM to define Package for classes loaded from the CDS 416 // archive definePackageInternal(String pkgname, Manifest man, URL url)417 private void definePackageInternal(String pkgname, Manifest man, URL url) 418 { 419 if (getAndVerifyPackage(pkgname, man, url) == null) { 420 try { 421 if (man != null) { 422 definePackage(pkgname, man, url); 423 } else { 424 definePackage(pkgname, null, null, null, null, null, null, null); 425 } 426 } catch (IllegalArgumentException iae) { 427 // parallel-capable class loaders: re-verify in case of a 428 // race condition 429 if (getAndVerifyPackage(pkgname, man, url) == null) { 430 // Should never happen 431 throw new AssertionError("Cannot find package " + 432 pkgname); 433 } 434 } 435 } 436 } 437 438 /* 439 * Defines a Class using the class bytes obtained from the specified 440 * Resource. The resulting Class must be resolved before it can be 441 * used. 442 */ defineClass(String name, Resource res)443 private Class<?> defineClass(String name, Resource res) throws IOException { 444 long t0 = System.nanoTime(); 445 int i = name.lastIndexOf('.'); 446 URL url = res.getCodeSourceURL(); 447 if (i != -1) { 448 String pkgname = name.substring(0, i); 449 // Check if package already loaded. 450 Manifest man = res.getManifest(); 451 definePackageInternal(pkgname, man, url); 452 } 453 // Now read the class bytes and define the class 454 java.nio.ByteBuffer bb = res.getByteBuffer(); 455 if (bb != null) { 456 // Use (direct) ByteBuffer: 457 CodeSigner[] signers = res.getCodeSigners(); 458 CodeSource cs = new CodeSource(url, signers); 459 // Android-removed: Android doesn't use sun.misc.PerfCounter. 460 // sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); 461 return defineClass(name, bb, cs); 462 } else { 463 byte[] b = res.getBytes(); 464 // must read certificates AFTER reading bytes. 465 CodeSigner[] signers = res.getCodeSigners(); 466 CodeSource cs = new CodeSource(url, signers); 467 // Android-removed: Android doesn't use sun.misc.PerfCounter. 468 // sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); 469 return defineClass(name, b, 0, b.length, cs); 470 } 471 } 472 473 /** 474 * Defines a new package by name in this ClassLoader. The attributes 475 * contained in the specified Manifest will be used to obtain package 476 * version and sealing information. For sealed packages, the additional 477 * URL specifies the code source URL from which the package was loaded. 478 * 479 * @param name the package name 480 * @param man the Manifest containing package version and sealing 481 * information 482 * @param url the code source url for the package, or null if none 483 * @exception IllegalArgumentException if the package name duplicates 484 * an existing package either in this class loader or one 485 * of its ancestors 486 * @return the newly defined Package object 487 */ definePackage(String name, Manifest man, URL url)488 protected Package definePackage(String name, Manifest man, URL url) 489 throws IllegalArgumentException 490 { 491 String path = name.replace('.', '/').concat("/"); 492 String specTitle = null, specVersion = null, specVendor = null; 493 String implTitle = null, implVersion = null, implVendor = null; 494 String sealed = null; 495 URL sealBase = null; 496 497 Attributes attr = man.getAttributes(path); 498 if (attr != null) { 499 specTitle = attr.getValue(Name.SPECIFICATION_TITLE); 500 specVersion = attr.getValue(Name.SPECIFICATION_VERSION); 501 specVendor = attr.getValue(Name.SPECIFICATION_VENDOR); 502 implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); 503 implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION); 504 implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); 505 sealed = attr.getValue(Name.SEALED); 506 } 507 attr = man.getMainAttributes(); 508 if (attr != null) { 509 if (specTitle == null) { 510 specTitle = attr.getValue(Name.SPECIFICATION_TITLE); 511 } 512 if (specVersion == null) { 513 specVersion = attr.getValue(Name.SPECIFICATION_VERSION); 514 } 515 if (specVendor == null) { 516 specVendor = attr.getValue(Name.SPECIFICATION_VENDOR); 517 } 518 if (implTitle == null) { 519 implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); 520 } 521 if (implVersion == null) { 522 implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION); 523 } 524 if (implVendor == null) { 525 implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); 526 } 527 if (sealed == null) { 528 sealed = attr.getValue(Name.SEALED); 529 } 530 } 531 if ("true".equalsIgnoreCase(sealed)) { 532 sealBase = url; 533 } 534 return definePackage(name, specTitle, specVersion, specVendor, 535 implTitle, implVersion, implVendor, sealBase); 536 } 537 538 /* 539 * Returns true if the specified package name is sealed according to the 540 * given manifest. 541 */ isSealed(String name, Manifest man)542 private boolean isSealed(String name, Manifest man) { 543 String path = name.replace('.', '/').concat("/"); 544 Attributes attr = man.getAttributes(path); 545 String sealed = null; 546 if (attr != null) { 547 sealed = attr.getValue(Name.SEALED); 548 } 549 if (sealed == null) { 550 if ((attr = man.getMainAttributes()) != null) { 551 sealed = attr.getValue(Name.SEALED); 552 } 553 } 554 return "true".equalsIgnoreCase(sealed); 555 } 556 557 /** 558 * Finds the resource with the specified name on the URL search path. 559 * 560 * @param name the name of the resource 561 * @return a {@code URL} for the resource, or {@code null} 562 * if the resource could not be found, or if the loader is closed. 563 */ findResource(final String name)564 public URL findResource(final String name) { 565 /* 566 * The same restriction to finding classes applies to resources 567 */ 568 URL url = AccessController.doPrivileged( 569 new PrivilegedAction<URL>() { 570 public URL run() { 571 return ucp.findResource(name, true); 572 } 573 }, acc); 574 575 return url != null ? ucp.checkURL(url) : null; 576 } 577 578 /** 579 * Returns an Enumeration of URLs representing all of the resources 580 * on the URL search path having the specified name. 581 * 582 * @param name the resource name 583 * @exception IOException if an I/O exception occurs 584 * @return an {@code Enumeration} of {@code URL}s 585 * If the loader is closed, the Enumeration will be empty. 586 */ findResources(final String name)587 public Enumeration<URL> findResources(final String name) 588 throws IOException 589 { 590 final Enumeration<URL> e = ucp.findResources(name, true); 591 592 return new Enumeration<URL>() { 593 private URL url = null; 594 595 private boolean next() { 596 if (url != null) { 597 return true; 598 } 599 do { 600 URL u = AccessController.doPrivileged( 601 new PrivilegedAction<URL>() { 602 public URL run() { 603 if (!e.hasMoreElements()) 604 return null; 605 return e.nextElement(); 606 } 607 }, acc); 608 if (u == null) 609 break; 610 url = ucp.checkURL(u); 611 } while (url == null); 612 return url != null; 613 } 614 615 public URL nextElement() { 616 if (!next()) { 617 throw new NoSuchElementException(); 618 } 619 URL u = url; 620 url = null; 621 return u; 622 } 623 624 public boolean hasMoreElements() { 625 return next(); 626 } 627 }; 628 } 629 630 /** 631 * Returns the permissions for the given codesource object. 632 * The implementation of this method first calls super.getPermissions 633 * and then adds permissions based on the URL of the codesource. 634 * <p> 635 * If the protocol of this URL is "jar", then the permission granted 636 * is based on the permission that is required by the URL of the Jar 637 * file. 638 * <p> 639 * If the protocol is "file" and there is an authority component, then 640 * permission to connect to and accept connections from that authority 641 * may be granted. If the protocol is "file" 642 * and the path specifies a file, then permission to read that 643 * file is granted. If protocol is "file" and the path is 644 * a directory, permission is granted to read all files 645 * and (recursively) all files and subdirectories contained in 646 * that directory. 647 * <p> 648 * If the protocol is not "file", then permission 649 * to connect to and accept connections from the URL's host is granted. 650 * @param codesource the codesource 651 * @exception NullPointerException if {@code codesource} is {@code null}. 652 * @return the permissions granted to the codesource 653 */ getPermissions(CodeSource codesource)654 protected PermissionCollection getPermissions(CodeSource codesource) 655 { 656 PermissionCollection perms = super.getPermissions(codesource); 657 658 URL url = codesource.getLocation(); 659 660 Permission p; 661 URLConnection urlConnection; 662 663 try { 664 urlConnection = url.openConnection(); 665 p = urlConnection.getPermission(); 666 } catch (java.io.IOException ioe) { 667 p = null; 668 urlConnection = null; 669 } 670 671 if (p instanceof FilePermission) { 672 // if the permission has a separator char on the end, 673 // it means the codebase is a directory, and we need 674 // to add an additional permission to read recursively 675 String path = p.getName(); 676 if (path.endsWith(File.separator)) { 677 path += "-"; 678 p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION); 679 } 680 } else if ((p == null) && (url.getProtocol().equals("file"))) { 681 String path = url.getFile().replace('/', File.separatorChar); 682 path = ParseUtil.decode(path); 683 if (path.endsWith(File.separator)) 684 path += "-"; 685 p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION); 686 } else { 687 /** 688 * Not loading from a 'file:' URL so we want to give the class 689 * permission to connect to and accept from the remote host 690 * after we've made sure the host is the correct one and is valid. 691 */ 692 URL locUrl = url; 693 if (urlConnection instanceof JarURLConnection) { 694 locUrl = ((JarURLConnection)urlConnection).getJarFileURL(); 695 } 696 String host = locUrl.getHost(); 697 if (host != null && (host.length() > 0)) 698 p = new SocketPermission(host, 699 SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION); 700 } 701 702 // make sure the person that created this class loader 703 // would have this permission 704 705 if (p != null) { 706 final SecurityManager sm = System.getSecurityManager(); 707 if (sm != null) { 708 final Permission fp = p; 709 AccessController.doPrivileged(new PrivilegedAction<Void>() { 710 public Void run() throws SecurityException { 711 sm.checkPermission(fp); 712 return null; 713 } 714 }, acc); 715 } 716 perms.add(p); 717 } 718 return perms; 719 } 720 721 /** 722 * Creates a new instance of URLClassLoader for the specified 723 * URLs and parent class loader. If a security manager is 724 * installed, the {@code loadClass} method of the URLClassLoader 725 * returned by this method will invoke the 726 * {@code SecurityManager.checkPackageAccess} method before 727 * loading the class. 728 * 729 * @param urls the URLs to search for classes and resources 730 * @param parent the parent class loader for delegation 731 * @exception NullPointerException if {@code urls} is {@code null}. 732 * @return the resulting class loader 733 */ newInstance(final URL[] urls, final ClassLoader parent)734 public static URLClassLoader newInstance(final URL[] urls, 735 final ClassLoader parent) { 736 // Save the caller's context 737 final AccessControlContext acc = AccessController.getContext(); 738 // Need a privileged block to create the class loader 739 URLClassLoader ucl = AccessController.doPrivileged( 740 new PrivilegedAction<URLClassLoader>() { 741 public URLClassLoader run() { 742 return new FactoryURLClassLoader(urls, parent, acc); 743 } 744 }); 745 return ucl; 746 } 747 748 /** 749 * Creates a new instance of URLClassLoader for the specified 750 * URLs and default parent class loader. If a security manager is 751 * installed, the {@code loadClass} method of the URLClassLoader 752 * returned by this method will invoke the 753 * {@code SecurityManager.checkPackageAccess} before 754 * loading the class. 755 * 756 * @param urls the URLs to search for classes and resources 757 * @exception NullPointerException if {@code urls} is {@code null}. 758 * @return the resulting class loader 759 */ newInstance(final URL[] urls)760 public static URLClassLoader newInstance(final URL[] urls) { 761 // Save the caller's context 762 final AccessControlContext acc = AccessController.getContext(); 763 // Need a privileged block to create the class loader 764 URLClassLoader ucl = AccessController.doPrivileged( 765 new PrivilegedAction<URLClassLoader>() { 766 public URLClassLoader run() { 767 return new FactoryURLClassLoader(urls, acc); 768 } 769 }); 770 return ucl; 771 } 772 773 static { 774 // Android-removed: SharedSecrets.setJavaNetAccess call. Android doesn't use it. 775 /*sun.misc.SharedSecrets.setJavaNetAccess ( 776 new sun.misc.JavaNetAccess() { 777 public URLClassPath getURLClassPath (URLClassLoader u) { 778 return u.ucp; 779 } 780 781 public String getOriginalHostName(InetAddress ia) { 782 return ia.holder.getOriginalHostName(); 783 } 784 } 785 );*/ ClassLoader.registerAsParallelCapable()786 ClassLoader.registerAsParallelCapable(); 787 } 788 } 789 790 final class FactoryURLClassLoader extends URLClassLoader { 791 792 static { 793 ClassLoader.registerAsParallelCapable(); 794 } 795 796 FactoryURLClassLoader(URL[] urls, ClassLoader parent, 797 AccessControlContext acc) { 798 super(urls, parent, acc); 799 } 800 801 FactoryURLClassLoader(URL[] urls, AccessControlContext acc) { 802 super(urls, acc); 803 } 804 805 public final Class<?> loadClass(String name, boolean resolve) 806 throws ClassNotFoundException 807 { 808 // First check if we have permission to access the package. This 809 // should go away once we've added support for exported packages. 810 SecurityManager sm = System.getSecurityManager(); 811 if (sm != null) { 812 int i = name.lastIndexOf('.'); 813 if (i != -1) { 814 sm.checkPackageAccess(name.substring(0, i)); 815 } 816 } 817 return super.loadClass(name, resolve); 818 } 819 } 820