📄 urlclassloader.java
字号:
throws IllegalArgumentException { Attributes attr = manifest.getMainAttributes(); String specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE); String specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION); String specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR); String implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE); String implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); String implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR); // Look if the Manifest indicates that this package is sealed // XXX - most likely not completely correct! // Shouldn't we also check the sealed attribute of the complete jar? // http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled // But how do we get that jar manifest here? String sealed = attr.getValue(Attributes.Name.SEALED); if ("false".equals(sealed)) { // make sure that the URL is null so the package is not sealed url = null; } return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, url); } /** * Finds (the first) class by name from one of the locations. The locations * are searched in the order they were added to the URLClassLoader. * * @param className the classname to find * @exception ClassNotFoundException when the class could not be found or * loaded * @return a Class object representing the found class */ protected Class findClass(final String className) throws ClassNotFoundException { // Just try to find the resource by the (almost) same name String resourceName = className.replace('.', '/') + ".class"; Resource resource = findURLResource(resourceName); if (resource == null) throw new ClassNotFoundException(className + " not found in " + urls); // Try to read the class data, create the CodeSource, Package and // construct the class (and watch out for those nasty IOExceptions) try { byte [] data; InputStream in = resource.getInputStream(); int length = resource.getLength(); if (length != -1) { // We know the length of the data. // Just try to read it in all at once data = new byte[length]; int pos = 0; while(length - pos > 0) { int len = in.read(data, pos, length - pos); if (len == -1) throw new EOFException("Not enough data reading from: " + in); pos += len; } } else { // We don't know the data length. // Have to read it in chunks. ByteArrayOutputStream out = new ByteArrayOutputStream(4096); byte b[] = new byte[4096]; int l = 0; while (l != -1) { l = in.read(b); if (l != -1) out.write(b, 0, l); } data = out.toByteArray(); } final byte[] classData = data; // Now get the CodeSource final CodeSource source = resource.getCodeSource(); // Find out package name String packageName = null; int lastDot = className.lastIndexOf('.'); if (lastDot != -1) packageName = className.substring(0, lastDot); if (packageName != null && getPackage(packageName) == null) { // define the package Manifest manifest = resource.loader.getManifest(); if (manifest == null) definePackage(packageName, null, null, null, null, null, null, null); else definePackage(packageName, manifest, resource.loader.baseURL); } // And finally construct the class! SecurityManager sm = System.getSecurityManager(); if (sm != null && securityContext != null) { return (Class)AccessController.doPrivileged (new PrivilegedAction() { public Object run() { return defineClass(className, classData, 0, classData.length, source); } }, securityContext); } else return defineClass(className, classData, 0, classData.length, source); } catch (IOException ioe) { throw new ClassNotFoundException(className, ioe); } } /** * Finds the first occurrence of a resource that can be found. The locations * are searched in the order they were added to the URLClassLoader. * * @param resourceName the resource name to look for * @return the URLResource for the resource if found, null otherwise */ private Resource findURLResource(String resourceName) { int max = urls.size(); for (int i = 0; i < max; i++) { URLLoader loader = (URLLoader)urlinfos.elementAt(i); if (loader == null) continue; Resource resource = loader.getResource(resourceName); if (resource != null) return resource; } return null; } /** * Finds the first occurrence of a resource that can be found. * * @param resourceName the resource name to look for * @return the URL if found, null otherwise */ public URL findResource(String resourceName) { Resource resource = findURLResource(resourceName); if (resource != null) return resource.getURL(); // Resource not found return null; } /** * If the URLStreamHandlerFactory has been set this return the appropriate * URLStreamHandler for the given protocol, if not set returns null. * * @param protocol the protocol for which we need a URLStreamHandler * @return the appropriate URLStreamHandler or null */ URLStreamHandler getURLStreamHandler(String protocol) { if (factory == null) return null; URLStreamHandler handler; synchronized (factoryCache) { // check if there're handler for the same protocol in cache HashMap cache = (HashMap)factoryCache.get(factory); handler = (URLStreamHandler)cache.get(protocol); if(handler == null) { // add it to cache handler = factory.createURLStreamHandler(protocol); cache.put(protocol, handler); } } return handler; } /** * Finds all the resources with a particular name from all the locations. * * @exception IOException when an error occurs accessing one of the * locations * @param resourceName the name of the resource to lookup * @return a (possible empty) enumeration of URLs where the resource can be * found */ public Enumeration findResources(String resourceName) throws IOException { Vector resources = new Vector(); int max = urls.size(); for (int i = 0; i < max; i++) { URLLoader loader = (URLLoader)urlinfos.elementAt(i); Resource resource = loader.getResource(resourceName); if (resource != null) resources.add(resource.getURL()); } return resources.elements(); } /** * Returns the permissions needed to access a particular code * source. These permissions includes those returned by * <code>SecureClassLoader.getPermissions()</code> and the actual * permissions to access the objects referenced by the URL of the * code source. The extra permissions added depend on the protocol * and file portion of the URL in the code source. If the URL has * the "file" protocol ends with a '/' character then it must be a * directory and a file Permission to read everything in that * directory and all subdirectories is added. If the URL had the * "file" protocol and doesn't end with a '/' character then it must * be a normal file and a file permission to read that file is * added. If the <code>URL</code> has any other protocol then a * socket permission to connect and accept connections from the host * portion of the URL is added. * * @param source The codesource that needs the permissions to be accessed * @return the collection of permissions needed to access the code resource * @see java.security.SecureClassLoader#getPermissions() */ protected PermissionCollection getPermissions(CodeSource source) { // XXX - This implementation does exactly as the Javadoc describes. // But maybe we should/could use URLConnection.getPermissions()? // First get the permissions that would normally be granted PermissionCollection permissions = super.getPermissions(source); // Now add the any extra permissions depending on the URL location URL url = source.getLocation(); String protocol = url.getProtocol(); if (protocol.equals("file")) { String file = url.getFile(); // If the file end in / it must be an directory if (file.endsWith("/") || file.endsWith(File.separator)) { // Grant permission to read everything in that directory and // all subdirectories permissions.add(new FilePermission(file + "-", "read")); } else { // It is a 'normal' file // Grant permission to access that file permissions.add(new FilePermission(file, "read")); } } else { // Grant permission to connect to and accept connections from host String host = url.getHost(); if (host != null) permissions.add(new SocketPermission(host, "connect,accept")); } return permissions; } /** * Returns all the locations that this class loader currently uses the * resolve classes and resource. This includes both the initially supplied * URLs as any URLs added later by the loader. * @return All the currently used URLs */ public URL[] getURLs() { return (URL[]) urls.toArray(new URL[urls.size()]); } /** * Creates a new instance of a <code>URLClassLoader</code> that gets * classes from the supplied <code>URL</code>s. This class loader * will have as parent the standard system class loader. * * @param urls the initial URLs used to resolve classes and * resources * * @exception SecurityException when the calling code does not have * permission to access the given <code>URL</code>s */ public static URLClassLoader newInstance(URL urls[]) throws SecurityException { return newInstance(urls, null); } /** * Creates a new instance of a <code>URLClassLoader</code> that gets * classes from the supplied <code>URL</code>s and with the supplied * loader as parent class loader. * * @param urls the initial URLs used to resolve classes and * resources * @param parent the parent class loader * * @exception SecurityException when the calling code does not have * permission to access the given <code>URL</code>s */ public static URLClassLoader newInstance(URL urls[], final ClassLoader parent) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm == null) return new URLClassLoader(urls, parent); else { final Object securityContext = sm.getSecurityContext(); // XXX - What to do with anything else then an AccessControlContext? if (!(securityContext instanceof AccessControlContext)) throw new SecurityException ("securityContext must be AccessControlContext: " + securityContext); URLClassLoader loader = (URLClassLoader)AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return new URLClassLoader (parent, (AccessControlContext)securityContext); } }); loader.addURLs(urls); return loader; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -