diff options
author | Tom Tromey <tromey@redhat.com> | 2002-08-30 18:16:00 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2002-08-30 18:16:00 +0000 |
commit | 4c322bff290ba4cf86aefa934a8c26acd3350aae (patch) | |
tree | 6b8d006ff1e5363ff7071fe6e79480680b240d33 /libjava/java/net/URLClassLoader.java | |
parent | 55f49e3d50d0a2d4158ecb93fbb8d079f396b1d2 (diff) | |
download | gcc-4c322bff290ba4cf86aefa934a8c26acd3350aae.zip gcc-4c322bff290ba4cf86aefa934a8c26acd3350aae.tar.gz gcc-4c322bff290ba4cf86aefa934a8c26acd3350aae.tar.bz2 |
JarURLConnection.java (getCertificates): New method from Classpath.
* java/net/JarURLConnection.java (getCertificates): New method
from Classpath.
* java/net/URLClassLoader.java (URLClassLoader): Extends
SecureClassLoader.
(definePackage): New method from Classpath.
(getPermissions): Likewise.
(newInstance): Likewise.
(findClass): Construct CodeSource for new class (from Classpath).
* java/net/SocketImpl.java (shutdownInput, shutdownOutput): New
methods.
* java/net/URL.java (getUserInfo): New method.
(set(String,String,int,String,String,String,String,String)): New
method.
* java/net/PlainSocketImpl.java (_Jv_SO_KEEPALIVE_): Define.
(shutdownInput, shutdownOutput): Declare.
* java/net/PlainDatagramSocketImpl.java (_Jv_SO_KEEPALIVE_):
Define.
* java/net/natPlainSocketImpl.cc (setOption): Handle keepalive.
(getOption): Likewise.
(shutdownInput): New method.
(shutdownOutput): Likewise.
* java/net/natPlainDatagramSocketImpl.cc (setOption): Handle
keepalive.
(getOption): Likewise.
* java/net/SocketOptions.java (SO_KEEPALIVE): New constant.
* java/net/Socket.java (setKeepAlive): New method.
(getKeepAlive): Likewise.
(shutdownInput, shutdownOutput): New methods.
From-SVN: r56685
Diffstat (limited to 'libjava/java/net/URLClassLoader.java')
-rw-r--r-- | libjava/java/net/URLClassLoader.java | 177 |
1 files changed, 170 insertions, 7 deletions
diff --git a/libjava/java/net/URLClassLoader.java b/libjava/java/net/URLClassLoader.java index 4fce625..3afb8f1 100644 --- a/libjava/java/net/URLClassLoader.java +++ b/libjava/java/net/URLClassLoader.java @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000 Free Software Foundation +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation This file is part of libgcj. @@ -12,11 +12,15 @@ import java.io.*; import java.util.jar.*; import java.util.Enumeration; import java.util.Vector; +import java.security.CodeSource; +import java.security.SecureClassLoader; +import java.security.PermissionCollection; +import java.security.cert.Certificate; /** * @since 1.2 */ -public class URLClassLoader extends ClassLoader +public class URLClassLoader extends SecureClassLoader { // The URLStreamHandlerFactory URLStreamHandlerFactory factory = null; @@ -228,12 +232,12 @@ public class URLClassLoader extends ClassLoader try { - URL u = getResource (name.replace ('.', '/') + ".class"); + URL url = getResource (name.replace ('.', '/') + ".class"); - if (u == null) + if (url == null) throw new ClassNotFoundException (name); - URLConnection connection = u.openConnection (); + URLConnection connection = url.openConnection (); InputStream is = connection.getInputStream (); int len = connection.getContentLength (); @@ -250,12 +254,171 @@ public class URLClassLoader extends ClassLoader off += c; } - return defineClass (name, data, 0, len); + // Now construct the CodeSource (if loaded from a jar file) + CodeSource source = null; + if (url.getProtocol().equals("jar")) + { + Certificate[] certificates = + ((JarURLConnection) connection).getCertificates(); + String u = url.toExternalForm (); + u = u.substring (4); //skip "jar:" + int i = u.indexOf ('!'); + if (i >= 0) + u = u.substring (0, i); + url = new URL("jar", "", u); + + source = new CodeSource(url, certificates); + } + else if (url.getProtocol().equals("file")) + { + try + { + String u = url.toExternalForm(); + // Skip "file:" and then get canonical directory name. + File f = new File(u.substring(5)); + f = f.getCanonicalFile(); + url = new URL("file", "", f.getParent()); + source = new CodeSource (url, null); + } + catch (IOException ignore) + { + } + } + + return defineClass (name, data, 0, len, source); } catch (java.io.IOException x) { throw new ClassNotFoundException(name); } } -} + /** + * Defines a Package based on the given name and the supplied manifest + * information. The manifest indicates the tile, version and + * vendor information of the specification and implementation and wheter the + * package is sealed. If the Manifest indicates that the package is sealed + * then the Package will be sealed with respect to the supplied URL. + * + * @exception IllegalArgumentException If this package name already exists + * in this class loader + * @param name The name of the package + * @param manifest The manifest describing the specification, + * implementation and sealing details of the package + * @param url the code source url to seal the package + * @return the defined Package + */ + protected Package definePackage(String name, Manifest manifest, URL url) + 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.3/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); + } + + /** + * 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 + * everthing 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 + * URL 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 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("/")) + { + // 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(); + permissions.add(new SocketPermission(host, "connect,accept")); + } + + return permissions; + } + + /** + * Creates a new instance of a URLClassLoader that gets classes from the + * supplied URLs. This class loader will have as parent the standard + * system class loader. + * @param urls the initial URLs used to resolve classes and resources + */ + public static URLClassLoader newInstance(URL urls[]) throws + SecurityException + { + return new URLClassLoader(urls); + } + + /** + * Creates a new instance of a URLClassLoader that gets classes from the + * supplied URLs 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 + */ + public static URLClassLoader newInstance(URL urls[], + ClassLoader parent) + throws SecurityException + { + return new URLClassLoader(urls, parent); + } +} |