diff options
Diffstat (limited to 'libjava/java/net')
24 files changed, 2607 insertions, 0 deletions
diff --git a/libjava/java/net/BindException.java b/libjava/java/net/BindException.java new file mode 100644 index 0000000..5f7b491 --- /dev/null +++ b/libjava/java/net/BindException.java @@ -0,0 +1,35 @@ +// BindException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class BindException extends SocketException +{ + public BindException() + { + super(); + } + + public BindException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/ConnectException.java b/libjava/java/net/ConnectException.java new file mode 100644 index 0000000..d4d3a48 --- /dev/null +++ b/libjava/java/net/ConnectException.java @@ -0,0 +1,35 @@ +// ConnectException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class ConnectException extends SocketException +{ + public ConnectException() + { + super(); + } + + public ConnectException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/ContentHandler.java b/libjava/java/net/ContentHandler.java new file mode 100644 index 0000000..fd2e3b1 --- /dev/null +++ b/libjava/java/net/ContentHandler.java @@ -0,0 +1,29 @@ +// ContentHandler.java - Superclass of classes that read from a URLConnection. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +import java.io.IOException; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract class ContentHandler +{ + public abstract Object getContent(URLConnection urlc) throws IOException; +} diff --git a/libjava/java/net/ContentHandlerFactory.java b/libjava/java/net/ContentHandlerFactory.java new file mode 100644 index 0000000..ee6dcff --- /dev/null +++ b/libjava/java/net/ContentHandlerFactory.java @@ -0,0 +1,27 @@ +// ContentHandlerFactory.java - Abstract Content Handler factory. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract interface ContentHandlerFactory +{ + public ContentHandler createContentHandler(String mimetype); +} diff --git a/libjava/java/net/FileNameMap.java b/libjava/java/net/FileNameMap.java new file mode 100644 index 0000000..24e8ef8 --- /dev/null +++ b/libjava/java/net/FileNameMap.java @@ -0,0 +1,27 @@ +// FileNameMap.java - Abstract interface to map from a File Name to MIME type. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract interface FileNameMap +{ + public String getContentTypeFor(String fileName); +} diff --git a/libjava/java/net/HttpURLConnection.java b/libjava/java/net/HttpURLConnection.java new file mode 100644 index 0000000..8b05b73 --- /dev/null +++ b/libjava/java/net/HttpURLConnection.java @@ -0,0 +1,174 @@ +// HttpURLConnection.java - Subclass of communications links using +// Hypertext Transfer Protocol. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +import java.io.*; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 29, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract class HttpURLConnection extends URLConnection +{ + /* HTTP Success Response Codes */ + public static final int HTTP_OK = 200; + public static final int HTTP_CREATED = 201; + public static final int HTTP_ACCEPTED = 202; + public static final int HTTP_NOT_AUTHORITATIVE = 203; + public static final int HTTP_NO_CONTENT = 204; + public static final int HTTP_RESET = 205; + public static final int HTTP_PARTIAL = 206; + + /* HTTP Redirection Response Codes */ + public static final int HTTP_MULT_CHOICE = 300; + public static final int HTTP_MOVED_PERM = 301; + public static final int HTTP_MOVED_TEMP = 302; + public static final int HTTP_SEE_OTHER = 303; + public static final int HTTP_NOT_MODIFIED = 304; + public static final int HTTP_USE_PROXY = 305; + + /* HTTP Client Error Response Codes */ + public static final int HTTP_BAD_REQUEST = 400; + public static final int HTTP_UNAUTHORIZED = 401; + public static final int HTTP_PAYMENT_REQUIRED = 402; + public static final int HTTP_FORBIDDEN = 403; + public static final int HTTP_NOT_FOUND = 404; + public static final int HTTP_BAD_METHOD = 405; + public static final int HTTP_NOT_ACCEPTABLE = 406; + public static final int HTTP_PROXY_AUTH = 407; + public static final int HTTP_CLIENT_TIMEOUT = 408; + public static final int HTTP_CONFLICT = 409; + public static final int HTTP_GONE = 410; + public static final int HTTP_LENGTH_REQUIRED = 411; + public static final int HTTP_PRECON_FAILED = 412; + public static final int HTTP_ENTITY_TOO_LARGE = 413; + public static final int HTTP_REQ_TOO_LONG = 414; + public static final int HTTP_UNSUPPORTED_TYPE = 415; + + /* HTTP Server Error Response Codes */ + public static final int HTTP_SERVER_ERROR = 500; + public static final int HTTP_INTERNAL_ERROR = 501; + public static final int HTTP_BAD_GATEWAY = 502; + public static final int HTTP_UNAVAILABLE = 503; + public static final int HTTP_GATEWAY_TIMEOUT = 504; + public static final int HTTP_VERSION = 505; + + protected String method = "GET"; + protected int responseCode = -1; + protected String responseMessage; + + static boolean followRedirects = true; + + protected HttpURLConnection(URL url) + { + super(url); + } + + public abstract void disconnect(); + + public abstract boolean usingProxy(); + + public static void setFollowRedirects(boolean set) + { + // Throw an exception if an extant security mgr precludes + // setting the factory. + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkSetFactory(); + + followRedirects = set; + } + + public static boolean getFollowRedirects() + { + return followRedirects; + } + + public void setRequestMethod(String method) throws ProtocolException + { + if (connected) + throw new ProtocolException("Already connected"); + + if (method.equals("GET") || method.equals("POST") || + method.equals("HEAD") || method.equals("OPTIONS") || + method.equals("PUT") || method.equals("DELETE") || + method.equals("TRACE")) + this.method = method; + else + throw new ProtocolException("Invalid HTTP request method"); + } + + public String getRequestMethod() + { + return method; + } + + public int getResponseCode() throws IOException + { + getResponseVals(); + return responseCode; + } + + public String getResponseMessage() throws IOException + { + getResponseVals(); + return responseMessage; + } + + private void getResponseVals() throws IOException + { + // Response is the first header received from the connection. + String respField = getHeaderField(0); + if (! respField.startsWith("HTTP/")) + { + // Set to default values on failure. + responseCode = -1; + responseMessage = null; + return; + } + + int firstSpc, nextSpc; + firstSpc = respField.indexOf(' '); + nextSpc = respField.indexOf(' ', firstSpc + 1); + responseMessage = respField.substring(nextSpc + 1); + String codeStr = respField.substring(firstSpc + 1, nextSpc); + try + { + responseCode = Integer.parseInt(codeStr); + } + catch (NumberFormatException e) + { + // Set to default values on failure. + responseCode = -1; + responseMessage = null; + } + if (responseCode == HTTP_NOT_FOUND) + throw new FileNotFoundException(url.toString()); + else if (responseCode >= 400) + throw new IOException(url.toString() + " " + respField); + } + + // TODO12: public Permission getPermission() throws IOException + // { + // } + + // TODO12: public InputStream getErrorStream() + // { + // } +} diff --git a/libjava/java/net/InetAddress.java b/libjava/java/net/InetAddress.java new file mode 100644 index 0000000..baf5153e --- /dev/null +++ b/libjava/java/net/InetAddress.java @@ -0,0 +1,255 @@ +// INetAddress.java -- An Internet Protocol (IP) address. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Per Bothner + * @date January 6, 1999. + */ + +/* + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * (The latter turns out to have some errors ...) + * Status: Believed complete and correct. + */ + +public final class InetAddress +{ + String hostname; + byte[] address; + + InetAddress (byte[] address, String hostname) + { + this.address = address; + this.hostname = hostname; + } + + public boolean isMulticastAddress () + { + int len = address.length; + if (len == 4) + return (address[0] & 0xF0) == 0xE0; + if (len == 16) + return address[0] == (byte) 0xFF; + return false; + } + + public String getHostName () + { + if (hostname == null) + lookup (null, this, false); + return hostname; + } + + public byte[] getAddress () + { + // An experiment shows that JDK1.2 returns a different byte array each + // time. This makes sense, in terms of security. + return (byte[]) address.clone(); + } + + /* Helper function due to a CNI limitation. */ + private static InetAddress[] allocArray (int count) + { + return new InetAddress[count]; + } + + /* Helper function due to a CNI limitation. */ + private static SecurityException checkConnect (String hostname) + { + SecurityManager s = System.getSecurityManager(); + if (s == null) + return null; + try + { + s.checkConnect(hostname, -1); + return null; + } + catch (SecurityException ex) + { + return ex; + } + } + + public String getHostAddress () + { + StringBuffer sbuf = new StringBuffer(40); + int len = address.length; + int i = 0; + if (len == 16) + { // An IPv6 address. + for (; ; i += 2) + { + if (i >= 16) + return sbuf.toString(); + int x = ((address[i] & 0xFF) << 8) | (address[i+1] & 0xFF); + boolean empty = sbuf.length() == 0; + if (empty) + { + if (i == 10 && x == 0xFFFF) + { // IPv4-mapped IPv6 address. + sbuf.append(":FFFF:"); + break; // Continue as IPv4 address; + } + else if (i == 12) + { // IPv4-compatible IPv6 address. + sbuf.append(':'); + break; // Continue as IPv4 address. + } + else if (i > 0) + sbuf.append("::"); + } + else + sbuf.append(':'); + if (x != 0 || i >= 14) + sbuf.append(Integer.toHexString(x).toUpperCase()); + } + } + for ( ; ; ) + { + sbuf.append(address[i] & 0xFF); + i++; + if (i == len) + break; + sbuf.append('.'); + } + return sbuf.toString(); + } + + public int hashCode() + { + // There hashing algorithm is not specified, but a simple experiment + // shows that it is equal to the address, as a 32-bit big-endian integer. + int hash = 0; + int len = address.length; + int i = len > 4 ? len - 4 : 0; + for ( ; i < len; i++) + hash = (hash << 8) | (address[i] & 0xFF); + return hash; + } + + public boolean equals (Object obj) + { + if (obj == null || ! (obj instanceof InetAddress)) + return false; + // "The Java Class Libraries" 2nd edition says "If a machine has + // multiple names instances of InetAddress for different name of + // that same machine are not equal. This is because they have + // different host names." This violates the description in the + // JDK 1.2 API documentation. A little experiementation + // shows that the latter is correct. + byte[] addr1 = address; + byte[] addr2 = ((InetAddress) obj).address; + if (addr1.length != addr2.length) + return false; + for (int i = addr1.length; --i >= 0; ) + if (addr1[i] != addr2[i]) + return false; + return true; + } + + public String toString() + { + return getHostName()+'/'+getHostAddress(); + } + + /** If host is a valid numeric IP address, return the numeric address. + * Otherwise, return null. */ + private static native byte[] aton (String host); + + private static native InetAddress[] lookup + (String hostname, InetAddress addr, boolean all); + + public static InetAddress getByName (String host) + throws UnknownHostException + { + if (host == null) + return getLocalHost(); + byte[] address = aton(host); + if (address != null) + return new InetAddress(address, null); + InetAddress iaddr = new InetAddress(null, null); + lookup(host, iaddr, false); + return iaddr; + } + + public static InetAddress[] getAllByName (String host) + throws UnknownHostException + { + byte[] address = aton(host); + if (address != null) + { + InetAddress[] result = new InetAddress[1]; + result[0] = new InetAddress(address, null); + return result; + } + return lookup(host, null, true); + } + + private static final byte[] localhostAddress = { 127, 0, 0, 1 }; + + private static native String getLocalHostname (); + + private static InetAddress localhost = null; + + public static InetAddress getLocalHost() throws UnknownHostException + { + SecurityManager s = System.getSecurityManager(); + // Experimentation shows that JDK1.2 does cache the result. + // However, if there is a security manager, and the cached result + // is other than "localhost", we need to check again. + if (localhost == null + || (s != null && localhost.address != localhostAddress)) + getLocalHost(s); + return localhost; + } + + private static synchronized void getLocalHost(SecurityManager s) + throws UnknownHostException + { + // Check the localhost cache again, now that we've synchronized. + if (s == null && localhost != null) + return; + String hostname = getLocalHostname(); + if (s != null) + { + // "The Java Class Libraries" suggests that if the security + // manager disallows getting the local host name, then + // we use the loopback host. + // However, the JDK 1.2 API claims to throw SecurityException, + // which seems to suggest SecurityException is *not* caught. + // In this case, experimentation shows that former is correct. + try + { + // This is wrong, if the name returned from getLocalHostname() + // is not a fully qualified name. FIXME. + s.checkConnect(hostname, -1); + } + catch (SecurityException ex) + { + hostname = null; + } + } + if (hostname != null) + { + try + { + localhost = getByName(hostname); + } + catch (Exception ex) + { + } + } + if (localhost == null) + localhost = new InetAddress (localhostAddress, "localhost"); + } +} diff --git a/libjava/java/net/MalformedURLException.java b/libjava/java/net/MalformedURLException.java new file mode 100644 index 0000000..a5a8db5 --- /dev/null +++ b/libjava/java/net/MalformedURLException.java @@ -0,0 +1,35 @@ +// MalformedURLException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class MalformedURLException extends java.io.IOException +{ + public MalformedURLException() + { + super(); + } + + public MalformedURLException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/NoRouteToHostException.java b/libjava/java/net/NoRouteToHostException.java new file mode 100644 index 0000000..dc01688 --- /dev/null +++ b/libjava/java/net/NoRouteToHostException.java @@ -0,0 +1,35 @@ +// NoRouteToHostException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class NoRouteToHostException extends SocketException +{ + public NoRouteToHostException() + { + super(); + } + + public NoRouteToHostException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/PlainSocketImpl.java b/libjava/java/net/PlainSocketImpl.java new file mode 100644 index 0000000..5bc2cae --- /dev/null +++ b/libjava/java/net/PlainSocketImpl.java @@ -0,0 +1,64 @@ +// natClass.cc - Implementation of java.lang.Class native methods. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; +import java.io.*; + +class PlainSocketImpl extends SocketImpl +{ + int fnum = -1; + + protected native void create (boolean stream) throws IOException; + + protected void connect (String host, int port) throws IOException + { + connect(InetAddress.getByName(host), port); + } + + protected native void connect (InetAddress host, int port) + throws IOException; + + protected native void bind (InetAddress host, int port) throws IOException; + + protected native void listen (int backlog) throws IOException; + + private native void accept (PlainSocketImpl s) throws IOException; + protected void accept (SocketImpl s) throws IOException + { + accept((PlainSocketImpl) s); + } + + private InputStream in; + private OutputStream out; + + protected InputStream getInputStream() throws IOException + { + if (in == null) + in = new FileInputStream (fd); + return in; + } + + protected OutputStream getOutputStream() throws IOException + { + if (out == null) + out = new FileOutputStream (fd); + return out; + } + + protected int available () throws IOException + { + return in.available(); + } + + protected void close () throws IOException + { + fd.close(); + } +} diff --git a/libjava/java/net/ProtocolException.java b/libjava/java/net/ProtocolException.java new file mode 100644 index 0000000..f7db685 --- /dev/null +++ b/libjava/java/net/ProtocolException.java @@ -0,0 +1,35 @@ +// ProtocolException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class ProtocolException extends java.io.IOException +{ + public ProtocolException() + { + super(); + } + + public ProtocolException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/ServerSocket.java b/libjava/java/net/ServerSocket.java new file mode 100644 index 0000000..e4b5069 --- /dev/null +++ b/libjava/java/net/ServerSocket.java @@ -0,0 +1,105 @@ +// Socket.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date January 6, 1999. + */ + +/** Written using on-line Java Platform 1.2 API Specification. + * Status: I believe all methods are implemented, but many + * of them just throw an exception. + */ + +package java.net; +import java.io.*; + +public class ServerSocket +{ + static SocketImplFactory factory; + SocketImpl impl; + + public ServerSocket (int port) + throws java.io.IOException + { + this(port, 5); + } + + public ServerSocket (int port, int backlog) + throws java.io.IOException + { + this(port, backlog, InetAddress.getLocalHost()); + } + + public ServerSocket (int port, int backlog, InetAddress bindAddr) + throws java.io.IOException + { + if (factory == null) + this.impl = new PlainSocketImpl(); + else + this.impl = factory.createSocketImpl(); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkListen(port); + impl.create(true); + impl.bind(bindAddr, port); + impl.listen(backlog); + } + + public InetAddress getInetAddress() + { + return impl.getInetAddress(); + } + + public int getLocalPort() + { + return impl.getLocalPort(); + } + + public Socket accept () throws IOException + { + Socket s = new Socket(Socket.factory == null ? new PlainSocketImpl() + : Socket.factory.createSocketImpl()); + implAccept (s); + return s; + } + + protected final void implAccept (Socket s) throws IOException + { + impl.accept(s.impl); + } + + public void close () throws IOException + { + impl.close(); + } + + public void setSoTimeout (int timeout) throws SocketException + { + throw new InternalError("ServerSocket.setSoTimeout not implemented"); + } + + public int getSoTimeout () throws SocketException + { + throw new InternalError("ServerSocket.getSoTimeout not implemented"); + } + + public String toString () + { + return impl.toString(); + } + + public static void setSocketImplFactory (SocketImplFactory fac) + throws IOException + { + factory = fac; + } + +} diff --git a/libjava/java/net/Socket.java b/libjava/java/net/Socket.java new file mode 100644 index 0000000..8c027d9 --- /dev/null +++ b/libjava/java/net/Socket.java @@ -0,0 +1,209 @@ +// Socket.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date January 6, 1999. + */ + +/** Written using on-line Java Platform 1.2 API Specification. + * Status: I believe all methods are implemented, but many + * of them just throw an exception. + */ + +package java.net; +import java.io.*; + +public class Socket +{ + static SocketImplFactory factory; + SocketImpl impl; + + protected Socket () + { + } + + protected Socket (SocketImpl impl) throws SocketException + { + this.impl = impl; + } + + public Socket (String host, int port) + throws UnknownHostException, IOException + { + this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(host, port); + impl.create(true); + impl.connect(host, port); + } + + public Socket (InetAddress address, int port) + throws IOException + { + this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(address.getHostName(), port); + impl.create(true); + impl.connect(address, port); + } + + public Socket (String host, int port, + InetAddress localAddr, int localPort) throws IOException + { + this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(host, port); + impl.create(true); + impl.bind(localAddr, localPort); + impl.connect(host, port); + } + + public Socket (InetAddress address, int port, + InetAddress localAddr, int localPort) throws IOException + { + this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(address.getHostName(), port); + impl.create(true); + impl.bind(localAddr, localPort); + impl.connect(address, port); + } + + /** + * @deprecated Use DatagramSocket instead for UDP transport. + */ + public Socket (String host, int port, boolean stream) throws IOException + { + impl = factory == null ? new PlainSocketImpl() + : factory.createSocketImpl(); + impl.create(stream); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(host, port); + impl.connect(host, port); + } + + /** + * @deprecated Use DatagramSocket instead for UDP transport. + */ + public Socket (InetAddress host, int port, boolean stream) throws IOException + { + impl = factory == null ? new PlainSocketImpl() + : factory.createSocketImpl(); + impl.create(stream); + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkConnect(host.getHostName(), port); + impl.connect(host, port); + } + + public InetAddress getInetAddress () + { + return impl.getInetAddress(); + } + + public InetAddress getLocalAddress () + { + // There doesn't seem to be any way to implement this + // using a (generic) SocketImpl ... What am I missing? + throw new InternalError("Socket.getLocalAddres not implemented"); + } + + public int getPort () + { + return impl.getPort(); + } + + public int getLocalPort () + { + return impl.getLocalPort(); + } + + public InputStream getInputStream () throws IOException + { + return impl.getInputStream(); + } + + public OutputStream getOutputStream () throws IOException + { + return impl.getOutputStream(); + } + + public void setTcpNoDelay (boolean on) throws SocketException + { + throw new InternalError("Socket.setTcpNoDelay not implemented"); + } + + public boolean getTcpNoDelay() throws SocketException + { + throw new InternalError("Socket.getTcpNoDelay not implemented"); + } + + public void setSoLinger(boolean on, int linger) throws SocketException + { + throw new InternalError("Socket.setSoLinger not implemented"); + } + + public boolean getSoLinger() throws SocketException + { + throw new InternalError("Socket.getSoLinger not implemented"); + } + + public void setSoTimeout (int timeout) throws SocketException + { + throw new InternalError("Socket.setSoTimeout not implemented"); + } + + public int getSoTimeout () throws SocketException + { + throw new InternalError("Socket.getSoTimeout not implemented"); + } + + public void setSendBufferSize (int size) throws SocketException + { + throw new InternalError("Socket.setSendBufferSize not implemented"); + } + + public int getSendBufferSize () throws SocketException + { + throw new InternalError("Socket.getSendBufferSize not implemented"); + } + + public void setReceiveBufferSize (int size) throws SocketException + { + throw new InternalError("Socket.setReceiveBufferSize not implemented"); + } + + public int getReceiveBufferSize () throws SocketException + { + throw new InternalError("Socket.getReceiveBufferSize not implemented"); + } + + public void close () throws IOException + { + impl.close(); + } + + public String toString () + { + return impl.toString(); + } + + public static void setSocketImplFactory (SocketImplFactory fac) + throws IOException + { + factory = fac; + } +} diff --git a/libjava/java/net/SocketException.java b/libjava/java/net/SocketException.java new file mode 100644 index 0000000..24a50ef --- /dev/null +++ b/libjava/java/net/SocketException.java @@ -0,0 +1,33 @@ +// SocketException.java - Base class for networking exceptions + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Per Bothner + * @date January 6, 1999. + */ + +/** Written using on-line Java Platform 1.2 API Specification. + * Believed complete and correct. + */ + +public class SocketException extends java.io.IOException +{ + public SocketException () + { + super(); + } + + public SocketException (String s) + { + super(s); + } +} diff --git a/libjava/java/net/SocketImpl.java b/libjava/java/net/SocketImpl.java new file mode 100644 index 0000000..5ad3118 --- /dev/null +++ b/libjava/java/net/SocketImpl.java @@ -0,0 +1,70 @@ +// SocketImpl.java - Abstract socket implementation. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; +import java.io.*; + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date January 6, 1999. + */ + +/** Written using on-line Java Platform 1.2 API Specification. + * Believed complete and correct, except for implementation of toString. + */ + +public abstract class SocketImpl +{ + protected InetAddress address; + + protected FileDescriptor fd; + + protected int localport; + + protected int port; + + public SocketImpl () + { + } + + protected abstract void create (boolean stream) throws IOException; + + protected abstract void connect (String host, int port) throws IOException; + + protected abstract void connect (InetAddress host, int port) + throws IOException; + + protected abstract void bind (InetAddress host, int port) throws IOException; + + protected abstract void listen (int backlog) throws IOException; + + protected abstract void accept (SocketImpl s) throws IOException; + + protected abstract InputStream getInputStream() throws IOException; + + protected abstract OutputStream getOutputStream() throws IOException; + + protected abstract int available () throws IOException; + + protected abstract void close () throws IOException; + + protected FileDescriptor getFileDescriptor () { return fd; } + + protected InetAddress getInetAddress () { return address; } + + protected int getPort () { return port; } + + protected int getLocalPort () { return localport; } + + public String toString () + { + return super.toString(); // FIXME + } +} diff --git a/libjava/java/net/SocketImplFactory.java b/libjava/java/net/SocketImplFactory.java new file mode 100644 index 0000000..7631ab8 --- /dev/null +++ b/libjava/java/net/SocketImplFactory.java @@ -0,0 +1,25 @@ +// SocketImplFactory.java - Abstract socket implementation factory. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date January 6, 1999. + */ + +/** Written using on-line Java Platform 1.2 API Specification. + * Status: Believed complete and correct. + */ + +public abstract interface SocketImplFactory +{ + public SocketImpl createSocketImpl (); +} diff --git a/libjava/java/net/URL.java b/libjava/java/net/URL.java new file mode 100644 index 0000000..da56f49 --- /dev/null +++ b/libjava/java/net/URL.java @@ -0,0 +1,341 @@ +// URL.java - A Uniform Resource Locator. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +import java.io.*; +import java.util.Hashtable; +import java.util.StringTokenizer; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 4, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public final class URL implements Serializable +{ + private String protocol; + private String host; + private int port; + private String file; + private String ref; + private URLStreamHandler handler; + private static Hashtable handlers = new Hashtable(); + private static URLStreamHandlerFactory factory; + + public URL(String protocol, String host, int port, String file) + throws MalformedURLException + { + this(protocol, host, port, file, null); + } + + public URL(String protocol, String host, String file) + throws MalformedURLException + { + this(protocol, host, -1, file, null); + } + + // JDK1.2 + public URL(String protocol, String host, int port, String file, + URLStreamHandler handler) throws MalformedURLException + { + if (protocol == null) + throw new MalformedURLException("null protocol"); + this.protocol = protocol; + + if (handler != null) + { + // TODO12: Need SecurityManager.checkPermission and + // TODO12: java.net.NetPermission from JDK 1.2 to be implemented. + // Throw an exception if an extant security mgr precludes + // specifying a StreamHandler. + // + // SecurityManager s = System.getSecurityManager(); + // if (s != null) + // s.checkPermission(NetPermission("specifyStreamHandler")); + + this.handler = handler; + } + else + this.handler = setURLStreamHandler(protocol); + + if (this.handler == null) + throw new MalformedURLException("Handler for protocol not found"); + + this.host = host; + + this.port = port; + + int hashAt = file.indexOf('#'); + if (hashAt < 0) + { + this.file = file; + this.ref = null; + } + else + { + this.file = file.substring(0, hashAt); + this.ref = file.substring(hashAt + 1); + } + } + + public URL(String spec) throws MalformedURLException + { + this((URL) null, spec, (URLStreamHandler) null); + } + + public URL(URL context, String spec) throws MalformedURLException + { + this(context, spec, (URLStreamHandler) null); + } + + // JDK1.2 + public URL(URL context, String spec, URLStreamHandler handler) + throws MalformedURLException + { + /* A protocol is defined by the doc as the substring before a ':' + * as long as the ':' occurs before any '/'. + * + * If context is null, then spec must be an absolute URL. + * + * The relative URL need not specify all the components of a URL. + * If the protocol, host name, or port number is missing, the value + * is inherited from the context. A bare file component is appended + * to the context's file. The optional anchor is not inherited. + */ + + int colon; + int slash; + if ((colon = spec.indexOf(':')) > 0 && + (colon < (slash = spec.indexOf('/')) || slash < 0)) + { + // Protocol specified in spec string. + protocol = spec.substring(0, colon); + if (context != null && context.protocol == protocol) + { + // The 1.2 doc specifically says these are copied to the new URL. + host = context.host; + port = context.port; + file = context.file; + } + } + else if (context != null) + { + // Protocol NOT specified in spec string. + // Use context fields (except ref) as a foundation for relative URLs. + colon = -1; + protocol = context.protocol; + host = context.host; + port = context.port; + file = context.file; + } + else // Protocol NOT specified in spec. and no context available. + throw new + MalformedURLException("Absolute URL required with null context"); + + if (handler != null) + { + // TODO12: Need SecurityManager.checkPermission and + // TODO12: java.net.NetPermission from JDK 1.2 to be implemented. + // Throw an exception if an extant security mgr precludes + // specifying a StreamHandler. + // + // SecurityManager s = System.getSecurityManager(); + // if (s != null) + // s.checkPermission(NetPermission("specifyStreamHandler")); + + this.handler = handler; + } + else + this.handler = setURLStreamHandler(protocol); + + if (this.handler == null) + throw new MalformedURLException("Handler for protocol not found"); + + // JDK 1.2 doc for parseURL specifically states that any '#' ref + // is to be excluded by passing the 'limit' as the indexOf the '#' + // if one exists, otherwise pass the end of the string. + int hashAt = spec.indexOf('#', colon + 1); + this.handler.parseURL(this, spec, colon + 1, + hashAt < 0 ? spec.length() : hashAt); + if (hashAt >= 0) + ref = spec.substring(hashAt + 1); + } + + public boolean equals(Object obj) + { + if (obj == null || ! (obj instanceof URL)) + return false; + + URL uObj = (URL) obj; + if (protocol != uObj.protocol || host != uObj.host || port != uObj.port || + file != uObj.file || ref != uObj.ref) + return false; + + return true; + } + + public final Object getContent() throws IOException + { + return openConnection().getContent(); + } + + public String getFile() + { + return file; + } + + public String getHost() + { + return host; + } + + public int getPort() + { + return port; + } + + public String getProtocol() + { + return protocol; + } + + public String getRef() + { + return ref; + } + + public int hashCode() + { + // JCL book says this is computed using (only) the hashcodes of the + // protocol, host and file fields. Empirical evidence indicates this + // is probably XOR. + return (protocol.hashCode() ^ host.hashCode() ^ file.hashCode()); + } + + public URLConnection openConnection() throws IOException + { + return handler.openConnection(this); + } + + public final InputStream openStream() throws IOException + { + return openConnection().getInputStream(); + } + + public boolean sameFile(URL other) + { + if (other == null || protocol != other.protocol || host != other.host || + port != other.port || file != other.file) + return false; + + return true; + } + + protected void set(String protocol, String host, int port, String file, + 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; + this.port = port; + this.host = host; + this.file = file; + this.ref = ref; + } + + public static synchronized void + setURLStreamHandlerFactory(URLStreamHandlerFactory fac) + { + if (factory != null) + throw new Error("URLStreamHandlerFactory already set"); + + // Throw an exception if an extant security mgr precludes + // setting the factory. + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkSetFactory(); + factory = fac; + } + + public String toExternalForm() + { + // Identical to toString(). + return handler.toExternalForm(this); + } + + public String toString() + { + // Identical to toExternalForm(). + return handler.toExternalForm(this); + } + + private URLStreamHandler setURLStreamHandler(String protocol) + { + URLStreamHandler handler; + + // See if a handler has been cached for this protocol. + if ((handler = (URLStreamHandler) handlers.get(protocol)) != null) + return handler; + + // If a non-default factory has been set, use it to find the protocol. + if (factory != null) + handler = factory.createURLStreamHandler(protocol); + + // Non-default factory may have returned null or a factory wasn't set. + // Use the default search algorithm to find a handler for this protocol. + if (handler == null) + { + // Get the list of packages to check and append our default handler + // to it, along with the JDK specified default as a last resort. + // Except in very unusual environments the JDK specified one shouldn't + // ever be needed (or available). + String propVal = System.getProperty("java.protocol.handler.pkgs"); + propVal = (propVal == null) ? "" : (propVal + "|"); + propVal = propVal + "gnu.gcj.protocol|sun.net.www.protocol"; + + StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|"); + do + { + String facName = pkgPrefix.nextToken() + "." + protocol + + ".Handler"; + try + { + handler = + (URLStreamHandler) Class.forName(facName).newInstance(); + } + catch (Exception e) + { + // Can't instantiate; handler still null, go on to next element. + } + } while ((handler == null || + ! (handler instanceof URLStreamHandler)) && + pkgPrefix.hasMoreTokens()); + } + + // Update the hashtable with the new protocol handler. + if (handler != null) + if (handler instanceof URLStreamHandler) + handlers.put(protocol, handler); + else + handler = null; + + return handler; + } +} diff --git a/libjava/java/net/URLConnection.java b/libjava/java/net/URLConnection.java new file mode 100644 index 0000000..12e8a8b --- /dev/null +++ b/libjava/java/net/URLConnection.java @@ -0,0 +1,423 @@ +// URLConnection.java - Superclass of all communications links between +// an application and a URL. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +import java.io.*; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Hashtable; +import java.util.StringTokenizer; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Two guessContentTypeFrom... methods not implemented. + * getContent method assumes content type from response; see comment there. + */ + +public abstract class URLConnection +{ + protected URL url; + protected boolean doInput = true; + protected boolean doOutput = false; + protected boolean allowUserInteraction; + protected boolean useCaches; + protected long ifModifiedSince = 0L; + protected boolean connected = false; + private static boolean defaultAllowUserInteraction = false; + private static boolean defaultUseCaches = true; + private static FileNameMap fileNameMap; // Set by the URLConnection subclass. + private static ContentHandlerFactory factory; + private static ContentHandler contentHandler; + private static Hashtable handlers = new Hashtable(); + private static Locale locale = new Locale("En", "Us", "Unix"); + private static SimpleDateFormat dateFormat1 = + new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale); + private static SimpleDateFormat dateFormat2 = + new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale); + private static SimpleDateFormat dateFormat3 = + new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale); + + protected URLConnection(URL url) + { + this.url = url; + allowUserInteraction = defaultAllowUserInteraction; + useCaches = defaultUseCaches; + } + + public abstract void connect() throws IOException; + + public URL getURL() + { + return url; + } + + public int getContentLength() + { + return getHeaderFieldInt("content-length", -1); + } + + public String getContentType() + { + return getHeaderField("content-type"); + } + + public String getContentEncoding() + { + return getHeaderField("content-encoding"); + } + + public long getExpiration() + { + return getHeaderFieldDate("expiration", 0L); + } + + public long getDate() + { + return getHeaderFieldDate("date", 0L); + } + + public long getLastModified() + { + return getHeaderFieldDate("last-modified", 0L); + } + + public String getHeaderField(int n) + { + // Subclasses for specific protocols override this. + return null; + } + + public String getHeaderField(String name) + { + // Subclasses for specific protocols override this. + return null; + } + + public int getHeaderFieldInt(String name, int val) + { + String str = getHeaderField(name); + try + { + if (str != null) + val = Integer.parseInt(str); + } + catch (NumberFormatException e) + { + ; // Do nothing; val is the default. + } + return val; + } + + public long getHeaderFieldDate(String name, long val) + { + String str = getHeaderField(name); + if (str != null) + { + Date date; + if ((date = dateFormat1.parse(str, new ParsePosition(0))) != null) + val = date.getTime(); + else if ((date = dateFormat2.parse(str, new ParsePosition(0))) != null) + val = date.getTime(); + else if ((date = dateFormat3.parse(str, new ParsePosition(0))) != null) + val = date.getTime(); + } + return val; + } + + public String getHeaderFieldKey(int n) + { + // Subclasses for specific protocols override this. + return null; + } + + public Object getContent() throws IOException + { + // FIXME: Doc indicates that other criteria should be applied as + // heuristics to determine the true content type, e.g. see + // guessContentTypeFromName() and guessContentTypeFromStream methods + // as well as FileNameMap class & fileNameMap field & get/set methods. + String cType = getContentType(); + contentHandler = setContentHandler(cType); + if (contentHandler == null) + return getInputStream(); + + return contentHandler.getContent(this); + } + +// TODO12: public Permission getPermission() throws IOException +// { +// // Subclasses may override this. +// return java.security.AllPermission; +// } + + public InputStream getInputStream() throws IOException + { + // Subclasses for specific protocols override this. + throw new UnknownServiceException("Protocol " + url.getProtocol() + + " does not support input."); + } + + public OutputStream getOutputStream() throws IOException + { + // Subclasses for specific protocols override this. + throw new UnknownServiceException("Protocol " + url.getProtocol() + + " does not support output."); + } + + public String toString() + { + return this.getClass().getName() + ":" + url.toString(); + } + + public void setDoInput(boolean doinput) + { + if (connected) + throw new IllegalAccessError("Already connected"); + + doInput = doinput; + } + + public boolean getDoInput() + { + return doInput; + } + + public void setDoOutput(boolean dooutput) + { + if (connected) + throw new IllegalAccessError("Already connected"); + + doOutput = dooutput; + if (doOutput) + doInput = false; + } + + public boolean getDoOutput() + { + return doOutput; + } + + public void setAllowUserInteraction(boolean allowuserinteraction) + { + if (connected) + throw new IllegalAccessError("Already connected"); + + allowUserInteraction = allowuserinteraction; + } + + public boolean getAllowUserInteraction() + { + return allowUserInteraction; + } + + public static void + setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) + { + defaultAllowUserInteraction = defaultallowuserinteraction; + } + + public static boolean getDefaultAllowUserInteraction() + { + return defaultAllowUserInteraction; + } + + public void setUseCaches(boolean usecaches) + { + if (connected) + throw new IllegalAccessError("Already connected"); + + useCaches = usecaches; + } + + public boolean getUseCaches() + { + return useCaches; + } + + public void setIfModifiedSince(long ifmodifiedsince) + { + if (connected) + throw new IllegalAccessError("Already connected"); + + ifModifiedSince = ifmodifiedsince; + } + + public long getIfModifiedSince() + { + return ifModifiedSince; + } + + public boolean getDefaultUseCaches() + { + return defaultUseCaches; + } + + public void setDefaultUseCaches(boolean defaultusecaches) + { + defaultUseCaches = defaultusecaches; + } + + public void setRequestProperty(String key, String value) + { + // Do nothing unless overridden by subclasses that support setting + // header fields in the request. + } + + public String getRequestProperty(String key) + { + // Overridden by subclasses that support reading header fields from the + // request. + return null; + } + + public static void setDefaultRequestProperty(String key, String value) + { + // Do nothing unless overridden by subclasses that support setting + // default request properties. + } + + public static String getDefaultRequestProperty(String key) + { + // Overridden by subclasses that support default request properties. + return null; + } + + public static void setContentHandlerFactory(ContentHandlerFactory fac) + { + if (factory != null) + throw new Error("ContentHandlerFactory already set"); + + // Throw an exception if an extant security mgr precludes + // setting the factory. + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkSetFactory(); + factory = fac; + } + +// TODO: protected static String guessContentTypeFromName(String fname) +// { +// } + +// TODO: public static String guessContentTypeFromStream(InputStream is) +// throws IOException +// { +// } + +// TODO12: protected void parseURL(URL u, String spec, int start, int limit) + + // JDK1.2 + public static FileNameMap getFileNameMap() + { + return fileNameMap; + } + + // JDK1.2 + public static void setFileNameMap(FileNameMap map) + { + // Throw an exception if an extant security mgr precludes + // setting the factory. + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkSetFactory(); + + fileNameMap = map; + } + + private ContentHandler setContentHandler(String contentType) + { + ContentHandler handler; + + // No content type so just handle it as the default. + if (contentType == null || contentType == "") + return null; + + // See if a handler has been cached for this content type. + // For efficiency, if a content type has been searched for but not + // found, it will be in the hash table but as the contentType String + // instead of a ContentHandler. + if ((handler = (ContentHandler) handlers.get(contentType)) != null) + if (handler instanceof ContentHandler) + return handler; + else + return null; + + // If a non-default factory has been set, use it to find the content type. + if (factory != null) + handler = factory.createContentHandler(contentType); + + // Non-default factory may have returned null or a factory wasn't set. + // Use the default search algorithm to find a handler for this content type. + if (handler == null) + { + // Get the list of packages to check and append our default handler + // to it, along with the JDK specified default as a last resort. + // Except in very unusual environments the JDK specified one shouldn't + // ever be needed (or available). + String propVal = System.getProperty("java.content.handler.pkgs"); + propVal = (propVal == null) ? "" : (propVal + "|"); + propVal = propVal + "gnu.gcj.content|sun.net.www.content"; + + // Replace the '/' character in the content type with '.' and + // all other non-alphabetic, non-numeric characters with '_'. + StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|"); + char[] cArray = contentType.toCharArray(); + for (int i = 0; i < cArray.length; i++) + { + if (cArray[i] == '/') + cArray[i] = '.'; + else if (! ((cArray[i] >= 'A' && cArray[i] <= 'Z') || + (cArray[i] >= 'a' && cArray[i] <= 'z') || + (cArray[i] >= '0' && cArray[i] <= '9'))) + cArray[i] = '_'; + } + String contentClass = new String(cArray); + + // See if a class of this content type exists in any of the packages. + do + { + String facName = pkgPrefix.nextToken() + "." + contentClass; + try + { + handler = + (ContentHandler) Class.forName(facName).newInstance(); + } + catch (Exception e) + { + // Can't instantiate; handler still null, go on to next element. + } + } while ((handler == null || + ! (handler instanceof ContentHandler)) && + pkgPrefix.hasMoreTokens()); + } + + // Update the hashtable with the new content handler. + if (handler != null && handler instanceof ContentHandler) + { + handlers.put(contentType, handler); + return handler; + } + + // For efficiency on subsequent searches, put a dummy entry in the hash + // table for content types that don't have a non-default ContentHandler. + handlers.put(contentType, contentType); + return null; + } +} diff --git a/libjava/java/net/URLStreamHandler.java b/libjava/java/net/URLStreamHandler.java new file mode 100644 index 0000000..29e0e6d --- /dev/null +++ b/libjava/java/net/URLStreamHandler.java @@ -0,0 +1,107 @@ +// URLStreamHandler.java - Superclass of all stream protocol handlers. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 4, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract class URLStreamHandler +{ + protected abstract URLConnection openConnection(URL u) + throws java.io.IOException; + +protected void parseURL(URL u, String spec, int start, int limit) + { + String tmpStr; + String host = ""; // Initialize to null string. + String file; + int port = -1; + int colon; + + /* TBD: The JDK 1.2 doc specifically says that limit is the position + * to stop parsing at and that it will be either the end of the string + * or the position of '#'; thus the doc infers that this method does + * not set the ref. + */ + tmpStr = spec.substring(start, limit); + int hostEnd = 0; + if (tmpStr.startsWith("//")) + { + int slash = tmpStr.indexOf('/', 2); + hostEnd = tmpStr.length(); + if (slash >= 0) + hostEnd = slash; + + host = tmpStr.substring(2, hostEnd); + + // Look for optional port number. + if ((colon = host.indexOf(':')) >= 0) + { + try + { + port = Integer.parseInt(host.substring(colon + 1)); + } + catch (NumberFormatException e) + { + ; // Ignore invalid port values; port is already set to -1. + } + host = host.substring(0, colon); + } + } + + if (hostEnd < tmpStr.length()) + file = ((tmpStr.startsWith("/")) ? "" : "/") + tmpStr.substring(hostEnd); + else + file = "/"; + + u.set(u.getProtocol(), host, port, file, u.getRef()); + } + + protected void setURL(URL u, String protocol, String host, int port, + String file, String ref) + { + u.set(protocol, host, port, file, ref); + } + + protected String toExternalForm(URL u) + { + String resStr, host, file, ref; + int port; + + resStr = u.getProtocol() + ":"; + host = u.getHost(); + port = u.getPort(); + file = u.getFile(); + ref = u.getRef(); + + if (! host.equals("")) + { + resStr = resStr + "//" + host; + if (port >= 0) + resStr = resStr + ":" + port; + } + + resStr = resStr + file; + + if (ref != null) + resStr = resStr + "#" + ref; + + return resStr; + } +} diff --git a/libjava/java/net/URLStreamHandlerFactory.java b/libjava/java/net/URLStreamHandlerFactory.java new file mode 100644 index 0000000..474d723 --- /dev/null +++ b/libjava/java/net/URLStreamHandlerFactory.java @@ -0,0 +1,27 @@ +// URLStreamHandlerFactory.java - Abstract URL Stream Handler factory. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public abstract interface URLStreamHandlerFactory +{ + public URLStreamHandler createURLStreamHandler(String protocol); +} diff --git a/libjava/java/net/UnknownHostException.java b/libjava/java/net/UnknownHostException.java new file mode 100644 index 0000000..1c20509 --- /dev/null +++ b/libjava/java/net/UnknownHostException.java @@ -0,0 +1,34 @@ +// UnknownHostException.java + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Per Bothner + * @date January 6, 1999. + */ + +/* + * Written using on-line Java Platform 1.2 API Specification. + * Status: Believed complete and correct. + */ + +public class UnknownHostException extends java.io.IOException +{ + public UnknownHostException () + { + super(); + } + + public UnknownHostException (String host) + { + super(host); + } +} diff --git a/libjava/java/net/UnknownServiceException.java b/libjava/java/net/UnknownServiceException.java new file mode 100644 index 0000000..dba798e --- /dev/null +++ b/libjava/java/net/UnknownServiceException.java @@ -0,0 +1,35 @@ +// UnknownServiceException.java + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.net; + +/** + * @author Warren Levy <warrenl@cygnus.com> + * @date March 5, 1999. + */ + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class UnknownServiceException extends java.io.IOException +{ + public UnknownServiceException() + { + super(); + } + + public UnknownServiceException(String msg) + { + super(msg); + } +} diff --git a/libjava/java/net/natInetAddress.cc b/libjava/java/net/natInetAddress.cc new file mode 100644 index 0000000..7f7d953 --- /dev/null +++ b/libjava/java/net/natInetAddress.cc @@ -0,0 +1,270 @@ +// natClass.cc - Implementation of java.lang.Class native methods. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <errno.h> + +#include <sys/param.h> +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <cni.h> +#include <jvm.h> +#include <java/net/InetAddress.h> +#include <java/net/UnknownHostException.h> +#include <java/lang/SecurityException.h> + +#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME) +#include <sys/utsname.h> +#endif + +#ifndef HAVE_GETHOSTNAME_DECL +extern "C" int gethostname (char *name, int namelen); +#endif + +jbyteArray +java::net::InetAddress::aton (jstring host) +{ + char *hostname; + char buf[100]; + int len = JvGetStringUTFLength(host); + if (len < 100) + hostname = buf; + else + hostname = (char*) _Jv_AllocBytesChecked (len+1); + JvGetStringUTFRegion (host, 0, host->length(), hostname); + buf[len] = '\0'; + char* bytes = NULL; + int blen = 0; +#ifdef HAVE_INET_ATON + struct in_addr laddr; + if (inet_aton (hostname, &laddr)) + { + bytes = (char*) &laddr; + len = 4; + } +#elif defined(HAVE_INET_ADDR) + in_addr_t laddr = inet_addr (hostname); + if (laddr != (in_addr_t)(-1)) + { + bytes = (char*) &laddr; + len = 4; + } +#endif +#ifdef HAVE_INET_PTON + char inet6_addr[16]; + if (len == 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0) + { + bytes = inet6_addr; + len = 16; + } +#endif + if (blen == 0) + return NULL; + jbyteArray result = JvNewByteArray (len); + memcpy (elements (result), bytes, blen); + return result; +} + + +JArray<java::net::InetAddress*> * +java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, + jboolean all) +{ + struct hostent *hptr = NULL; +#if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R) + struct hostent hent_r; + char fixed_buffer[200]; + char *buffer_r = fixed_buffer; + int size_r = sizeof (fixed_buffer); +#endif + + if (host != NULL) + { + char *hostname; + char buf[100]; + int len = JvGetStringUTFLength(host); + if (len < 100) + hostname = buf; + else + hostname = (char*) _Jv_AllocBytesChecked (len+1); + JvGetStringUTFRegion (host, 0, host->length(), hostname); + buf[len] = '\0'; +#ifdef HAVE_GETHOSTBYNAME_R + int herr = ERANGE; + while (hptr == NULL && herr == ERANGE) + { + int ok; +#ifdef GETHOSTBYNAME_R_RETURNS_INT + ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r, + &hptr, &herr); +#else + hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr); + ok = hptr != NULL; +#endif /* GETHOSTNAME_R_RETURNS_INT */ + if (! ok && herr == ERANGE) + { + size_r *= 2; + buffer_r = (char *) _Jv_AllocBytesChecked (size_r); + } + } +#else + // FIXME: this is insufficient if some other piece of code calls + // this gethostbyname. + JvSynchronize sync (java::net::InetAddress::localhostAddress); + hptr = gethostbyname (hostname); +#endif /* HAVE_GETHOSTBYNAME_R */ + } + else + { + jbyteArray bytes = iaddr->address; + char *chars = (char*) elements (bytes); + int len = bytes->length; + int type; + char *val; + if (len == 4) + { + val = chars; + type = AF_INET; + } +#ifdef HAVE_INET6 + else if (len == 16) + { + val = (char *) &chars; + type = AF_INET16; + } +#endif /* HAVE_INET6 */ + else + JvFail ("unrecognized size"); + +#ifdef HAVE_GETHOSTBYADDR_R + int herr = ERANGE; + while (hptr == NULL && herr == ERANGE) + { + int ok; +#ifdef GETHOSTBYADDR_R_RETURNS_INT + ok = ! gethostbyaddr_r (val, len, type, &hent_r, + buffer_r, size_r, &hptr, &herr); +#else + hptr = gethostbyaddr_r (val, len, type, &hent_r, + buffer_r, size_r, &herr); + ok = hptr != NULL; +#endif /* GETHOSTBYADDR_R_RETURNS_INT */ + if (! ok && herr == ERANGE) + { + size_r *= 2; + buffer_r = (char *) _Jv_AllocBytesChecked (size_r); + } + } +#else /* HAVE_GETHOSTBYADDR_R */ + // FIXME: this is insufficient if some other piece of code calls + // this gethostbyaddr. + JvSynchronize sync (java::net::InetAddress::localhostAddress); + hptr = gethostbyaddr (val, len, type); +#endif /* HAVE_GETHOSTBYADDR_R */ + } + if (hptr != NULL) + { + host = JvNewStringUTF (hptr->h_name); + java::lang::SecurityException *ex = checkConnect (host); + if (ex != NULL) + { + if (iaddr == NULL || iaddr->address == NULL) + JvThrow (ex); + hptr = NULL; + } + } + if (hptr == NULL) + { + if (iaddr != NULL && iaddr->address != NULL) + { + iaddr->hostname = iaddr->getHostAddress(); + return NULL; + } + else + JvThrow (new java::net::UnknownHostException(host)); + } + int count; + if (all) + { + char** ptr = hptr->h_addr_list; + count = 0; + while (*ptr++) count++; + } + else + count = 1; + JArray<java::net::InetAddress*> *result; + java::net::InetAddress** iaddrs; + if (all) + { + result = java::net::InetAddress::allocArray (count); + iaddrs = elements (result); + } + else + { + result = NULL; + iaddrs = &iaddr; + } + + for (int i = 0; i < count; i++) + { + if (iaddrs[i] == NULL) + iaddrs[i] = new java::net::InetAddress (NULL, NULL); + if (i == 0) + iaddrs[0]->hostname = host; + if (iaddrs[i]->address == NULL) + { + char *bytes = hptr->h_addr_list[i]; + iaddr->address = JvNewByteArray (hptr->h_length); + memcpy (elements (iaddr->address), bytes, hptr->h_length); + } + } + return result; +} + +jstring +java::net::InetAddress::getLocalHostname () +{ + char *chars; +#ifdef HAVE_GETHOSTNAME + char buffer[MAXHOSTNAMELEN]; + if (gethostname (buffer, MAXHOSTNAMELEN)) + return NULL; + chars = buffer; +#elif HAVE_UNAME + struct utsname stuff; + if (uname (&stuff) != 0) + return NULL: + chars = stuff.nodename; +#else + return NULL; +#endif + // It is admittedly non-optimal to convert the hostname to Unicode + // only to convert it back in getByName, but simplicity wins. Note + // that unless there is a SecurityManager, we only get called once + // anyway, thanks to the InetAddress.localhost cache. + return JvNewStringUTF (chars); +} diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc new file mode 100644 index 0000000..076ee71 --- /dev/null +++ b/libjava/java/net/natPlainSocketImpl.cc @@ -0,0 +1,177 @@ +/* Copyright (C) 1998, 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include <cni.h> +#include <java/io/IOException.h> +#include <java/io/FileDescriptor.h> +#include <java/net/PlainSocketImpl.h> +#include <java/net/InetAddress.h> + +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + +union SockAddr +{ + struct sockaddr_in address; +#ifdef HAVE_INET6 + struct sockaddr_in6 address6; +#endif +}; + +void +java::net::PlainSocketImpl::create (jboolean stream) +{ + int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); + if (sock < 0) + { + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.create: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); + } + fnum = sock; + fd = new java::io::FileDescriptor (sock); +} + +void +java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport) +{ + union SockAddr u; + jbyteArray haddress = host->address; + jbyte *bytes = elements (haddress); + int len = haddress->length; + struct sockaddr *ptr = (struct sockaddr *) &u.address; + if (len == 4) + { + u.address.sin_family = AF_INET; + memcpy (&u.address.sin_addr, bytes, len); + len = sizeof (struct sockaddr_in); + u.address.sin_port = htons (lport); + } +#ifdef HAVE_INET6 + else if (len == 16) + { + u.address6.sin6_family = AF_INET6; + memcpy (&u.address6.sin6_addr, bytes, len); + len = sizeof (struct sockaddr_in6); + u.address6.sin6_port = htons (lport); + } +#endif + else + goto error; + if (::bind (fnum, ptr, len) == 0) + { + address = host; + localport = lport; + return; + } + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.bind: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); +} + +void +java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport) +{ + union SockAddr u; + jbyteArray haddress = host->address; + jbyte *bytes = elements (haddress); + int len = haddress->length; + struct sockaddr *ptr = (struct sockaddr *) &u.address; + if (len == 4) + { + u.address.sin_family = AF_INET; + memcpy (&u.address.sin_addr, bytes, len); + len = sizeof (struct sockaddr_in); + u.address.sin_port = htons (rport); + } +#ifdef HAVE_INET6 + else if (len == 16) + { + u.address6.sin6_family = AF_INET6; + memcpy (&u.address6.sin6_addr, bytes, len); + len = sizeof (struct sockaddr_in6); + u.address6.sin6_port = htons (rport); + } +#endif + else + goto error; + if (::connect (fnum, ptr, len) == 0) + { + address = host; + port = rport; + return; + } + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.connect: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); +} + +void +java::net::PlainSocketImpl::listen (jint backlog) +{ + if (::listen (fnum, backlog) != 0) + { + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.listen: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); + } +} + +void +java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s) +{ + union SockAddr u; + socklen_t addrlen = sizeof(u); + int new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen); + if (new_socket < 0) + goto error; + jbyteArray raddr; + jint rport; + if (u.address.sin_family == AF_INET) + { + raddr = JvNewByteArray (4); + memcpy (elements (raddr), &u.address.sin_addr, 4); + rport = ntohs (u.address.sin_port); + } +#ifdef HAVE_INET6 + { + raddr = JvNewByteArray (16); + memcpy (elements (raddr), &u.address6.sin6_addr, 16); + rport = ntohs (u.address6.sin6_port); + } +#endif + else + goto error; + s->fnum = new_socket; + s->localport = localport; + s->address = new InetAddress (raddr, NULL); + s->port = rport; + s->fd = new java::io::FileDescriptor (new_socket); + return; + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.accept: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); +} |