diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2007-01-09 19:58:05 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2007-01-09 19:58:05 +0000 |
commit | 97b8365cafc3a344a22d3980b8ed885f5c6d8357 (patch) | |
tree | 996a5f57d4a68c53473382e45cb22f574cb3e4db /libjava/classpath/vm | |
parent | c648dedbde727ca3f883bb5fd773aa4af70d3369 (diff) | |
download | gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.gz |
Merged gcj-eclipse branch to trunk.
From-SVN: r120621
Diffstat (limited to 'libjava/classpath/vm')
18 files changed, 1268 insertions, 341 deletions
diff --git a/libjava/classpath/vm/.cvsignore b/libjava/classpath/vm/.cvsignore new file mode 100644 index 00000000000..282522db034 --- /dev/null +++ b/libjava/classpath/vm/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/libjava/classpath/vm/reference/.cvsignore b/libjava/classpath/vm/reference/.cvsignore new file mode 100644 index 00000000000..282522db034 --- /dev/null +++ b/libjava/classpath/vm/reference/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/libjava/classpath/vm/reference/gnu/classpath/VMStackWalker.java b/libjava/classpath/vm/reference/gnu/classpath/VMStackWalker.java index e995c46341d..2214e757110 100644 --- a/libjava/classpath/vm/reference/gnu/classpath/VMStackWalker.java +++ b/libjava/classpath/vm/reference/gnu/classpath/VMStackWalker.java @@ -1,5 +1,5 @@ /* VMStackWalker.java -- Reference implementation of VM hooks for stack access - Copyright (C) 2005 Free Software Foundation + Copyright (C) 2005, 2006 Free Software Foundation This file is part of GNU Classpath. @@ -112,5 +112,20 @@ public final class VMStackWalker * is here to work around access permissions. */ public static native ClassLoader getClassLoader(Class cl); -} + /** + * Walk up the stack and return the first non-null class loader. + * If there aren't any non-null class loaders on the stack, return null. + */ + public static ClassLoader firstNonNullClassLoader() + { + Class[] stack = getClassContext(); + for (int i = 0; i < stack.length; i++) + { + ClassLoader loader = getClassLoader(stack[i]); + if (loader != null) + return loader; + } + return null; + } +} diff --git a/libjava/classpath/vm/reference/gnu/classpath/jdwp/VMVirtualMachine.java b/libjava/classpath/vm/reference/gnu/classpath/jdwp/VMVirtualMachine.java index d4985bf2f2e..d8616063d19 100644 --- a/libjava/classpath/vm/reference/gnu/classpath/jdwp/VMVirtualMachine.java +++ b/libjava/classpath/vm/reference/gnu/classpath/jdwp/VMVirtualMachine.java @@ -199,7 +199,7 @@ public class VMVirtualMachine * @return an array of virtual machine methods */ public static native VMMethod[] getAllClassMethods (Class klass) - throws JdwpException; + { return null; } /** * A factory method for getting valid virtual machine methods @@ -213,7 +213,7 @@ public class VMVirtualMachine * @throws JdwpException for any other error */ public static native VMMethod getClassMethod(Class klass, long id) - throws JdwpException; + { return null; } /** * Returns the thread's call stack diff --git a/libjava/classpath/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java b/libjava/classpath/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java index 193e3353517..43b9ae1a100 100644 --- a/libjava/classpath/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java +++ b/libjava/classpath/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java @@ -90,7 +90,7 @@ final class VMMemoryMXBeanImpl * information when memory is allocated and deallocated. The * format of the output is left up to the virtual machine. * - * @return true if verbose class loading output is on. + * @return true if verbose memory usage output is on. */ static native boolean isVerbose(); @@ -101,7 +101,7 @@ final class VMMemoryMXBeanImpl * may be called by multiple threads concurrently, but there * is only one global setting of verbosity that is affected. * - * @param verbose the new setting for verbose class loading + * @param verbose the new setting for verbose memory usage * output. */ static native void setVerbose(boolean verbose); diff --git a/libjava/classpath/vm/reference/gnu/java/net/VMPlainSocketImpl.java b/libjava/classpath/vm/reference/gnu/java/net/VMPlainSocketImpl.java index 76be558dcd4..916f9593087 100644 --- a/libjava/classpath/vm/reference/gnu/java/net/VMPlainSocketImpl.java +++ b/libjava/classpath/vm/reference/gnu/java/net/VMPlainSocketImpl.java @@ -38,15 +38,16 @@ exception statement from your version. */ package gnu.java.net; import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.SocketAddress; +import java.net.NetworkInterface; import java.net.SocketException; -import java.net.SocketImpl; import java.net.SocketOptions; -import java.net.UnknownHostException; import gnu.classpath.Configuration; +import gnu.java.nio.VMChannel; /** * The VM interface for {@link gnu.java.net.PlainSocketImpl}. @@ -56,6 +57,12 @@ import gnu.classpath.Configuration; */ public final class VMPlainSocketImpl { + /** Option id for time to live + */ + private static final int CP_IP_TTL = 0x1E61; + + private final State nfd; + /** * Static initializer to load native library. */ @@ -66,249 +73,440 @@ public final class VMPlainSocketImpl System.loadLibrary("javanet"); } } + + public VMPlainSocketImpl() + { + // XXX consider adding security check here. + nfd = new State(); + } + + public VMPlainSocketImpl(VMChannel channel) throws IOException + { + this(); + nfd.setChannelFD(channel.getState()); + } + + public State getState() + { + return nfd; + } - /** - * Sets the specified option on a socket to the passed in object. - * The optionId parameter is one of the defined constants in - * the SocketImpl interface. - * - * @param socket the socket object - * @param optionId the identifier of the option - * @param value the value to set the option to + /** This method exists to hide the CP_IP_TTL value from + * higher levels. * - * @throws SocketException if an error occurs + * Always think of JNode ... :) */ - static native void setOption(PlainSocketImpl socket, int optionId, Object value) - throws SocketException; + public void setTimeToLive(int ttl) + throws SocketException + { + try + { + setOption(nfd.getNativeFD(), CP_IP_TTL, ttl); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } - /** - * Returns the current setting of the specified option. The optionId - * is one of the defined constants in this interface. - * - * @param socket the socket object - * @param optionId the option identifier - * - * @return the current value of the option - * - * @throws SocketException ff an error occurs - */ - static native Object getOption(PlainSocketImpl socket, int optionId) + public int getTimeToLive() + throws SocketException + { + try + { + return getOption(nfd.getNativeFD(), CP_IP_TTL); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } + + public void setOption(int optionId, Object optionValue) + throws SocketException + { + int value; + if (optionValue instanceof Integer) + value = ((Integer) optionValue).intValue(); + else if (optionValue instanceof Boolean) + // Switching off the linger behavior is done by setting + // the value to -1. This is how the Java API interprets + // it. + value = ((Boolean) optionValue).booleanValue() + ? 1 + : (optionId == SocketOptions.SO_LINGER) + ? -1 + : 0; + else + throw new IllegalArgumentException("option value type " + + optionValue.getClass().getName()); + + try + { + setOption(nfd.getNativeFD(), optionId, value); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } + + private static native void setOption(int fd, int id, int value) throws SocketException; - /** - * Creates a new socket that is not bound to any local address/port and - * is not connected to any remote address/port. - * - * @param socket the socket object - * - * @throws IOException if something goes wrong while creating the socket - */ - static native void create(PlainSocketImpl socket) throws IOException; + public void setMulticastInterface(int optionId, InetAddress addr) + throws SocketException + { + try + { + if (addr instanceof Inet4Address) + setMulticastInterface(nfd.getNativeFD(), optionId, (Inet4Address) addr); + else if (addr instanceof Inet6Address) + { + NetworkInterface iface = NetworkInterface.getByInetAddress(addr); + setMulticastInterface6(nfd.getNativeFD(), optionId, iface.getName()); + } + else + throw new SocketException("Unknown address format: " + addr); + } + catch (SocketException se) + { + throw se; + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } - /** - * Connects to the remote address and port specified as arguments. - * - * @param socket the socket object - * @param addr the remote address to connect to - * @param port the remote port to connect to - * - * @throws IOException if an error occurs - */ - static native void connect(PlainSocketImpl socket, InetAddress addr, - int port) throws IOException; + private static native void setMulticastInterface(int fd, + int optionId, + Inet4Address addr); - /** - * Binds to the specified port on the specified addr. Note that this addr - * must represent a local IP address. **** How bind to INADDR_ANY? **** - * - * @param socket the socket object - * @param addr the address to bind to - * @param port the port number to bind to - * - * @exception IOException If an error occurs - */ - static native void bind(PlainSocketImpl socket, InetAddress addr, int port) - throws IOException; + private static native void setMulticastInterface6(int fd, + int optionId, + String ifName); /** - * Starts listening for connections on a socket. The queueLen parameter - * is how many pending connections will queue up waiting to be serviced - * before being accepted. If the queue of pending requests exceeds this - * number, additional connections will be refused. - * - * @param socket the socket object - * @param queueLen the length of the pending connection queue + * Get a socket option. This implementation is only required to support + * socket options that are boolean values, which include: + * + * SocketOptions.IP_MULTICAST_LOOP + * SocketOptions.SO_BROADCAST + * SocketOptions.SO_KEEPALIVE + * SocketOptions.SO_OOBINLINE + * SocketOptions.SO_REUSEADDR + * SocketOptions.TCP_NODELAY + * + * and socket options that are integer values, which include: * - * @exception IOException if an error occurs + * SocketOptions.IP_TOS + * SocketOptions.SO_LINGER + * SocketOptions.SO_RCVBUF + * SocketOptions.SO_SNDBUF + * SocketOptions.SO_TIMEOUT + * + * @param optionId The option ID to fetch. + * @return A {@link Boolean} or {@link Integer} containing the socket + * option. + * @throws SocketException */ - static native void listen(PlainSocketImpl socket, int queueLen) - throws IOException; + public Object getOption(int optionId) throws SocketException + { + int value; + try + { + value = getOption(nfd.getNativeFD(), optionId); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + + switch (optionId) + { + case SocketOptions.IP_MULTICAST_LOOP: + case SocketOptions.SO_BROADCAST: + case SocketOptions.SO_KEEPALIVE: + case SocketOptions.SO_OOBINLINE: + case SocketOptions.SO_REUSEADDR: + case SocketOptions.TCP_NODELAY: + return Boolean.valueOf(value != 0); + + case SocketOptions.IP_TOS: + case SocketOptions.SO_LINGER: + case SocketOptions.SO_RCVBUF: + case SocketOptions.SO_SNDBUF: + case SocketOptions.SO_TIMEOUT: + return new Integer(value); + + default: + throw new SocketException("getting option " + optionId + + " not supported here"); + } + } + + private static native int getOption(int fd, int id) throws SocketException; /** - * Accepts a new connection on this socket. + * Returns an Inet4Address or Inet6Address instance belonging to the + * interface which is set as the multicast interface. * - * @param socket the socket object - * @param impl the socket object to accept this connection. + * The optionId is provided to make it possible that the native + * implementation may do something different depending on whether + * the value is SocketOptions.IP_MULTICAST_IF or + * SocketOptions.IP_MULTICAST_IF2. */ - static native void accept(PlainSocketImpl socket, SocketImpl impl) - throws IOException; + public InetAddress getMulticastInterface(int optionId) + throws SocketException + { + try + { + return getMulticastInterface(nfd.getNativeFD(), optionId); + } + catch (IOException ioe) + { + SocketException se = new SocketException(); + se.initCause(ioe); + throw se; + } + } + private static native InetAddress getMulticastInterface(int fd, + int optionId); + /** - * Returns the number of bytes that the caller can read from this socket - * without blocking. - * - * @param socket the socket object + * Binds this socket to the given local address and port. * - * @return the number of readable bytes before blocking - * - * @throws IOException If an error occurs + * @param address The address to bind to; the InetAddress is either + * an IPv4 or IPv6 address. + * @throws IOException If binding fails; for example, if the port + * in the given InetSocketAddress is privileged, and the current + * process has insufficient privileges. */ - static native int available(PlainSocketImpl socket) throws IOException; - + public void bind(InetSocketAddress address) throws IOException + { + InetAddress addr = address.getAddress(); + if (addr instanceof Inet4Address) + { + bind (nfd.getNativeFD(), addr.getAddress(), address.getPort()); + } + else if (addr instanceof Inet6Address) + bind6 (nfd.getNativeFD(), addr.getAddress(), address.getPort()); + else + throw new SocketException ("unsupported address type"); + } + /** - * Closes the socket. This will cause any InputStream or OutputStream - * objects for this Socket to be closed as well. - * - * <p> - * Note that if the SO_LINGER option is set on this socket, then the - * operation could block. - * </p> - * - * @param socket the socket object + * Native bind function for IPv4 addresses. The addr array must be + * exactly four bytes long. + * + * VMs without native support need not implement this. * - * @throws IOException if an error occurs + * @param fd The native file descriptor integer. + * @param addr The IPv4 address, in network byte order. + * @param port The port to bind to. + * @throws IOException */ - static native void close(PlainSocketImpl socket) throws IOException; - + private static native void bind(int fd, byte[] addr, int port) + throws IOException; + /** - * Internal method used by SocketInputStream for reading data from - * the connection. Reads up to len bytes of data into the buffer - * buf starting at offset bytes into the buffer. - * - * @param socket the socket object - * - * @return the actual number of bytes read or -1 if end of stream. + * Native bind function for IPv6 addresses. The addr array must be + * exactly sixteen bytes long. + * + * VMs without native support need not implement this. * - * @throws IOException if an error occurs + * @param fd The native file descriptor integer. + * @param addr The IPv6 address, in network byte order. + * @param port The port to bind to. + * @throws IOException */ - static native int read(PlainSocketImpl socket, byte[] buf, int offset, - int len) throws IOException; + private static native void bind6(int fd, byte[] addr, int port) + throws IOException; /** - * Internal method used by SocketInputStream for reading data from - * the connection. Reads and returns one byte of data. - * - * @param socket the socket object - * - * @return read byte or -1 if end of stream. + * Listen on this socket for incoming connections. * - * @throws IOException if an error occurs + * @param backlog The backlog of connections. + * @throws IOException If listening fails. + * @see gnu.java.nio.VMChannel#accept() */ - static int read(PlainSocketImpl socket) throws IOException + public void listen(int backlog) throws IOException { - byte[] buf = new byte[1]; - if (read(socket, buf, 0, 1) > 0) - return buf[0] & 0xFF; - else - return -1; + listen(nfd.getNativeFD(), backlog); } - + /** - * Internal method used by SocketOuputStream for writing data to - * the connection. Writes up to len bytes of data from the buffer - * <code>buf</code> starting at <cod>offset</code> bytes into the buffer. + * Native listen function. VMs without native support need not implement + * this. * - * @param socket the socket object - * @param buf the buffer to write to the stream - * @param offset the start offset in the buffer - * @param len the number of bytes to write - * - * @throws IOException if an error occurs + * @param fd The file descriptor integer. + * @param backlog The listen backlog size. + * @throws IOException */ - static native void write(PlainSocketImpl socket, byte[] buf, int offset, - int len) throws IOException; + private static native void listen(int fd, int backlog) throws IOException; - /** - * Internal method used by SocketOuputStream for writing data to - * the connection. Writes exactly one byte to the socket. - * - * @param socket the socket object - * @param data the byte to write to the socket - * - * @throws IOException if an error occurs - */ - static void write(PlainSocketImpl socket, int data) - throws IOException + public void join(InetAddress group) throws IOException { - write(socket, new byte[]{ (byte) data }, 0, 1); + if (group instanceof Inet4Address) + join(nfd.getNativeFD(), group.getAddress()); + else if (group instanceof Inet6Address) + join6(nfd.getNativeFD(), group.getAddress()); + else + throw new IllegalArgumentException("unknown address type"); } + + private static native void join(int fd, byte[] addr) throws IOException; + + private static native void join6(int fd, byte[] addr) throws IOException; + + public void leave(InetAddress group) throws IOException + { + if (group instanceof Inet4Address) + leave(nfd.getNativeFD(), group.getAddress()); + else if (group instanceof Inet6Address) + leave6(nfd.getNativeFD(), group.getAddress()); + else + throw new IllegalArgumentException("unknown address type"); + } + + private static native void leave(int fd, byte[] addr) throws IOException; + + private static native void leave6(int fd, byte[] addr) throws IOException; - /** - * Sets the input stream for this socket to the end of the stream. Any - * attempts to read more bytes from the stream will return an EOF. - * - * @param socket the socket object - * - * @throws IOException if I/O errors occur - */ - static native void shutdownInput(PlainSocketImpl socket) throws IOException; - - /** - * Disables the output stream for this socket. Any attempt to write more - * data to the socket will throw an IOException. - * - * @param socket the socket object - * - * @throws IOException if I/O errors occur - */ - static native void shutdownOutput(PlainSocketImpl socket) throws IOException; - - /** - * Connects to the remote socket address with a specified timeout. - * - * @param socket the socket object - * @param address the remote address to connect to - * @param timeout the timeout to use for this connect, 0 means infinite. - * - * @throws IOException if an error occurs - */ - static synchronized void connect(PlainSocketImpl socket, - SocketAddress address, int timeout) + public void joinGroup(InetSocketAddress addr, NetworkInterface netif) throws IOException { - InetSocketAddress sockAddr = (InetSocketAddress) address; - InetAddress addr = sockAddr.getAddress(); - - if (addr == null) - throw new UnknownHostException(sockAddr.getHostName()); - - int port = sockAddr.getPort(); - - if (timeout < 0) - throw new IllegalArgumentException("negative timeout"); - - Object oldTimeoutObj = null; - try - { - oldTimeoutObj = getOption(socket, SocketOptions.SO_TIMEOUT); - setOption(socket, SocketOptions.SO_TIMEOUT, new Integer(timeout)); - connect(socket, addr, port); - } - finally - { - if (oldTimeoutObj != null) - setOption(socket, SocketOptions.SO_TIMEOUT, oldTimeoutObj); - } + InetAddress address = addr.getAddress(); + + if (address instanceof Inet4Address) + joinGroup(nfd.getNativeFD(), address.getAddress(), + netif != null ? netif.getName() : null); + else if (address instanceof Inet6Address) + joinGroup6(nfd.getNativeFD(), address.getAddress(), + netif != null ? netif.getName() : null); + else + throw new IllegalArgumentException("unknown address type"); } - + + private static native void joinGroup(int fd, byte[] addr, String ifname) + throws IOException; + + private static native void joinGroup6(int fd, byte[] addr, String ifname) + throws IOException; + + public void leaveGroup(InetSocketAddress addr, NetworkInterface netif) + throws IOException + { + InetAddress address = addr.getAddress(); + if (address instanceof Inet4Address) + leaveGroup(nfd.getNativeFD(), address.getAddress(), + netif != null ? netif.getName() : null); + else if (address instanceof Inet6Address) + leaveGroup6(nfd.getNativeFD(), address.getAddress(), + netif != null ? netif.getName() : null); + else + throw new IllegalArgumentException("unknown address type"); + } + + private static native void leaveGroup(int fd, byte[] addr, String ifname) + throws IOException; + + private static native void leaveGroup6(int fd, byte[] addr, String ifname) + throws IOException; + + + public void shutdownInput() throws IOException + { + shutdownInput(nfd.getNativeFD()); + } + + private static native void shutdownInput(int native_fd) throws IOException; + + public void shutdownOutput() throws IOException + { + shutdownOutput(nfd.getNativeFD()); + } + + private static native void shutdownOutput(int native_fd) throws IOException; + + public void sendUrgentData(int data) throws IOException + { + sendUrgentData(nfd.getNativeFD(), data); + } + + private static native void sendUrgentData(int natfive_fd, int data) throws IOException; + + public void close() throws IOException + { + nfd.close(); + } + + // Inner classes. + /** - * Send one byte of urgent data over the socket. - * - * @param socket the socket object - * @param data the byte to send + * Our wrapper for the native file descriptor. In this implementation, + * it is a simple wrapper around {@link VMChannel.State}, to simplify + * management of the native state. */ - static void sendUrgendData(PlainSocketImpl socket, int data) + public final class State { - throw new InternalError ("PlainSocketImpl::sendUrgentData not implemented"); + private VMChannel.State channelFd; + + State() + { + channelFd = null; + } + + public boolean isValid() + { + if (channelFd != null) + return channelFd.isValid(); + return false; + } + + public int getNativeFD() throws IOException + { + return channelFd.getNativeFD(); + } + + public void setChannelFD(final VMChannel.State nfd) throws IOException + { + if (this.channelFd != null && this.channelFd.isValid()) + throw new IOException("file descriptor already initialized"); + this.channelFd = nfd; + } + + public void close() throws IOException + { + if (channelFd == null) + throw new IOException("invalid file descriptor"); + channelFd.close(); + } + + protected void finalize() throws Throwable + { + try + { + if (isValid()) + close(); + } + finally + { + super.finalize(); + } + } } } + diff --git a/libjava/classpath/vm/reference/gnu/java/nio/VMChannel.java b/libjava/classpath/vm/reference/gnu/java/nio/VMChannel.java index fdea8ff6213..1f69877b6ba 100644 --- a/libjava/classpath/vm/reference/gnu/java/nio/VMChannel.java +++ b/libjava/classpath/vm/reference/gnu/java/nio/VMChannel.java @@ -39,13 +39,16 @@ exception statement from your version. */ package gnu.java.nio; import gnu.classpath.Configuration; -import gnu.java.net.PlainSocketImpl; -import gnu.java.nio.PipeImpl.SinkChannelImpl; -import gnu.java.nio.PipeImpl.SourceChannelImpl; -import gnu.java.nio.channels.FileChannelImpl; import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.SocketException; import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; /** * Native interface to support configuring of channel to run in a non-blocking @@ -54,33 +57,43 @@ import java.nio.ByteBuffer; * @author Michael Barker <mike@middlesoft.co.uk> * */ -public class VMChannel +public final class VMChannel { - private final int fd; - - private VMChannel(int fd) - { - this.fd = fd; - } + /** + * Our reference implementation uses an integer to store the native + * file descriptor. Implementations without such support + */ + private final State nfd; - public static VMChannel getVMChannel(PlainSocketImpl socket) - { - return new VMChannel(socket.getNativeFD()); - } + private Kind kind; - public static VMChannel getVMChannel(SourceChannelImpl source) + public VMChannel() { - return new VMChannel(source.getNativeFD()); + // XXX consider adding security check here, so only Classpath + // code may create instances. + this.nfd = new State(); + kind = Kind.OTHER; } - public static VMChannel getVMChannel(SinkChannelImpl sink) + /** + * This constructor is used by the POSIX reference implementation; + * other virtual machines need not support it. + * + * <strong>Important:</strong> do not call this in library code that is + * not specific to Classpath's reference implementation. + * + * @param native_fd The native file descriptor integer. + * @throws IOException + */ + VMChannel(final int native_fd) throws IOException { - return new VMChannel(sink.getNativeFD()); + this(); + this.nfd.setNativeFD(native_fd); } - public static VMChannel getVMChannel(FileChannelImpl file) + public State getState() { - return new VMChannel(file.getNativeFD()); + return nfd; } static @@ -93,81 +106,151 @@ public class VMChannel initIDs(); } + public static VMChannel getStdin() throws IOException + { + return new VMChannel(stdin_fd()); + } + + public static VMChannel getStdout() throws IOException + { + return new VMChannel(stdout_fd()); + } + + public static VMChannel getStderr() throws IOException + { + return new VMChannel(stderr_fd()); + } + + private static native int stdin_fd(); + private static native int stdout_fd(); + private static native int stderr_fd(); + /** * Set the file descriptor to have the required blocking * setting. * - * @param fd - * @param blocking + * @param blocking The blocking flag to set. */ - public native void setBlocking(int fd, boolean blocking); + public void setBlocking(boolean blocking) throws IOException + { + setBlocking(nfd.getNativeFD(), blocking); + } - public void setBlocking(boolean blocking) + private static native void setBlocking(int fd, boolean blocking) + throws IOException; + + public int available() throws IOException { - setBlocking(fd, blocking); + return available(nfd.getNativeFD()); } + private static native int available(int native_fd) throws IOException; /** * Reads a byte buffer directly using the supplied file descriptor. - * Assumes that the buffer is a DirectBuffer. * - * @param fd Native file descriptor to read from. * @param dst Direct Byte Buffer to read to. * @return Number of bytes read. * @throws IOException If an error occurs or dst is not a direct buffers. */ - native int read(int fd, ByteBuffer dst) - throws IOException; - public int read(ByteBuffer dst) throws IOException { - return read(fd, dst); + return read(nfd.getNativeFD(), dst); + } + + private static native int read(int fd, ByteBuffer dst) throws IOException; + + /** + * Read a single byte. + * + * @return The byte read, or -1 on end of file. + * @throws IOException + */ + public int read() throws IOException + { + return read(nfd.getNativeFD()); } + private static native int read(int fd) throws IOException; + /** * Reads into byte buffers directly using the supplied file descriptor. * Assumes that the buffer list contains DirectBuffers. Will perform a * scattering read. * - * @param fd Native file descriptor to read from. * @param dsts An array direct byte buffers. * @param offset Index of the first buffer to read to. * @param length The number of buffers to read to. * @return Number of bytes read. * @throws IOException If an error occurs or the dsts are not direct buffers. */ - native long readScattering(int fd, ByteBuffer[] dsts, int offset, int length) - throws IOException; - public long readScattering(ByteBuffer[] dsts, int offset, int length) throws IOException { if (offset + length > dsts.length) throw new IndexOutOfBoundsException("offset + length > dsts.length"); + + return readScattering(nfd.getNativeFD(), dsts, offset, length); + } + + private static native long readScattering(int fd, ByteBuffer[] dsts, + int offset, int length) + throws IOException; + + /** + * Receive a datagram on this channel, returning the host address + * that sent the datagram. + * + * @param dst Where to store the datagram. + * @return The host address that sent the datagram. + * @throws IOException + */ + public SocketAddress receive(ByteBuffer dst) throws IOException + { + if (kind != Kind.SOCK_DGRAM) + throw new SocketException("not a datagram socket"); + ByteBuffer hostPort = ByteBuffer.allocateDirect(18); + int hostlen = receive(nfd.getNativeFD(), dst, hostPort); + if (hostlen == 0) + return null; + if (hostlen == 4) // IPv4 + { + byte[] addr = new byte[4]; + hostPort.get(addr); + int port = hostPort.getShort() & 0xFFFF; + return new InetSocketAddress(Inet4Address.getByAddress(addr), port); + } + if (hostlen == 16) // IPv6 + { + byte[] addr = new byte[16]; + hostPort.get(addr); + int port = hostPort.getShort() & 0xFFFF; + return new InetSocketAddress(Inet6Address.getByAddress(addr), port); + } - return readScattering(fd, dsts, offset, length); + throw new SocketException("host address received with invalid length: " + + hostlen); } + private static native int receive (int fd, ByteBuffer dst, ByteBuffer address) + throws IOException; + /** * Writes from a direct byte bufer using the supplied file descriptor. * Assumes the buffer is a DirectBuffer. * - * @param fd - * @param src + * @param src The source buffer. * @return Number of bytes written. * @throws IOException */ - native int write(int fd, ByteBuffer src) - throws IOException; - - public int write(ByteBuffer src) - throws IOException + public int write(ByteBuffer src) throws IOException { - return write(fd, src); + return write(nfd.getNativeFD(), src); } + private native int write(int fd, ByteBuffer src) throws IOException; + /** * Writes from byte buffers directly using the supplied file descriptor. * Assumes the that buffer list constains DirectBuffers. Will perform @@ -180,18 +263,488 @@ public class VMChannel * @return Number of bytes written. * @throws IOException */ - native long writeGathering(int fd, ByteBuffer[] srcs, int offset, int length) - throws IOException; - public long writeGathering(ByteBuffer[] srcs, int offset, int length) throws IOException { if (offset + length > srcs.length) throw new IndexOutOfBoundsException("offset + length > srcs.length"); - return writeGathering(fd, srcs, offset, length); + // A gathering write is limited to 16 buffers; when writing, ensure + // that we have at least one buffer with something in it in the 16 + // buffer window starting at offset. + while (!srcs[offset].hasRemaining() && offset < srcs.length) + offset++; + + // There are no buffers with anything to write. + if (offset == srcs.length) + return 0; + + // If we advanced `offset' so far that we don't have `length' + // buffers left, reset length to only the remaining buffers. + if (length > srcs.length - offset) + length = srcs.length - offset; + + return writeGathering(nfd.getNativeFD(), srcs, offset, length); + } + + private native long writeGathering(int fd, ByteBuffer[] srcs, + int offset, int length) + throws IOException; + + /** + * Send a datagram to the given address. + * + * @param src The source buffer. + * @param dst The destination address. + * @return The number of bytes written. + * @throws IOException + */ + public int send(ByteBuffer src, InetSocketAddress dst) + throws IOException + { + InetAddress addr = dst.getAddress(); + if (addr == null) + throw new NullPointerException(); + if (addr instanceof Inet4Address) + return send(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort()); + else if (addr instanceof Inet6Address) + return send6(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort()); + else + throw new SocketException("unrecognized inet address type"); + } + + // Send to an IPv4 address. + private static native int send(int fd, ByteBuffer src, byte[] addr, int port) + throws IOException; + + // Send to an IPv6 address. + private static native int send6(int fd, ByteBuffer src, byte[] addr, int port) + throws IOException; + + /** + * Write a single byte. + * + * @param b The byte to write. + * @throws IOException + */ + public void write(int b) throws IOException + { + write(nfd.getNativeFD(), b); } + private static native void write(int fd, int b) throws IOException; + private native static void initIDs(); + // Network (socket) specific methods. + + /** + * Create a new socket. This method will initialize the native file + * descriptor state of this instance. + * + * @param stream Whether or not to create a streaming socket, or a datagram + * socket. + * @throws IOException If creating a new socket fails, or if this + * channel already has its native descriptor initialized. + */ + public void initSocket(boolean stream) throws IOException + { + if (nfd.isValid()) + throw new IOException("native FD already initialized"); + if (stream) + kind = Kind.SOCK_STREAM; + else + kind = Kind.SOCK_DGRAM; + nfd.setNativeFD(socket(stream)); + } + + /** + * Create a new socket, returning the native file descriptor. + * + * @param stream Set to true for streaming sockets; false for datagrams. + * @return The native file descriptor. + * @throws IOException If creating the socket fails. + */ + private static native int socket(boolean stream) throws IOException; + + /** + * Connect the underlying socket file descriptor to the remote host. + * + * @param saddr The address to connect to. + * @param timeout The connect timeout to use for blocking connects. + * @return True if the connection succeeded; false if the file descriptor + * is in non-blocking mode and the connection did not immediately + * succeed. + * @throws IOException If an error occurs while connecting. + */ + public boolean connect(InetSocketAddress saddr, int timeout) + throws SocketException + { + int fd; + + InetAddress addr = saddr.getAddress(); + + // Translates an IOException into a SocketException to conform + // to the throws clause. + try + { + fd = nfd.getNativeFD(); + } + catch (IOException ioe) + { + throw new SocketException(ioe.getMessage()); + } + + if (addr instanceof Inet4Address) + return connect(fd, addr.getAddress(), saddr.getPort(), + timeout); + if (addr instanceof Inet6Address) + return connect6(fd, addr.getAddress(), saddr.getPort(), + timeout); + throw new SocketException("unsupported internet address"); + } + + private static native boolean connect(int fd, byte[] addr, int port, int timeout) + throws SocketException; + + private static native boolean connect6(int fd, byte[] addr, int port, int timeout) + throws SocketException; + + /** + * Disconnect this channel, if it is a datagram socket. Disconnecting + * a datagram channel will disassociate it from any address, so the + * socket will remain open, but can send and receive datagrams from + * any address. + * + * @throws IOException If disconnecting this channel fails, or if this + * channel is not a datagram channel. + */ + public void disconnect() throws IOException + { + if (kind != Kind.SOCK_DGRAM) + throw new IOException("can only disconnect datagram channels"); + disconnect(nfd.getNativeFD()); + } + + private static native void disconnect(int fd) throws IOException; + + public InetSocketAddress getLocalAddress() throws IOException + { + if (!nfd.isValid()) + return null; + ByteBuffer name = ByteBuffer.allocateDirect(18); + int namelen = getsockname(nfd.getNativeFD(), name); + if (namelen == 0) // not bound + return null; // XXX return some wildcard? + if (namelen == 4) + { + byte[] addr = new byte[4]; + name.get(addr); + int port = name.getShort() & 0xFFFF; + return new InetSocketAddress(Inet4Address.getByAddress(addr), port); + } + if (namelen == 16) + { + byte[] addr = new byte[16]; + name.get(addr); + int port = name.getShort() & 0xFFFF; + return new InetSocketAddress(Inet6Address.getByAddress(addr), port); + } + throw new SocketException("invalid address length"); + } + + private static native int getsockname(int fd, ByteBuffer name) + throws IOException; + + /** + * Returns the socket address of the remote peer this channel is connected + * to, or null if this channel is not yet connected. + * + * @return The peer address. + * @throws IOException + */ + public InetSocketAddress getPeerAddress() throws IOException + { + if (!nfd.isValid()) + return null; + ByteBuffer name = ByteBuffer.allocateDirect(18); + int namelen = getpeername (nfd.getNativeFD(), name); + if (namelen == 0) // not connected yet + return null; + if (namelen == 4) // IPv4 + { + byte[] addr = new byte[4]; + name.get(addr); + int port = name.getShort() & 0xFFFF; + return new InetSocketAddress(Inet4Address.getByAddress(addr), port); + } + else if (namelen == 16) // IPv6 + { + byte[] addr = new byte[16]; + name.get(addr); + int port = name.getShort() & 0xFFFF; + return new InetSocketAddress(Inet6Address.getByAddress(addr), port); + } + throw new SocketException("invalid address length"); + } + + /* + * The format here is the peer address, followed by the port number. + * The returned value is the length of the peer address; thus, there + * will be LEN + 2 valid bytes put into NAME. + */ + private static native int getpeername(int fd, ByteBuffer name) + throws IOException; + + /** + * Accept an incoming connection, returning a new VMChannel, or null + * if the channel is nonblocking and no connection is pending. + * + * @return The accepted connection, or null. + * @throws IOException If an IO error occurs. + */ + public VMChannel accept() throws IOException + { + int new_fd = accept(nfd.getNativeFD()); + if (new_fd == -1) // non-blocking accept had no pending connection + return null; + return new VMChannel(new_fd); + } + + private static native int accept(int native_fd) throws IOException; + + // File-specific methods. + + /** + * Open a file at PATH, initializing the native state to operate on + * that open file. + * + * @param path The absolute file path. + * @throws IOException If the file cannot be opened, or if this + * channel was previously initialized. + */ + public void openFile(String path, int mode) throws IOException + { + if (nfd.isValid() || nfd.isClosed()) + throw new IOException("can't reinitialize this channel"); + int fd = open(path, mode); + nfd.setNativeFD(fd); + kind = Kind.FILE; + } + + private static native int open(String path, int mode) throws IOException; + + public long position() throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + return position(nfd.getNativeFD()); + } + + private static native long position(int fd) throws IOException; + + public void seek(long pos) throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + seek(nfd.getNativeFD(), pos); + } + + private static native void seek(int fd, long pos) throws IOException; + + public void truncate(long length) throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + truncate(nfd.getNativeFD(), length); + } + + private static native void truncate(int fd, long len) throws IOException; + + public boolean lock(long pos, long len, boolean shared, boolean wait) + throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + return lock(nfd.getNativeFD(), pos, len, shared, wait); + } + + private static native boolean lock(int fd, long pos, long len, + boolean shared, boolean wait) + throws IOException; + + public void unlock(long pos, long len) throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + unlock(nfd.getNativeFD(), pos, len); + } + + private static native void unlock(int fd, long pos, long len) throws IOException; + + public long size() throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + return size(nfd.getNativeFD()); + } + + private static native long size(int fd) throws IOException; + + public MappedByteBuffer map(char mode, long position, int size) + throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + return map(nfd.getNativeFD(), mode, position, size); + } + + private static native MappedByteBuffer map(int fd, char mode, + long position, int size) + throws IOException; + + public boolean flush(boolean metadata) throws IOException + { + if (kind != Kind.FILE) + throw new IOException("not a file"); + return flush(nfd.getNativeFD(), metadata); + } + + private static native boolean flush(int fd, boolean metadata) throws IOException; + + // Close. + + /** + * Close this socket. The socket is also automatically closed when this + * object is finalized. + * + * @throws IOException If closing the socket fails, or if this object has + * no open socket. + */ + public void close() throws IOException + { + nfd.close(); + } + + static native void close(int native_fd) throws IOException; + + /** + * <p>Provides a simple mean for the JNI code to find out whether the + * current thread was interrupted by a call to Thread.interrupt().</p> + * + * @return + */ + static boolean isThreadInterrupted() + { + return Thread.currentThread().isInterrupted(); + } + + // Inner classes. + + /** + * A wrapper for a native file descriptor integer. This tracks the state + * of an open file descriptor, and ensures that + * + * This class need not be fully supported by virtual machines; if a + * virtual machine does not use integer file descriptors, or does and + * wishes to hide that, then the methods of this class may be stubbed out. + * + * System-specific classes that depend on access to native file descriptor + * integers SHOULD declare this fact. + */ + public final class State + { + private int native_fd; + private boolean valid; + private boolean closed; + + State() + { + native_fd = -1; + valid = false; + closed = false; + } + + public boolean isValid() + { + return valid; + } + + public boolean isClosed() + { + return closed; + } + + public int getNativeFD() throws IOException + { + if (!valid) + throw new IOException("invalid file descriptor"); + return native_fd; + } + + void setNativeFD(final int native_fd) throws IOException + { + if (valid) + throw new IOException("file descriptor already initialized"); + this.native_fd = native_fd; + valid = true; + } + + public void close() throws IOException + { + if (!valid) + throw new IOException("invalid file descriptor"); + try + { + VMChannel.close(native_fd); + } + finally + { + valid = false; + closed = true; + } + } + + public String toString() + { + if (closed) + return "<<closed>>"; + if (!valid) + return "<<invalid>>"; + return String.valueOf(native_fd); + } + + protected void finalize() throws Throwable + { + try + { + if (valid) + close(); + } + finally + { + super.finalize(); + } + } + } + + /** + * An enumeration of possible kinds of channel. + */ + static class Kind // XXX enum + { + /** A streaming (TCP) socket. */ + static final Kind SOCK_STREAM = new Kind(); + + /** A datagram (UDP) socket. */ + static final Kind SOCK_DGRAM = new Kind(); + + /** A file. */ + static final Kind FILE = new Kind(); + + /** Something else; not a socket or file. */ + static final Kind OTHER = new Kind(); + + private Kind() { } + } } diff --git a/libjava/classpath/vm/reference/gnu/java/nio/VMPipe.java b/libjava/classpath/vm/reference/gnu/java/nio/VMPipe.java index 11dd2aa7b4b..e5257c1cf96 100644 --- a/libjava/classpath/vm/reference/gnu/java/nio/VMPipe.java +++ b/libjava/classpath/vm/reference/gnu/java/nio/VMPipe.java @@ -38,7 +38,6 @@ exception statement from your version. */ package gnu.java.nio; import java.io.IOException; -import java.nio.channels.spi.SelectorProvider; import gnu.classpath.Configuration; /** @@ -58,7 +57,24 @@ final class VMPipe System.loadLibrary ("javanio"); } } - - static native void init(PipeImpl self, SelectorProvider provider) - throws IOException; + + /** + * Create a pipe, consisting of a readable VMChannel and a writable + * VMChannel. The readable channel is returned is the first element + * of the array, and the writable in the second. + * + * @return A pair of VMChannels; the first readable, the second + * writable. + * @throws IOException If the pipe cannot be created. + */ + static VMChannel[] pipe() throws IOException + { + VMChannel[] pipe = new VMChannel[2]; + int[] fds = pipe0(); + pipe[0] = new VMChannel(fds[0]); + pipe[1] = new VMChannel(fds[1]); + return pipe; + } + + private static native int[] pipe0() throws IOException; } diff --git a/libjava/classpath/vm/reference/java/io/VMFile.java b/libjava/classpath/vm/reference/java/io/VMFile.java index 2f48aad71f8..13d256d424a 100644 --- a/libjava/classpath/vm/reference/java/io/VMFile.java +++ b/libjava/classpath/vm/reference/java/io/VMFile.java @@ -38,6 +38,9 @@ exception statement from your version. */ package java.io; +import java.net.MalformedURLException; +import java.net.URL; + import gnu.classpath.Configuration; import gnu.java.io.PlatformHelper; @@ -209,6 +212,108 @@ final class VMFile } /** + * Returns the path as an absolute path name. The value returned is the + * current directory plus the separatory string plus the path of the file. + * The current directory is determined from the <code>user.dir</code> system + * property. + * + * @param path the path to convert to absolute path + * + * @return the absolute path that corresponds to <code>path</code> + */ + static String getAbsolutePath(String path) + { + if (File.separatorChar == '\\' + && path.length() > 0 && path.charAt (0) == '\\') + { + // On Windows, even if the path starts with a '\\' it is not + // really absolute until we prefix the drive specifier from + // the current working directory to it. + return System.getProperty ("user.dir").substring (0, 2) + path; + } + else if (File.separatorChar == '\\' + && path.length() > 1 && path.charAt (1) == ':' + && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') + || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))) + { + // On Windows, a process has a current working directory for + // each drive and a path like "G:foo\bar" would mean the + // absolute path "G:\wombat\foo\bar" if "\wombat" is the + // working directory on the G drive. + String drvDir = null; + try + { + drvDir = new File (path.substring (0, 2)).getCanonicalPath(); + } + catch (IOException e) + { + drvDir = path.substring (0, 2) + "\\"; + } + + // Note: this would return "C:\\." for the path "C:.", if "\" + // is the working folder on the C drive, but this is + // consistent with what Sun's JRE 1.4.1.01 actually returns! + if (path.length() > 2) + return drvDir + '\\' + path.substring (2, path.length()); + else + return drvDir; + } + else if (path.equals("")) + return System.getProperty ("user.dir"); + else + return System.getProperty ("user.dir") + File.separatorChar + path; + } + + /** + * This method returns true if the path represents an absolute file + * path and false if it does not. The definition of an absolute path varies + * by system. As an example, on GNU systems, a path is absolute if it starts + * with a "/". + * + * @param path the path to check + * + * @return <code>true</code> if path represents an absolute file name, + * <code>false</code> otherwise. + */ + static boolean isAbsolute(String path) + { + if (File.separatorChar == '\\') + return path.startsWith(File.separator + File.separator) + || (path.length() > 2 + && ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') + || (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) + && path.charAt(1) == ':' + && path.charAt(2) == '\\'); + else + return path.startsWith(File.separator); + } + + /** + * Returns a <code>URL</code> with the <code>file:</code> + * protocol that represents this file. The exact form of this URL is + * system dependent. + * + * @param file the file to convert to URL + * + * @return a <code>URL</code> for this object. + * + * @throws MalformedURLException if the URL cannot be created + * successfully. + */ + static URL toURL(File file) + throws MalformedURLException + { + // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt", + // while on UNIX, it returns URLs of the form "file:/foo/bar.txt". + if (File.separatorChar == '\\') + return new URL ("file:/" + file.getAbsolutePath().replace ('\\', '/') + + (file.isDirectory() ? "/" : "")); + else + return new URL ("file:" + file.getAbsolutePath() + + (file.isDirectory() ? "/" : "")); + } + + /** * This method returns a canonical representation of the pathname of * this file. The actual form of the canonical representation is * system-dependent. On the GNU system, conversion to canonical diff --git a/libjava/classpath/vm/reference/java/io/VMObjectInputStream.java b/libjava/classpath/vm/reference/java/io/VMObjectInputStream.java index 5fb56fcd4c9..be0f8eb5235 100644 --- a/libjava/classpath/vm/reference/java/io/VMObjectInputStream.java +++ b/libjava/classpath/vm/reference/java/io/VMObjectInputStream.java @@ -40,10 +40,7 @@ exception statement from your version. */ package java.io; import gnu.classpath.Configuration; -import gnu.classpath.VMStackWalker; import java.lang.reflect.Constructor; -import java.security.AccessController; -import java.security.PrivilegedAction; final class VMObjectInputStream { @@ -56,42 +53,6 @@ final class VMObjectInputStream } /** - * PrivilegedAction needed for Class.getClassLoader() - */ - private static PrivilegedAction loaderAction = new PrivilegedAction() - { - /** - * Returns the first user defined class loader on the call stack, or the - * context class loader of the current thread, when no non-null class loader - * was found. - */ - public Object run() - { - Class[] ctx = VMStackWalker.getClassContext(); - - for (int i = 0; i < ctx.length; i++) - { - ClassLoader cl = ctx[i].getClassLoader(); - if (cl != null) - return cl; - } - return Thread.currentThread().getContextClassLoader(); - } - }; - - /** - * Returns the first user defined class loader on the call stack, or the - * context class loader of the current thread, when no non-null class loader - * was found. - * - * @return the class loader - */ - static ClassLoader currentClassLoader() - { - return (ClassLoader) AccessController.doPrivileged(loaderAction); - } - - /** * Allocates a new Object of type clazz but without running the * default constructor on it. It then calls the given constructor on * it. The given constructor method comes from the constr_clazz diff --git a/libjava/classpath/vm/reference/java/lang/VMClassLoader.java b/libjava/classpath/vm/reference/java/lang/VMClassLoader.java index 897df5186b3..e56152d0126 100644 --- a/libjava/classpath/vm/reference/java/lang/VMClassLoader.java +++ b/libjava/classpath/vm/reference/java/lang/VMClassLoader.java @@ -415,8 +415,9 @@ final class VMClassLoader { byte[] modifiedData = new byte[len]; System.arraycopy(data, offset, modifiedData, 0, len); + String jvmName = name.replace('.', '/'); modifiedData = - ((InstrumentationImpl)instrumenter).callTransformers(loader, name, + ((InstrumentationImpl)instrumenter).callTransformers(loader, jvmName, null, pd, modifiedData); return defineClass(loader, name, modifiedData, 0, modifiedData.length, diff --git a/libjava/classpath/vm/reference/java/lang/reflect/Constructor.java b/libjava/classpath/vm/reference/java/lang/reflect/Constructor.java index 521190b6656..eebee5f5d2a 100644 --- a/libjava/classpath/vm/reference/java/lang/reflect/Constructor.java +++ b/libjava/classpath/vm/reference/java/lang/reflect/Constructor.java @@ -77,11 +77,11 @@ import java.util.Arrays; * @since 1.1 * @status updated to 1.4 */ -public final class Constructor +public final class Constructor<T> extends AccessibleObject implements GenericDeclaration, Member { - private Class clazz; + private Class<T> clazz; private int slot; private static final int CONSTRUCTOR_MODIFIERS @@ -104,7 +104,7 @@ public final class Constructor * Gets the class that declared this constructor. * @return the class that declared this member */ - public Class getDeclaringClass() + public Class<T> getDeclaringClass() { return clazz; } @@ -166,7 +166,7 @@ public final class Constructor * * @return a list of the types of the constructor's parameters */ - public native Class[] getParameterTypes(); + public native Class<?>[] getParameterTypes(); /** * Get the exception types this constructor says it throws, in no particular @@ -175,7 +175,7 @@ public final class Constructor * * @return a list of the types in the constructor's throws clause */ - public native Class[] getExceptionTypes(); + public native Class<?>[] getExceptionTypes(); /** * Compare two objects to see if they are semantically equivalent. @@ -244,8 +244,8 @@ public final class Constructor return sb.toString(); } - /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */ - static void addTypeParameters(StringBuilder sb, TypeVariable[] typeArgs) + static <X extends GenericDeclaration> + void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs) { if (typeArgs.length == 0) return; @@ -313,15 +313,15 @@ public final class Constructor * @throws ExceptionInInitializerError if construction triggered class * initialization, which then failed */ - public Object newInstance(Object args[]) + public T newInstance(Object... args) throws InstantiationException, IllegalAccessException, InvocationTargetException { return constructNative(args, clazz, slot); } - private native Object constructNative(Object[] args, Class declaringClass, - int slot) + private native T constructNative(Object[] args, Class declaringClass, + int slot) throws InstantiationException, IllegalAccessException, InvocationTargetException; @@ -337,8 +337,7 @@ public final class Constructor * specification, version 3. * @since 1.5 */ - /* FIXME[GENERICS]: Add <Constructor<T>> */ - public TypeVariable[] getTypeParameters() + public TypeVariable<Constructor<T>>[] getTypeParameters() { String sig = getSignature(); if (sig == null) @@ -395,4 +394,3 @@ public final class Constructor return p.getGenericParameterTypes(); } } - diff --git a/libjava/classpath/vm/reference/java/lang/reflect/Field.java b/libjava/classpath/vm/reference/java/lang/reflect/Field.java index 5121700fede..5db1fa3ecc1 100644 --- a/libjava/classpath/vm/reference/java/lang/reflect/Field.java +++ b/libjava/classpath/vm/reference/java/lang/reflect/Field.java @@ -102,7 +102,7 @@ extends AccessibleObject implements Member * is a non-inherited member. * @return the class that declared this member */ - public Class getDeclaringClass() + public Class<?> getDeclaringClass() { return declaringClass; } @@ -159,7 +159,7 @@ extends AccessibleObject implements Member * Gets the type of this field. * @return the type of this field */ - public native Class getType(); + public native Class<?> getType(); /** * Compare two objects to see if they are semantically equivalent. @@ -213,7 +213,7 @@ extends AccessibleObject implements Member sb.append(getName()); return sb.toString(); } - + public String toGenericString() { StringBuilder sb = new StringBuilder(64); @@ -658,5 +658,4 @@ extends AccessibleObject implements Member * is no Signature attribute, return null. */ private native String getSignature(); - } diff --git a/libjava/classpath/vm/reference/java/lang/reflect/Method.java b/libjava/classpath/vm/reference/java/lang/reflect/Method.java index a9920241b17..c520f057024 100644 --- a/libjava/classpath/vm/reference/java/lang/reflect/Method.java +++ b/libjava/classpath/vm/reference/java/lang/reflect/Method.java @@ -104,7 +104,7 @@ extends AccessibleObject implements Member, GenericDeclaration * is a non-inherited member. * @return the class that declared this member */ - public Class getDeclaringClass() + public Class<?> getDeclaringClass() { return declaringClass; } @@ -172,7 +172,7 @@ extends AccessibleObject implements Member, GenericDeclaration * Gets the return type of this method. * @return the type of this method */ - public native Class getReturnType(); + public native Class<?> getReturnType(); /** * Get the parameter list for this method, in declaration order. If the @@ -180,7 +180,7 @@ extends AccessibleObject implements Member, GenericDeclaration * * @return a list of the types of the method's parameters */ - public native Class[] getParameterTypes(); + public native Class<?>[] getParameterTypes(); /** * Get the exception types this method says it throws, in no particular @@ -189,7 +189,7 @@ extends AccessibleObject implements Member, GenericDeclaration * * @return a list of the types in the method's throws clause */ - public native Class[] getExceptionTypes(); + public native Class<?>[] getExceptionTypes(); /** * Compare two objects to see if they are semantically equivalent. @@ -349,7 +349,7 @@ extends AccessibleObject implements Member, GenericDeclaration * @throws ExceptionInInitializerError if accessing a static method triggered * class initialization, which then failed */ - public Object invoke(Object o, Object[] args) + public Object invoke(Object o, Object... args) throws IllegalAccessException, InvocationTargetException { return invokeNative(o, args, declaringClass, slot); @@ -375,8 +375,7 @@ extends AccessibleObject implements Member, GenericDeclaration * specification, version 3. * @since 1.5 */ - /* FIXME[GENERICS]: Should be TypeVariable<Method>[] */ - public TypeVariable[] getTypeParameters() + public TypeVariable<Method>[] getTypeParameters() { String sig = getSignature(); if (sig == null) @@ -451,4 +450,3 @@ extends AccessibleObject implements Member, GenericDeclaration return p.getGenericReturnType(); } } - diff --git a/libjava/classpath/vm/reference/java/net/VMInetAddress.java b/libjava/classpath/vm/reference/java/net/VMInetAddress.java index 19f5d7d341c..a99c216b96c 100644 --- a/libjava/classpath/vm/reference/java/net/VMInetAddress.java +++ b/libjava/classpath/vm/reference/java/net/VMInetAddress.java @@ -84,4 +84,14 @@ class VMInetAddress implements Serializable */ public static native byte[][] getHostByName(String hostname) throws UnknownHostException; + + /** + * Return the IP address represented by a literal address. + * Will return null if the literal address is not valid. + * + * @param address the name of the host + * + * @return The IP address as a byte array + */ + public static native byte[] aton(String address); } diff --git a/libjava/classpath/vm/reference/java/net/VMNetworkInterface.java b/libjava/classpath/vm/reference/java/net/VMNetworkInterface.java index 47f803246d5..7f1e3ad9890 100644 --- a/libjava/classpath/vm/reference/java/net/VMNetworkInterface.java +++ b/libjava/classpath/vm/reference/java/net/VMNetworkInterface.java @@ -40,6 +40,9 @@ package java.net; import gnu.classpath.Configuration; +import java.nio.ByteBuffer; +import java.util.HashSet; +import java.util.Set; import java.util.Vector; /** @@ -54,22 +57,67 @@ import java.util.Vector; */ final class VMNetworkInterface { + String name; + Set addresses; + + VMNetworkInterface(String name) + { + this.name = name; + addresses = new HashSet(); + } + + /** + * Creates a dummy instance which represents any network + * interface. + */ + public VMNetworkInterface() + { + addresses = new HashSet(); + try + { + addresses.add(InetAddress.getByName("0.0.0.0")); + } + catch (UnknownHostException _) + { + // Cannot happen. + } + } + static - { - if (Configuration.INIT_LOAD_LIBRARY) - System.loadLibrary("javanet"); - } + { + if (Configuration.INIT_LOAD_LIBRARY) + System.loadLibrary("javanet"); + + initIds(); + } + + private static native void initIds(); /** - * Returns a Vector of InetAddresses. The returned value will be - * 'condensed', meaning that all elements with the same interface - * name will be collapesed into one InetAddress for that name - * containing all addresses before the returning the result to the - * user. This means the native method can be implemented in a naive - * way mapping each address/interface to a name even if that means - * that the Vector contains multiple InetAddresses with the same - * interface name. + * Return a list of VM network interface objects. + * + * @return The list of network interfaces. + * @throws SocketException */ - public static native Vector getInterfaces() + public static native VMNetworkInterface[] getVMInterfaces() throws SocketException; + + private void addAddress(ByteBuffer addr) + throws SocketException, UnknownHostException + { + if (addr.remaining() == 4) + { + byte[] ipv4 = new byte[4]; + addr.get(ipv4); + addresses.add(Inet4Address.getByAddress(ipv4)); + } + else if (addr.remaining() == 16) + { + byte[] ipv6 = new byte[16]; + addr.get(ipv6); + addresses.add(Inet6Address.getByAddress(ipv6)); + } + else + throw new SocketException("invalid interface address"); + } } diff --git a/libjava/classpath/vm/reference/java/nio/channels/VMChannels.java b/libjava/classpath/vm/reference/java/nio/channels/VMChannels.java index e58d7fbf92c..c833b6eecfd 100644 --- a/libjava/classpath/vm/reference/java/nio/channels/VMChannels.java +++ b/libjava/classpath/vm/reference/java/nio/channels/VMChannels.java @@ -40,7 +40,7 @@ package java.nio.channels; import gnu.java.nio.ChannelInputStream; import gnu.java.nio.ChannelOutputStream; -import gnu.java.nio.channels.FileChannelImpl; +import gnu.java.nio.FileChannelImpl; import java.io.FileInputStream; import java.io.FileOutputStream; diff --git a/libjava/classpath/vm/reference/sun/reflect/misc/ReflectUtil.java b/libjava/classpath/vm/reference/sun/reflect/misc/ReflectUtil.java index aa89c50ac9b..88a6f2515bf 100644 --- a/libjava/classpath/vm/reference/sun/reflect/misc/ReflectUtil.java +++ b/libjava/classpath/vm/reference/sun/reflect/misc/ReflectUtil.java @@ -51,9 +51,29 @@ public class ReflectUtil { } + /** + * Check if the current thread is allowed to access the package of + * the declaringClass. + * + * @param declaringClass class name to check access to + * @throws SecurityException if permission is denied + * @throws NullPointerException if declaringClass is null + */ public static void checkPackageAccess(Class declaringClass) { - // FIXME: not sure what to check here. + SecurityManager sm; + if ((sm = System.getSecurityManager()) != null) + { + while (declaringClass.isArray()) + declaringClass = declaringClass.getComponentType(); + String name = declaringClass.getName(); + int i = name.lastIndexOf('.'); + if (i != -1) // if declaringClass is a member of a package + { + name = name.substring(0, i); + sm.checkPackageAccess(name); + } + } } /** @@ -64,6 +84,7 @@ public class ReflectUtil * @param declarer the declaring class of the member * @param ignored unknown parameter; always null * @param modifiers the modifiers on the member + * @return true if access is granted, false otherwise */ public static void ensureMemberAccess(Class caller, Class declarer, |