diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-30 18:16:00 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-30 18:16:00 +0000 |
commit | 31b99cc56c35a556ca59bc2009049fe4afcee73d (patch) | |
tree | 6b8d006ff1e5363ff7071fe6e79480680b240d33 /libjava | |
parent | ffed53c48e396362cc94c253cc7fe3569f730f81 (diff) | |
download | gcc-31b99cc56c35a556ca59bc2009049fe4afcee73d.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@56685 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 31 | ||||
-rw-r--r-- | libjava/java/net/JarURLConnection.java | 15 | ||||
-rw-r--r-- | libjava/java/net/PlainDatagramSocketImpl.java | 5 | ||||
-rw-r--r-- | libjava/java/net/PlainSocketImpl.java | 7 | ||||
-rw-r--r-- | libjava/java/net/Socket.java | 63 | ||||
-rw-r--r-- | libjava/java/net/SocketImpl.java | 16 | ||||
-rw-r--r-- | libjava/java/net/SocketOptions.java | 7 | ||||
-rw-r--r-- | libjava/java/net/URL.java | 33 | ||||
-rw-r--r-- | libjava/java/net/URLClassLoader.java | 177 | ||||
-rw-r--r-- | libjava/java/net/natPlainDatagramSocketImpl.cc | 9 | ||||
-rw-r--r-- | libjava/java/net/natPlainSocketImpl.cc | 44 |
11 files changed, 392 insertions, 15 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 06211f11563..33c9bb40fc0 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,34 @@ +2002-08-29 Tom Tromey <tromey@redhat.com> + + * 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. + 2002-08-29 Michael Koch <konqueror@gmx.de> * java/net/DatagramPacket.java: updated to JDK 1.4 API diff --git a/libjava/java/net/JarURLConnection.java b/libjava/java/net/JarURLConnection.java index f0b3b5df343..5ee438dd515 100644 --- a/libjava/java/net/JarURLConnection.java +++ b/libjava/java/net/JarURLConnection.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. @@ -15,6 +15,7 @@ import java.util.zip.*; import java.util.Map; import java.util.Vector; import java.util.Hashtable; +import java.security.cert.Certificate; /** * @author Kresten Krab Thorup <krab@gnu.org> @@ -316,4 +317,16 @@ public abstract class JarURLConnection extends URLConnection hdrHash.put(key.toLowerCase(), Long.toString(len)); } + /** + * Returns an array of Certificate objects for the jar file entry specified + * by this URL or null if there are none + * + * @return A Certificate array + * + * @exception IOException If an error occurs + */ + public Certificate[] getCertificates() throws IOException + { + return getJarEntry().getCertificates(); + } } diff --git a/libjava/java/net/PlainDatagramSocketImpl.java b/libjava/java/net/PlainDatagramSocketImpl.java index 55ea468dadc..5f8a559557c 100644 --- a/libjava/java/net/PlainDatagramSocketImpl.java +++ b/libjava/java/net/PlainDatagramSocketImpl.java @@ -1,6 +1,6 @@ // PlainDatagramSocketImpl.java - Implementation of DatagramSocketImpl. -/* Copyright (C) 1999 Free Software Foundation +/* Copyright (C) 1999, 2002 Free Software Foundation This file is part of libgcj. @@ -33,7 +33,8 @@ class PlainDatagramSocketImpl extends DatagramSocketImpl _Jv_SO_LINGER_ = SocketOptions.SO_LINGER, _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT, _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF, - _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF; + _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF, + _Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE; int fnum = -1; diff --git a/libjava/java/net/PlainSocketImpl.java b/libjava/java/net/PlainSocketImpl.java index 354d652a5bf..2146f5e9a7d 100644 --- a/libjava/java/net/PlainSocketImpl.java +++ b/libjava/java/net/PlainSocketImpl.java @@ -32,7 +32,8 @@ class PlainSocketImpl extends SocketImpl _Jv_SO_LINGER_ = SocketOptions.SO_LINGER, _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT, _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF, - _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF; + _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF, + _Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE; /** * The OS file handle representing the socket. @@ -53,6 +54,10 @@ class PlainSocketImpl extends SocketImpl public native Object getOption(int optID) throws SocketException; + public native void shutdownInput () throws IOException; + + public native void shutdownOutput () throws IOException; + protected native void create (boolean stream) throws IOException; protected void connect (String host, int port) throws IOException diff --git a/libjava/java/net/Socket.java b/libjava/java/net/Socket.java index 6c0df5402b4..217e6956b5b 100644 --- a/libjava/java/net/Socket.java +++ b/libjava/java/net/Socket.java @@ -618,6 +618,47 @@ public class Socket } /** + * This method sets the value for the socket level socket option + * SO_KEEPALIVE. + * + * @param on True if SO_KEEPALIVE should be enabled + * + * @exception SocketException If an error occurs or Socket is not connected + * + * @since Java 1.3 + */ + public void setKeepAlive (boolean on) throws SocketException + { + if (impl == null) + throw new SocketException("Not connected"); + + impl.setOption(SocketOptions.SO_RCVBUF, new Boolean(on)); + } + + /** + * This method returns the value of the socket level socket option + * SO_KEEPALIVE. + * + * @return The setting + * + * @exception SocketException If an error occurs or Socket is not connected + * + * @since Java 1.3 + */ + public boolean getKeepAlive () throws SocketException + { + if (impl == null) + throw new SocketException("Not connected"); + + Object buf = impl.getOption(SocketOptions.SO_RCVBUF); + + if (buf instanceof Boolean) + return(((Boolean)buf).booleanValue()); + else + throw new SocketException("Internal Error: Unexpected type"); + } + + /** * Closes the socket. * * @exception IOException If an error occurs @@ -667,4 +708,26 @@ public class Socket factory = fac; } + + /** + * Closes the input side of the socket stream. + * + * @exception IOException If an error occurs. + */ + public void shutdownInput() throws IOException + { + if (impl != null) + impl.shutdownInput(); + } + + /** + * Closes the output side of the socket stream. + * + * @exception IOException If an error occurs. + */ + public void shutdownOutput() throws IOException + { + if (impl != null) + impl.shutdownOutput(); + } } diff --git a/libjava/java/net/SocketImpl.java b/libjava/java/net/SocketImpl.java index fb5a60ca520..7dcf87de629 100644 --- a/libjava/java/net/SocketImpl.java +++ b/libjava/java/net/SocketImpl.java @@ -264,4 +264,20 @@ public abstract class SocketImpl implements SocketOptions * @XXX This redeclaration from SocketOptions is a workaround to a gcj bug. */ public abstract Object getOption(int option_id) throws SocketException; + + /** + * Shut down the input side of this socket. Subsequent reads will + * return end-of-file. + * + * @exception IOException if an error occurs + */ + public abstract void shutdownInput () throws IOException; + + /** + * Shut down the output side of this socket. Subsequent writes will + * fail with an IOException. + * + * @exception IOException if an error occurs + */ + public abstract void shutdownOutput () throws IOException; } diff --git a/libjava/java/net/SocketOptions.java b/libjava/java/net/SocketOptions.java index 7dcba2a67a6..bf57450d037 100644 --- a/libjava/java/net/SocketOptions.java +++ b/libjava/java/net/SocketOptions.java @@ -1,5 +1,5 @@ /* SocketOptions.java -- Implements options for sockets (duh!) - Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -62,6 +62,11 @@ public interface SocketOptions */ /** + * Option id for the SO_KEEPALIVE value + */ +static final int SO_KEEPALIVE = 0x8; + +/** * Option id for the SO_LINGER value */ static final int SO_LINGER = 0x80; // 128 diff --git a/libjava/java/net/URL.java b/libjava/java/net/URL.java index a3e9d784cef..73edeca415d 100644 --- a/libjava/java/net/URL.java +++ b/libjava/java/net/URL.java @@ -175,7 +175,8 @@ public final class URL implements Serializable this.handler = setURLStreamHandler(protocol); if (this.handler == null) - throw new MalformedURLException("Protocol handler not found: " + protocol); + throw new MalformedURLException("Protocol handler not found: " + + protocol); // JDK 1.2 doc for parseURL specifically states that any '#' ref // is to be excluded by passing the 'limit' as the indexOf the '#' @@ -245,6 +246,12 @@ public final class URL implements Serializable return ref; } + public String getUserInfo () + { + int at = host.indexOf('@'); + return at < 0 ? null : host.substring(0, at); + } + public int hashCode() { // JCL book says this is computed using (only) the hashcodes of the @@ -299,6 +306,30 @@ public final class URL implements Serializable hashCode = hashCode(); // Used for serialization. } + /** @since 1.3 */ + protected void set(String protocol, String host, int port, + String authority, String userInfo, + String path, String query, String ref) + { + // TBD: Theoretically, a poorly written StreamHandler could pass an + // invalid protocol. It will cause the handler to be set to null + // thus overriding a valid handler. Callers of this method should + // be aware of this. + this.handler = setURLStreamHandler(protocol); + this.protocol = protocol; + if (userInfo == null) + this.host = host; + else + this.host = userInfo + "@" + host; + this.port = port; + if (query == null) + this.file = path; + else + this.file = path + "?" + query; + this.ref = ref; + hashCode = hashCode(); // Used for serialization. + } + public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) { diff --git a/libjava/java/net/URLClassLoader.java b/libjava/java/net/URLClassLoader.java index 4fce6250e4a..3afb8f1861c 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); + } +} diff --git a/libjava/java/net/natPlainDatagramSocketImpl.cc b/libjava/java/net/natPlainDatagramSocketImpl.cc index e581f08db5c..bb306e202bd 100644 --- a/libjava/java/net/natPlainDatagramSocketImpl.cc +++ b/libjava/java/net/natPlainDatagramSocketImpl.cc @@ -524,6 +524,10 @@ java::net::PlainDatagramSocketImpl::setOption (jint optID, throw new java::net::SocketException ( JvNewStringUTF ("SO_LINGER not valid for UDP")); return; + case _Jv_SO_KEEPALIVE_ : + throw new java::net::SocketException ( + JvNewStringUTF ("SO_KEEPALIVE not valid for UDP")); + return; case _Jv_SO_SNDBUF_ : case _Jv_SO_RCVBUF_ : #if defined(SO_SNDBUF) && defined(SO_RCVBUF) @@ -613,11 +617,14 @@ java::net::PlainDatagramSocketImpl::getOption (jint optID) throw new java::net::SocketException ( JvNewStringUTF ("TCP_NODELAY not valid for UDP")); break; - case _Jv_SO_LINGER_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_LINGER not valid for UDP")); break; + case _Jv_SO_KEEPALIVE_ : + throw new java::net::SocketException ( + JvNewStringUTF ("SO_KEEPALIVE not valid for UDP")); + break; case _Jv_SO_RCVBUF_ : case _Jv_SO_SNDBUF_ : #if defined(SO_SNDBUF) && defined(SO_RCVBUF) diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc index 370c9946177..f82aa6bb47c 100644 --- a/libjava/java/net/natPlainSocketImpl.cc +++ b/libjava/java/net/natPlainSocketImpl.cc @@ -222,6 +222,20 @@ java::net::PlainSocketImpl::close(void) JvNewStringLatin1 ("SocketImpl.close: unimplemented")); } +void +java::net::PlainSocketImpl::shutdownInput (void) +{ + throw new SocketException ( + JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented")); +} + +void +java::net::PlainSocketImpl::shutdownOutput (void) +{ + throw new SocketException ( + JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented")); +} + #else /* DISABLE_JAVA_NET */ union SockAddr @@ -722,12 +736,18 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) #ifdef TCP_NODELAY if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val, val_len) != 0) - goto error; + goto error; #else throw new java::lang::InternalError ( JvNewStringUTF ("TCP_NODELAY not supported")); #endif /* TCP_NODELAY */ return; + + case _Jv_SO_KEEPALIVE_ : + if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, + val_len) != 0) + goto error; + case _Jv_SO_LINGER_ : #ifdef SO_LINGER struct linger l_val; @@ -816,6 +836,14 @@ java::net::PlainSocketImpl::getOption (jint optID) JvNewStringUTF ("SO_LINGER not supported")); #endif break; + + case _Jv_SO_KEEPALIVE_ : + if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, + &val_len) != 0) + goto error; + else + return new java::lang::Boolean (val != 0); + case _Jv_SO_RCVBUF_ : case _Jv_SO_SNDBUF_ : #if defined(SO_SNDBUF) && defined(SO_RCVBUF) @@ -876,4 +904,18 @@ java::net::PlainSocketImpl::getOption (jint optID) throw new java::net::SocketException (JvNewStringUTF (strerr)); } +void +java::net::PlainSocketImpl::shutdownInput (void) +{ + if (::shutdown (fnum, 0)) + throw new SocketException (JvNewStringUTF (strerror (errno))); +} + +void +java::net::PlainSocketImpl::shutdownOutput (void) +{ + if (::shutdown (fnum, 1)) + throw new SocketException (JvNewStringUTF (strerror (errno))); +} + #endif /* DISABLE_JAVA_NET */ |