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
This commit is contained in:
Tom Tromey 2002-08-30 18:16:00 +00:00 committed by Tom Tromey
parent 55f49e3d50
commit 4c322bff29
11 changed files with 392 additions and 15 deletions

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -617,6 +617,47 @@ public class Socket
throw new SocketException("Internal Error: Unexpected type");
}
/**
* 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.
*
@ -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();
}
}

View File

@ -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;
}

View File

@ -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.
@ -61,6 +61,11 @@ public interface SocketOptions
* Static Variables
*/
/**
* Option id for the SO_KEEPALIVE value
*/
static final int SO_KEEPALIVE = 0x8;
/**
* Option id for the SO_LINGER value
*/

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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 */