summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/net
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/net
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/net')
-rw-r--r--libjava/classpath/java/net/Authenticator.java313
-rw-r--r--libjava/classpath/java/net/BindException.java74
-rw-r--r--libjava/classpath/java/net/ConnectException.java75
-rw-r--r--libjava/classpath/java/net/ContentHandler.java126
-rw-r--r--libjava/classpath/java/net/ContentHandlerFactory.java65
-rw-r--r--libjava/classpath/java/net/DatagramPacket.java391
-rw-r--r--libjava/classpath/java/net/DatagramSocket.java968
-rw-r--r--libjava/classpath/java/net/DatagramSocketImpl.java296
-rw-r--r--libjava/classpath/java/net/DatagramSocketImplFactory.java60
-rw-r--r--libjava/classpath/java/net/FileNameMap.java65
-rw-r--r--libjava/classpath/java/net/HttpURLConnection.java589
-rw-r--r--libjava/classpath/java/net/Inet4Address.java273
-rw-r--r--libjava/classpath/java/net/Inet6Address.java429
-rw-r--r--libjava/classpath/java/net/InetAddress.java655
-rw-r--r--libjava/classpath/java/net/InetSocketAddress.java261
-rw-r--r--libjava/classpath/java/net/JarURLConnection.java229
-rw-r--r--libjava/classpath/java/net/MalformedURLException.java74
-rw-r--r--libjava/classpath/java/net/MimeTypeMapper.java346
-rw-r--r--libjava/classpath/java/net/MulticastSocket.java518
-rw-r--r--libjava/classpath/java/net/NetPermission.java90
-rw-r--r--libjava/classpath/java/net/NetworkInterface.java316
-rw-r--r--libjava/classpath/java/net/NoRouteToHostException.java74
-rw-r--r--libjava/classpath/java/net/PasswordAuthentication.java92
-rw-r--r--libjava/classpath/java/net/PortUnreachableException.java72
-rw-r--r--libjava/classpath/java/net/ProtocolException.java75
-rw-r--r--libjava/classpath/java/net/Proxy.java139
-rw-r--r--libjava/classpath/java/net/ProxySelector.java117
-rw-r--r--libjava/classpath/java/net/ResolverCache.java269
-rw-r--r--libjava/classpath/java/net/STATUS48
-rw-r--r--libjava/classpath/java/net/ServerSocket.java627
-rw-r--r--libjava/classpath/java/net/Socket.java1288
-rw-r--r--libjava/classpath/java/net/SocketAddress.java63
-rw-r--r--libjava/classpath/java/net/SocketException.java75
-rw-r--r--libjava/classpath/java/net/SocketImpl.java321
-rw-r--r--libjava/classpath/java/net/SocketImplFactory.java59
-rw-r--r--libjava/classpath/java/net/SocketOptions.java166
-rw-r--r--libjava/classpath/java/net/SocketPermission.java636
-rw-r--r--libjava/classpath/java/net/SocketTimeoutException.java73
-rw-r--r--libjava/classpath/java/net/TODO24
-rw-r--r--libjava/classpath/java/net/URI.java1450
-rw-r--r--libjava/classpath/java/net/URISyntaxException.java144
-rw-r--r--libjava/classpath/java/net/URL.java1010
-rw-r--r--libjava/classpath/java/net/URLClassLoader.java860
-rw-r--r--libjava/classpath/java/net/URLConnection.java1150
-rw-r--r--libjava/classpath/java/net/URLDecoder.java182
-rw-r--r--libjava/classpath/java/net/URLEncoder.java186
-rw-r--r--libjava/classpath/java/net/URLStreamHandler.java541
-rw-r--r--libjava/classpath/java/net/URLStreamHandlerFactory.java65
-rw-r--r--libjava/classpath/java/net/UnknownHostException.java77
-rw-r--r--libjava/classpath/java/net/UnknownServiceException.java76
-rw-r--r--libjava/classpath/java/net/package.html46
51 files changed, 16218 insertions, 0 deletions
diff --git a/libjava/classpath/java/net/Authenticator.java b/libjava/classpath/java/net/Authenticator.java
new file mode 100644
index 000000000..229e140cc
--- /dev/null
+++ b/libjava/classpath/java/net/Authenticator.java
@@ -0,0 +1,313 @@
+/* Authenticator.java -- Abstract class for obtaining authentication info
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This abstract class provides a model for obtaining authentication
+ * information (in the form of a username and password) required by
+ * some network operations (such as hitting a password protected
+ * web site).
+ * <p>
+ * To make use of this feature, a programmer must create a subclass
+ * that knows how to obtain the necessary info. An example
+ * would be a class that popped up a dialog box to prompt the user.
+ * After creating an instance of that subclass, the static
+ * <code>setDefault</code> method of this class is called to set up
+ * that instance as the object to use on subsequent calls to obtain
+ * authorization.
+ *
+ * @since 1.2
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status Believed to be JDK 1.4 complete
+ */
+public abstract class Authenticator
+{
+ /*
+ * Class Variables
+ */
+
+ /**
+ * This is the default Authenticator object to use for password requests
+ */
+ private static Authenticator defaultAuthenticator;
+
+ /*
+ * Instance Variables
+ */
+
+ /**
+ * The hostname of the site requesting authentication
+ */
+ private String host;
+
+ /**
+ * InternetAddress of the site requesting authentication
+ */
+ private InetAddress addr;
+
+ /**
+ * The port number of the site requesting authentication
+ */
+ private int port;
+
+ /**
+ * The protocol name of the site requesting authentication
+ */
+ private String protocol;
+
+ /**
+ * The prompt to display to the user when requesting authentication info
+ */
+ private String prompt;
+
+ /**
+ * The authentication scheme in use
+ */
+ private String scheme;
+
+ /*
+ * Class Methods
+ */
+
+ /**
+ * This method sets the default <code>Authenticator</code> object (an
+ * instance of a subclass of <code>Authenticator</code>) to use when
+ * prompting the user for
+ * information. Note that this method checks to see if the caller is
+ * allowed to set this value (the "setDefaultAuthenticator" permission)
+ * and throws a <code>SecurityException</code> if it is not.
+ *
+ * @param defAuth The new default <code>Authenticator</code> object to use
+ *
+ * @exception SecurityException If the caller does not have permission
+ * to perform this operation
+ */
+ public static void setDefault(Authenticator defAuth)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new NetPermission("setDefaultAuthenticator"));
+
+ defaultAuthenticator = defAuth;
+ }
+
+ /**
+ * This method is called whenever a username and password for a given
+ * network operation is required. First, a security check is made to see
+ * if the caller has the "requestPasswordAuthentication"
+ * permission. If not, the method thows an exception. If there is no
+ * default <code>Authenticator</code> object, the method then returns
+ * <code>null</code>. Otherwise, the default authenticators's instance
+ * variables are initialized and it's <code>getPasswordAuthentication</code>
+ * method is called to get the actual authentication information to return.
+ *
+ * @param addr The address requesting authentication
+ * @param port The port requesting authentication
+ * @param protocol The protocol requesting authentication
+ * @param prompt The prompt to display to the user when requesting
+ * authentication info
+ * @param scheme The authentication scheme in use
+ *
+ * @return A <code>PasswordAuthentication</code> object with the user's
+ * authentication info.
+ *
+ * @exception SecurityException If the caller does not have permission to
+ * perform this operation
+ */
+ public static PasswordAuthentication requestPasswordAuthentication(InetAddress addr,
+ int port,
+ String protocol,
+ String prompt,
+ String scheme)
+ throws SecurityException
+ {
+ return requestPasswordAuthentication(null, addr, port, protocol, prompt,
+ scheme);
+ }
+
+ /**
+ * This method is called whenever a username and password for a given
+ * network operation is required. First, a security check is made to see
+ * if the caller has the "requestPasswordAuthentication"
+ * permission. If not, the method thows an exception. If there is no
+ * default <code>Authenticator</code> object, the method then returns
+ * <code>null</code>. Otherwise, the default authenticators's instance
+ * variables are initialized and it's <code>getPasswordAuthentication</code>
+ * method is called to get the actual authentication information to return.
+ * This method is the preferred one as it can be used with hostname
+ * when addr is unknown.
+ *
+ * @param host The hostname requesting authentication
+ * @param addr The address requesting authentication
+ * @param port The port requesting authentication
+ * @param protocol The protocol requesting authentication
+ * @param prompt The prompt to display to the user when requesting
+ * authentication info
+ * @param scheme The authentication scheme in use
+ *
+ * @return A <code>PasswordAuthentication</code> object with the user's
+ * authentication info.
+ *
+ * @exception SecurityException If the caller does not have permission to
+ * perform this operation
+ *
+ * @since 1.4
+ */
+ public static PasswordAuthentication requestPasswordAuthentication(String host,
+ InetAddress addr,
+ int port,
+ String protocol,
+ String prompt,
+ String scheme)
+ throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new NetPermission("requestPasswordAuthentication"));
+
+ if (defaultAuthenticator == null)
+ return null;
+
+ defaultAuthenticator.host = host;
+ defaultAuthenticator.addr = addr;
+ defaultAuthenticator.port = port;
+ defaultAuthenticator.protocol = protocol;
+ defaultAuthenticator.prompt = prompt;
+ defaultAuthenticator.scheme = scheme;
+
+ return defaultAuthenticator.getPasswordAuthentication();
+ }
+
+ /*
+ * Constructors
+ */
+
+ /**
+ * Default, no-argument constructor for subclasses to call.
+ */
+ public Authenticator()
+ {
+ }
+
+ /*
+ * Instance Methods
+ */
+
+ /**
+ * This method returns the address of the site that is requesting
+ * authentication.
+ *
+ * @return The requesting site's address
+ */
+ protected final InetAddress getRequestingSite()
+ {
+ return addr;
+ }
+
+ /**
+ * Returns the hostname of the host or proxy requesting authorization,
+ * or <code>null</code> if not available.
+ *
+ * @return The name of the host requesting authentication, or
+ * <code>null</code> if it is not available.
+ *
+ * @since 1.4
+ */
+ protected final String getRequestingHost()
+ {
+ return host;
+ }
+
+ /**
+ * This method returns the port of the site that is requesting
+ * authentication.
+ *
+ * @return The requesting port
+ */
+ protected final int getRequestingPort()
+ {
+ return port;
+ }
+
+ /**
+ * This method returns the requesting protocol of the operation that is
+ * requesting authentication
+ *
+ * @return The requesting protocol
+ */
+ protected final String getRequestingProtocol()
+ {
+ return protocol;
+ }
+
+ /**
+ * Returns the prompt that should be used when requesting authentication
+ * information from the user
+ *
+ * @return The user prompt
+ */
+ protected final String getRequestingPrompt()
+ {
+ return prompt;
+ }
+
+ /**
+ * This method returns the authentication scheme in use
+ *
+ * @return The authentication scheme
+ */
+ protected final String getRequestingScheme()
+ {
+ return scheme;
+ }
+
+ /**
+ * This method is called whenever a request for authentication is made. It
+ * can call the other getXXX methods to determine the information relevant
+ * to this request. Subclasses should override this method, which returns
+ * <code>null</code> by default.
+ *
+ * @return The <code>PasswordAuthentication</code> information
+ */
+ protected PasswordAuthentication getPasswordAuthentication()
+ {
+ return null;
+ }
+} // class Authenticator
diff --git a/libjava/classpath/java/net/BindException.java b/libjava/classpath/java/net/BindException.java
new file mode 100644
index 000000000..cfb509a70
--- /dev/null
+++ b/libjava/classpath/java/net/BindException.java
@@ -0,0 +1,74 @@
+/* BindException.java -- An exception occurred while binding to a socket
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that an error occurred while attempting to bind
+ * socket to a particular port.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class BindException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5945005768251722951L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public BindException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * text from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public BindException(String message)
+ {
+ super(message);
+ }
+} // class BindException
diff --git a/libjava/classpath/java/net/ConnectException.java b/libjava/classpath/java/net/ConnectException.java
new file mode 100644
index 000000000..c115d2fe0
--- /dev/null
+++ b/libjava/classpath/java/net/ConnectException.java
@@ -0,0 +1,75 @@
+/* ConnectException.java -- An exception occurred while connecting to a host
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that an error occurred while attempting to
+ * connect to a remote host. Often this indicates that the remote host
+ * refused the connection (ie, is not listening on the target socket).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ConnectException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 3831404271622369215L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public ConnectException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * text from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public ConnectException(String message)
+ {
+ super(message);
+ }
+} // class ConnectException
diff --git a/libjava/classpath/java/net/ContentHandler.java b/libjava/classpath/java/net/ContentHandler.java
new file mode 100644
index 000000000..fed8f3de4
--- /dev/null
+++ b/libjava/classpath/java/net/ContentHandler.java
@@ -0,0 +1,126 @@
+/* ContentHandler.java -- Abstract class for handling content from URL's
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+/**
+ * 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.
+ */
+
+/**
+ * This is an abstract class that is the superclass for classes that read
+ * objects from URL's. Calling the <code>getContent()</code> method in the
+ * <code>URL</code> class or the <code>URLConnection</code> class will cause
+ * an instance of a subclass of <code>ContentHandler</code> to be created for
+ * the MIME type of the object being downloaded from the URL. Thus, this
+ * class is seldom needed by applications/applets directly, but only
+ * indirectly through methods in other classes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class ContentHandler
+{
+ /*
+ * Constructors
+ */
+
+ /**
+ * Default, no-argument constructor.
+ */
+ public ContentHandler()
+ {
+ }
+
+ /*
+ * Instance Methods
+ */
+
+ /**
+ * This method reads from the <code>InputStream</code> of the passed in URL
+ * connection and uses the data downloaded to create an <code>Object</code>
+ * represening the content. For example, if the URL is pointing to a GIF
+ * file, this method might return an <code>Image</code> object. This method
+ * must be implemented by subclasses.
+ *
+ * @param urlc A <code>URLConnection</code> object to read data from.
+ *
+ * @return An object representing the data read
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract Object getContent(URLConnection urlc)
+ throws IOException;
+
+ /**
+ * This method reads from the <code>InputStream</code> of the passed in URL
+ * connection and uses the data downloaded to create an <code>Object</code>
+ * represening the content. For example, if the URL is pointing to a GIF
+ * file, this method might return an <code>Image</code> object. This method
+ * must be implemented by subclasses. This method uses the list of
+ * supplied classes as candidate types. If the data read doesn't match
+ * any of the supplied type, <code>null</code> is returned.
+ *
+ * @param urlc A <code>URLConnection</code> object to read data from.
+ * @param classes An array of types of objects that are candidate types
+ * for the data to be read.
+ *
+ * @return An object representing the data read, or <code>null</code>
+ * if the data does not match any of the candidate types.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.3
+ */
+ public Object getContent(URLConnection urlc, Class[] classes)
+ throws IOException
+ {
+ Object obj = getContent(urlc);
+
+ for (int i = 0; i < classes.length; i++)
+ {
+ if (classes[i].isInstance(obj))
+ return obj;
+ }
+
+ return null;
+ }
+} // class ContentHandler
diff --git a/libjava/classpath/java/net/ContentHandlerFactory.java b/libjava/classpath/java/net/ContentHandlerFactory.java
new file mode 100644
index 000000000..51a92cf15
--- /dev/null
+++ b/libjava/classpath/java/net/ContentHandlerFactory.java
@@ -0,0 +1,65 @@
+/* ContentHandlerFactory.java -- Interface for creating content handlers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * 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.
+ */
+/**
+ * This interface maps MIME types to <code>ContentHandler</code> objects.
+ * It consists of one method that, when passed a MIME type, returns a
+ * handler for that type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface ContentHandlerFactory
+{
+ /**
+ * This method is passed a MIME type as a string and is responsible for
+ * returning the appropriate <code>ContentHandler</code> object.
+ *
+ * @param mimeType The MIME type to map to a <code>ContentHandler</code>
+ *
+ * @return The <code>ContentHandler</code> for the passed in MIME type
+ */
+ ContentHandler createContentHandler(String mimeType);
+} // interface ContentHandlerFactory
diff --git a/libjava/classpath/java/net/DatagramPacket.java b/libjava/classpath/java/net/DatagramPacket.java
new file mode 100644
index 000000000..e642f889c
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramPacket.java
@@ -0,0 +1,391 @@
+/* DatagramPacket.java -- Class to model a packet to be sent via UDP
+ Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * This class models a packet of data that is to be sent across the network
+ * using a connectionless protocol such as UDP. It contains the data
+ * to be send, as well as the destination address and port. Note that
+ * datagram packets can arrive in any order and are not guaranteed to be
+ * delivered at all.
+ * <p>
+ * This class can also be used for receiving data from the network.
+ * <p>
+ * Note that for all method below where the buffer length passed by the
+ * caller cannot exceed the actually length of the byte array passed as
+ * the buffer, if this condition is not true, then the method silently
+ * reduces the length value to maximum allowable value.
+ *
+ * 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.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aarom M. Renn (arenn@urbanophile.com) (Documentation comments)
+ * @date April 28, 1999.
+ */
+public final class DatagramPacket
+{
+ /**
+ * The data buffer to send
+ */
+ private byte[] buffer;
+
+ /**
+ * This is the offset into the buffer to start sending from or receiving to.
+ */
+ private int offset;
+
+ /**
+ * The length of the data buffer to send.
+ */
+ int length;
+
+ /**
+ * The maximal length of the buffer.
+ */
+ int maxlen;
+
+ /**
+ * The address to which the packet should be sent or from which it
+ * was received.
+ */
+ private InetAddress address;
+
+ /**
+ * The port to which the packet should be sent or from which it was
+ * was received.
+ */
+ private int port;
+
+ /**
+ * This method initializes a new instance of <code>DatagramPacket</code>
+ * which has the specified buffer, offset, and length.
+ *
+ * @param buf The buffer for holding the incoming datagram.
+ * @param offset The offset into the buffer to start writing.
+ * @param length The maximum number of bytes to read.
+ *
+ * @since 1.2
+ */
+ public DatagramPacket(byte[] buf, int offset, int length)
+ {
+ setData(buf, offset, length);
+ address = null;
+ port = -1;
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * receiving packets from the network.
+ *
+ * @param buf A buffer for storing the returned packet data
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ */
+ public DatagramPacket(byte[] buf, int length)
+ {
+ this(buf, 0, length);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param offset The offset into the buffer to start writing from.
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The address to send to
+ * @param port The port to send to
+ *
+ * @since 1.2
+ */
+ public DatagramPacket(byte[] buf, int offset, int length,
+ InetAddress address, int port)
+ {
+ setData(buf, offset, length);
+ setAddress(address);
+ setPort(port);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The address to send to
+ * @param port The port to send to
+ */
+ public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
+ {
+ this(buf, 0, length, address, port);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param offset The offset into the buffer to start writing from.
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The socket address to send to
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public DatagramPacket(byte[] buf, int offset, int length,
+ SocketAddress address) throws SocketException
+ {
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ setData(buf, offset, length);
+ setAddress(tmp.getAddress());
+ setPort(tmp.getPort());
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The socket address to send to
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public DatagramPacket(byte[] buf, int length, SocketAddress address)
+ throws SocketException
+ {
+ this(buf, 0, length, address);
+ }
+
+ /**
+ * Returns the address that this packet is being sent to or, if it was used
+ * to receive a packet, the address that is was received from. If the
+ * constructor that doesn not take an address was used to create this object
+ * and no packet was actually read into this object, then this method
+ * returns <code>null</code>.
+ *
+ * @return The address for this packet.
+ */
+ public synchronized InetAddress getAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the port number this packet is being sent to or, if it was used
+ * to receive a packet, the port that it was received from. If the
+ * constructor that doesn not take an address was used to create this object
+ * and no packet was actually read into this object, then this method
+ * will return 0.
+ *
+ * @return The port number for this packet
+ */
+ public synchronized int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the data buffer for this packet
+ *
+ * @return This packet's data buffer
+ */
+ public synchronized byte[] getData()
+ {
+ return buffer;
+ }
+
+ /**
+ * This method returns the current offset value into the data buffer
+ * where data will be sent from.
+ *
+ * @return The buffer offset.
+ *
+ * @since 1.2
+ */
+ public synchronized int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the length of the data in the buffer
+ *
+ * @return The length of the data
+ */
+ public synchronized int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * This sets the address to which the data packet will be transmitted.
+ *
+ * @param address The destination address
+ *
+ * @since 1.1
+ */
+ public synchronized void setAddress(InetAddress address)
+ {
+ this.address = address;
+ }
+
+ /**
+ * This sets the port to which the data packet will be transmitted.
+ *
+ * @param port The destination port
+ *
+ * @since 1.1
+ */
+ public synchronized void setPort(int port)
+ {
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Invalid port: " + port);
+
+ this.port = port;
+ }
+
+ /**
+ * Sets the address of the remote host this package will be sent
+ *
+ * @param address The socket address of the remove host
+ *
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public void setSocketAddress(SocketAddress address)
+ throws IllegalArgumentException
+ {
+ if (address == null)
+ throw new IllegalArgumentException("address may not be null");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ this.address = tmp.getAddress();
+ this.port = tmp.getPort();
+ }
+
+ /**
+ * Gets the socket address of the host this packet
+ * will be sent to/is coming from
+ *
+ * @return The socket address of the remote host
+ *
+ * @since 1.4
+ */
+ public SocketAddress getSocketAddress()
+ {
+ return new InetSocketAddress(address, port);
+ }
+
+ /**
+ * Sets the data buffer for this packet.
+ *
+ * @param buf The new buffer for this packet
+ *
+ * @exception NullPointerException If the argument is null
+ *
+ * @since 1.1
+ */
+ public void setData(byte[] buf)
+ {
+ setData(buf, 0, buf.length);
+ }
+
+ /**
+ * This method sets the data buffer for the packet.
+ *
+ * @param buf The byte array containing the data for this packet.
+ * @param offset The offset into the buffer to start reading data from.
+ * @param length The number of bytes of data in the buffer.
+ *
+ * @exception NullPointerException If the argument is null
+ *
+ * @since 1.2
+ */
+ public synchronized void setData(byte[] buf, int offset, int length)
+ {
+ // This form of setData must be used if offset is to be changed.
+ if (buf == null)
+ throw new NullPointerException("Null buffer");
+ if (offset < 0)
+ throw new IllegalArgumentException("Invalid offset: " + offset);
+
+ buffer = buf;
+ this.offset = offset;
+ setLength(length);
+ }
+
+ /**
+ * Sets the length of the data in the buffer.
+ *
+ * @param length The new length. (Where len &lt;= buf.length)
+ *
+ * @exception IllegalArgumentException If the length is negative or
+ * if the length is greater than the packet's data buffer length
+ *
+ * @since 1.1
+ */
+ public synchronized void setLength(int length)
+ {
+ if (length < 0)
+ throw new IllegalArgumentException("Invalid length: " + length);
+ if (offset + length > buffer.length)
+ throw new IllegalArgumentException("Potential buffer overflow - offset: "
+ + offset + " length: " + length);
+
+ this.length = length;
+ this.maxlen = length;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocket.java b/libjava/classpath/java/net/DatagramSocket.java
new file mode 100644
index 000000000..6ca9c42fe
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocket.java
@@ -0,0 +1,968 @@
+/* DatagramSocket.java -- A class to model UDP sockets
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.classpath.SystemProperties;
+
+import gnu.java.net.PlainDatagramSocketImpl;
+import gnu.java.nio.DatagramChannelImpl;
+
+import java.io.IOException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+
+
+/**
+ * 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.
+ */
+/**
+ * This class models a connectionless datagram socket that sends
+ * individual packets of data across the network. In the TCP/IP world,
+ * this means UDP. Datagram packets do not have guaranteed delivery,
+ * or any guarantee about the order the data will be received on the
+ * remote host.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @date May 3, 1999.
+ */
+public class DatagramSocket
+{
+ /**
+ * This is the user DatagramSocketImplFactory for this class. If this
+ * variable is null, a default factory is used.
+ */
+ private static DatagramSocketImplFactory factory;
+
+ /**
+ * This is the implementation object used by this socket.
+ */
+ private DatagramSocketImpl impl;
+
+ /**
+ * True if socket implementation was created.
+ */
+ private boolean implCreated;
+
+ /**
+ * This is the address we are "connected" to
+ */
+ private InetAddress remoteAddress;
+
+ /**
+ * This is the port we are "connected" to
+ */
+ private int remotePort = -1;
+
+ /**
+ * True if socket is bound.
+ */
+ private boolean bound;
+
+ /**
+ * Creates a <code>DatagramSocket</code> from a specified
+ * <code>DatagramSocketImpl</code> instance
+ *
+ * @param impl The <code>DatagramSocketImpl</code> the socket will be
+ * created from
+ *
+ * @since 1.4
+ */
+ protected DatagramSocket(DatagramSocketImpl impl)
+ {
+ if (impl == null)
+ throw new NullPointerException("impl may not be null");
+
+ this.impl = impl;
+ this.remoteAddress = null;
+ this.remotePort = -1;
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * a random port and every address on the local machine.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception SecurityException If a security manager exists and
+ * its <code>checkListen</code> method doesn't allow the operation.
+ */
+ public DatagramSocket() throws SocketException
+ {
+ this(new InetSocketAddress(0));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified port and every address on the local machine.
+ *
+ * @param port The local port number to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * <code>checkListen</code> method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ */
+ public DatagramSocket(int port) throws SocketException
+ {
+ this(new InetSocketAddress(port));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified local port and address.
+ *
+ * @param port The local port number to bind to.
+ * @param addr The local address to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ */
+ public DatagramSocket(int port, InetAddress addr) throws SocketException
+ {
+ this(new InetSocketAddress(addr, port));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified local port and address.
+ *
+ * @param address The local address and port number to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * <code>checkListen</code> method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public DatagramSocket(SocketAddress address) throws SocketException
+ {
+ String propVal = SystemProperties.getProperty("impl.prefix");
+ if (propVal == null || propVal.equals(""))
+ {
+ if (factory != null)
+ impl = factory.createDatagramSocketImpl();
+ else
+ {
+ try
+ {
+ impl = new PlainDatagramSocketImpl();
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+ }
+ else
+ try
+ {
+ impl =
+ (DatagramSocketImpl) Class.forName("java.net." + propVal
+ + "DatagramSocketImpl")
+ .newInstance();
+ }
+ catch (Exception e)
+ {
+ System.err.println("Could not instantiate class: java.net."
+ + propVal + "DatagramSocketImpl");
+ try
+ {
+ impl = new PlainDatagramSocketImpl();
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
+ if (address != null)
+ bind(address);
+ }
+
+ // This needs to be accessible from java.net.MulticastSocket
+ DatagramSocketImpl getImpl() throws SocketException
+ {
+ try
+ {
+ if (! implCreated)
+ {
+ impl.create();
+ implCreated = true;
+ }
+
+ return impl;
+ }
+ catch (IOException e)
+ {
+ SocketException se = new SocketException();
+ se.initCause(e);
+ throw se;
+ }
+ }
+
+ /**
+ * Closes this datagram socket.
+ */
+ public void close()
+ {
+ if (isClosed())
+ return;
+
+ try
+ {
+ getImpl().close();
+ }
+ catch (SocketException e)
+ {
+ // Ignore this case, just close the socket in finally clause.
+ }
+ finally
+ {
+ remoteAddress = null;
+ remotePort = -1;
+ impl = null;
+ }
+
+ try
+ {
+ if (getChannel() != null)
+ getChannel().close();
+ }
+ catch (IOException e)
+ {
+ // Do nothing.
+ }
+ }
+
+ /**
+ * This method returns the remote address to which this socket is
+ * connected. If this socket is not connected, then this method will
+ * return <code>null</code>.
+ *
+ * @return The remote address.
+ *
+ * @since 1.2
+ */
+ public InetAddress getInetAddress()
+ {
+ return remoteAddress;
+ }
+
+ /**
+ * This method returns the remote port to which this socket is
+ * connected. If this socket is not connected, then this method will
+ * return -1.
+ *
+ * @return The remote port.
+ *
+ * @since 1.2
+ */
+ public int getPort()
+ {
+ return remotePort;
+ }
+
+ /**
+ * Returns the local address this datagram socket is bound to.
+ *
+ * @return The local address is the socket is bound or null
+ *
+ * @since 1.1
+ */
+ public InetAddress getLocalAddress()
+ {
+ if (! isBound())
+ return null;
+
+ InetAddress localAddr;
+
+ try
+ {
+ localAddr =
+ (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(localAddr.getHostAddress(), -1);
+ }
+ catch (SecurityException e)
+ {
+ localAddr = InetAddress.ANY_IF;
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return null;
+ }
+
+ return localAddr;
+ }
+
+ /**
+ * Returns the local port this socket is bound to.
+ *
+ * @return The local port number.
+ */
+ public int getLocalPort()
+ {
+ if (isClosed())
+ return -1;
+
+ try
+ {
+ return getImpl().getLocalPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return 0;
+ }
+ }
+
+ /**
+ * Returns the value of the socket's SO_TIMEOUT setting. If this method
+ * returns 0 then SO_TIMEOUT is disabled.
+ *
+ * @return The current timeout in milliseconds.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.1
+ */
+ public synchronized int getSoTimeout() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
+ * disable SO_TIMEOUT. Any other value is the number of milliseconds
+ * a socket read/write will block before timing out.
+ *
+ * @param timeout The new SO_TIMEOUT value in milliseconds.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.1
+ */
+ public synchronized void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("Invalid timeout: " + timeout);
+
+ getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_SNDBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The send buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.2
+ */
+ public int getSendBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_SNDBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new send buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If size is 0 or negative.
+ *
+ * @since 1.2
+ */
+ public void setSendBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size < 0)
+ throw new IllegalArgumentException("Buffer size is less than 0");
+
+ getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.2
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If size is 0 or negative.
+ *
+ * @since 1.2
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size < 0)
+ throw new IllegalArgumentException("Buffer size is less than 0");
+
+ getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
+ }
+
+ /**
+ * This method connects this socket to the specified address and port.
+ * When a datagram socket is connected, it will only send or receive
+ * packets to and from the host to which it is connected. A multicast
+ * socket that is connected may only send and not receive packets.
+ *
+ * @param address The address to connect this socket to.
+ * @param port The port to connect this socket to.
+ *
+ * @exception IllegalArgumentException If address or port are invalid.
+ * @exception SecurityException If the caller is not allowed to send
+ * datagrams to or receive from this address and port.
+ *
+ * @since 1.2
+ */
+ public void connect(InetAddress address, int port)
+ {
+ if (address == null)
+ throw new IllegalArgumentException("Connect address may not be null");
+
+ if ((port < 1) || (port > 65535))
+ throw new IllegalArgumentException("Port number is illegal: " + port);
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(address.getHostAddress(), port);
+
+ try
+ {
+ getImpl().connect(address, port);
+ remoteAddress = address;
+ remotePort = port;
+ }
+ catch (SocketException e)
+ {
+ // This means simply not connected or connect not implemented.
+ }
+ }
+
+ /**
+ * This method disconnects this socket from the address/port it was
+ * connected to. If the socket was not connected in the first place,
+ * this method does nothing.
+ *
+ * @since 1.2
+ */
+ public void disconnect()
+ {
+ if (! isConnected())
+ return;
+
+ try
+ {
+ getImpl().disconnect();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+ finally
+ {
+ remoteAddress = null;
+ remotePort = -1;
+ }
+ }
+
+ /**
+ * Reads a datagram packet from the socket. Note that this method
+ * will block until a packet is received from the network. On return,
+ * the passed in <code>DatagramPacket</code> is populated with the data
+ * received and all the other information about the packet.
+ *
+ * @param p A <code>DatagramPacket</code> for storing the data
+ *
+ * @exception IOException If an error occurs.
+ * @exception SocketTimeoutException If setSoTimeout was previously called
+ * and the timeout has expired.
+ * @exception PortUnreachableException If the socket is connected to a
+ * currently unreachable destination. Note, there is no guarantee that the
+ * exception will be thrown.
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode.
+ * @exception SecurityException If a security manager exists and its
+ * checkAccept method doesn't allow the receive.
+ */
+ public synchronized void receive(DatagramPacket p) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (remoteAddress != null && remoteAddress.isMulticastAddress())
+ throw new IOException
+ ("Socket connected to a multicast address my not receive");
+
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen);
+ getImpl().receive(p2);
+ p.length = p2.length;
+ if (p2.getAddress() != null)
+ p.setAddress(p2.getAddress());
+ if (p2.getPort() != -1)
+ p.setPort(p2.getPort());
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && isConnected())
+ s.checkAccept(p.getAddress().getHostAddress(), p.getPort());
+ }
+
+ /**
+ * Sends the specified packet. The host and port to which the packet
+ * are to be sent should be set inside the packet.
+ *
+ * @param p The datagram packet to send.
+ *
+ * @exception IOException If an error occurs.
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast or checkConnect method doesn't allow the send.
+ * @exception PortUnreachableException If the socket is connected to a
+ * currently unreachable destination. Note, there is no guarantee that the
+ * exception will be thrown.
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode.
+ */
+ public void send(DatagramPacket p) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && ! isConnected())
+ {
+ InetAddress addr = p.getAddress();
+ if (addr.isMulticastAddress())
+ s.checkMulticast(addr);
+ else
+ s.checkConnect(addr.getHostAddress(), p.getPort());
+ }
+
+ if (isConnected())
+ {
+ if (p.getAddress() != null
+ && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
+ throw new IllegalArgumentException
+ ("DatagramPacket address does not match remote address");
+ }
+
+ // FIXME: if this is a subclass of MulticastSocket,
+ // use getTimeToLive for TTL val.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ getImpl().send(p);
+ }
+
+ /**
+ * Binds the socket to the given socket address.
+ *
+ * @param address The socket address to bind to.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception SecurityException If a security manager exists and
+ * its checkListen method doesn't allow the operation.
+ * @exception IllegalArgumentException If address type is not supported.
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress address) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (address == null)
+ address = new InetSocketAddress(InetAddress.ANY_IF, 0);
+
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetAddress addr = ((InetSocketAddress) address).getAddress();
+ int port = ((InetSocketAddress) address).getPort();
+
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Invalid port: " + port);
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkListen(port);
+
+ if (addr == null)
+ addr = InetAddress.ANY_IF;
+
+ try
+ {
+ getImpl().bind(port, addr);
+ bound = true;
+ }
+ catch (SocketException exception)
+ {
+ getImpl().close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ getImpl().close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ getImpl().close();
+ throw error;
+ }
+ }
+
+ /**
+ * Checks if the datagram socket is closed.
+ *
+ * @return True if socket is closed, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ return impl == null;
+ }
+
+ /**
+ * Returns the datagram channel assoziated with this datagram socket.
+ *
+ * @return The associated <code>DatagramChannel</code> object or null
+ *
+ * @since 1.4
+ */
+ public DatagramChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Connects the datagram socket to a specified socket address.
+ *
+ * @param address The socket address to connect to.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If address type is not supported.
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress address) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ connect(tmp.getAddress(), tmp.getPort());
+ }
+
+ /**
+ * Returns the binding state of the socket.
+ *
+ * @return True if socket bound, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ return bound;
+ }
+
+ /**
+ * Returns the connection state of the socket.
+ *
+ * @return True if socket is connected, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isConnected()
+ {
+ return remoteAddress != null;
+ }
+
+ /**
+ * Returns the SocketAddress of the host this socket is conneted to
+ * or null if this socket is not connected.
+ *
+ * @return The socket address of the remote host if connected or null
+ *
+ * @since 1.4
+ */
+ public SocketAddress getRemoteSocketAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ return new InetSocketAddress(remoteAddress, remotePort);
+ }
+
+ /**
+ * Returns the local SocketAddress this socket is bound to.
+ *
+ * @return The local SocketAddress or null if the socket is not bound.
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (! isBound())
+ return null;
+
+ return new InetSocketAddress(getLocalAddress(), getLocalPort());
+ }
+
+ /**
+ * Enables/Disables SO_REUSEADDR.
+ *
+ * @param on Whether or not to have SO_REUSEADDR turned on.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
+ }
+
+ /**
+ * Checks if SO_REUSEADDR is enabled.
+ *
+ * @return True if SO_REUSEADDR is set on the socket, false otherwise.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Enables/Disables SO_BROADCAST
+ *
+ * @param enable True if SO_BROADCAST should be enabled, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setBroadcast(boolean enable) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
+ }
+
+ /**
+ * Checks if SO_BROADCAST is enabled
+ *
+ * @return Whether SO_BROADCAST is set
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getBroadcast() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the traffic class value
+ *
+ * @param tc The traffic class
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If tc value is illegal
+ *
+ * @see DatagramSocket#getTrafficClass()
+ *
+ * @since 1.4
+ */
+ public void setTrafficClass(int tc) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (tc < 0 || tc > 255)
+ throw new IllegalArgumentException();
+
+ getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
+ }
+
+ /**
+ * Returns the current traffic class
+ *
+ * @return The current traffic class.
+ *
+ * @see DatagramSocket#setTrafficClass(int tc)
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public int getTrafficClass() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.IP_TOS);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the datagram socket implementation factory for the application
+ *
+ * @param fac The factory to set
+ *
+ * @exception IOException If an error occurs
+ * @exception SocketException If the factory is already defined
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
+ throws IOException
+ {
+ if (factory != null)
+ throw new SocketException("DatagramSocketImplFactory already defined");
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
+ factory = fac;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocketImpl.java b/libjava/classpath/java/net/DatagramSocketImpl.java
new file mode 100644
index 000000000..4f51f9f93
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocketImpl.java
@@ -0,0 +1,296 @@
+/* DatagramSocketImpl.java -- Abstract class for UDP socket implementations
+ Copyright (C) 1998, 1999 2000, 2001,
+ 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+
+/**
+ * This abstract class models a datagram socket implementation. An
+ * actual implementation class would implement these methods, probably
+ * via redirecting them to native code.
+ * <p>
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * <p>
+ * Status: Believed complete and correct.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ */
+public abstract class DatagramSocketImpl implements SocketOptions
+{
+ /**
+ * The local port to which this socket is bound
+ */
+ protected int localPort;
+
+ /**
+ * The FileDescriptor object for this object.
+ */
+ protected FileDescriptor fd;
+
+ /**
+ * Default, no-argument constructor for subclasses to call.
+ */
+ public DatagramSocketImpl()
+ {
+ }
+
+ /**
+ * This method binds the socket to the specified local port and address.
+ *
+ * @param lport The port number to bind to
+ * @param laddr The address to bind to
+ *
+ * @exception SocketException If an error occurs
+ */
+ protected abstract void bind(int lport, InetAddress laddr)
+ throws SocketException;
+
+ /**
+ * This methods closes the socket
+ */
+ protected abstract void close();
+
+ /**
+ * Creates a new datagram socket.
+ *
+ * @exception SocketException If an error occurs
+ */
+ protected abstract void create() throws SocketException;
+
+ /**
+ * Takes a peek at the next packet received in order to retrieve the
+ * address of the sender
+ *
+ * @param i The <code>InetAddress</code> to fill in with the information
+ * about the sender if the next packet
+ *
+ * @return The port number of the sender of the packet
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract int peek(InetAddress i) throws IOException;
+
+ /**
+ * Takes a peek at the next packet received. This packet is not consumed.
+ * With the next peekData/receive operation this packet will be read again.
+ *
+ * @param p The <code>DatagramPacket</code> to fill in with the data sent.
+ *
+ * @return The port number of the sender of the packet.
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ *
+ * @since 1.4
+ */
+ protected abstract int peekData(DatagramPacket p) throws IOException;
+
+ /**
+ * Transmits the specified packet of data to the network. The destination
+ * host and port should be encoded in the packet.
+ *
+ * @param p The packet to send
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract void send(DatagramPacket p) throws IOException;
+
+ /**
+ * Receives a packet of data from the network Will block until a packet
+ * arrives. The packet info in populated into the passed in
+ * <code>DatagramPacket</code> object.
+ *
+ * @param p A place to store the incoming packet.
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract void receive(DatagramPacket p) throws IOException;
+
+ /**
+ * Connects the socket to a host specified by address and port.
+ *
+ * @param address The <code>InetAddress</code> of the host to connect to
+ * @param port The port number of the host to connect to
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected void connect(InetAddress address, int port)
+ throws SocketException
+ {
+ // This method has to be overwritten by real implementations
+ }
+
+ /**
+ * Disconnects the socket.
+ *
+ * @since 1.4
+ */
+ protected void disconnect()
+ {
+ // This method has to be overwritten by real implementations
+ }
+
+ /**
+ * Sets the Time to Live (TTL) setting on this socket to the specified
+ * value. <b>Use <code>setTimeToLive(int)</code></b> instead.
+ *
+ * @param ttl The new Time to Live value
+ *
+ * @exception IOException If an error occurs
+ * @deprecated
+ */
+ protected abstract void setTTL(byte ttl) throws IOException;
+
+ /**
+ * This method returns the current Time to Live (TTL) setting on this
+ * socket. <b>Use <code>getTimeToLive()</code></b> instead.
+ *
+ * @return the current time-to-live
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated // FIXME: when ?
+ */
+ protected abstract byte getTTL() throws IOException;
+
+ /**
+ * Sets the Time to Live (TTL) setting on this socket to the specified
+ * value.
+ *
+ * @param ttl The new Time to Live value
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void setTimeToLive(int ttl) throws IOException;
+
+ /**
+ * This method returns the current Time to Live (TTL) setting on this
+ * socket.
+ *
+ * @return the current time-to-live
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract int getTimeToLive() throws IOException;
+
+ /**
+ * Causes this socket to join the specified multicast group
+ *
+ * @param inetaddr The multicast address to join with
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void join(InetAddress inetaddr) throws IOException;
+
+ /**
+ * Causes the socket to leave the specified multicast group.
+ *
+ * @param inetaddr The multicast address to leave
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void leave(InetAddress inetaddr) throws IOException;
+
+ /**
+ * Causes this socket to join the specified multicast group on a specified
+ * device
+ *
+ * @param mcastaddr The address to leave
+ * @param netIf The specified network interface to join the group at
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void joinGroup(SocketAddress mcastaddr,
+ NetworkInterface netIf)
+ throws IOException;
+
+ /**
+ * Leaves a multicast group
+ *
+ * @param mcastaddr The address to join
+ * @param netIf The specified network interface to leave the group at
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void leaveGroup(SocketAddress mcastaddr,
+ NetworkInterface netIf)
+ throws IOException;
+
+ /**
+ * Returns the FileDescriptor for this socket
+ *
+ * @return the file descriptor associated with this socket
+ */
+ protected FileDescriptor getFileDescriptor()
+ {
+ return fd;
+ }
+
+ /**
+ * Returns the local port this socket is bound to
+ *
+ * @return the local port
+ */
+ protected int getLocalPort()
+ {
+ return localPort;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocketImplFactory.java b/libjava/classpath/java/net/DatagramSocketImplFactory.java
new file mode 100644
index 000000000..014651aa8
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocketImplFactory.java
@@ -0,0 +1,60 @@
+/* DatagramSocketImplFactory.java --
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/** Written using on-line Java Platform 1.4 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface defines one method which returns a
+ * <code>DatagramSocketImpl</code> object.
+ * This should not be needed by ordinary applications.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.3
+ */
+public interface DatagramSocketImplFactory
+{
+ /**
+ * This method returns an instance of the DatagramSocketImpl object
+ *
+ * @return A DatagramSocketImpl object
+ */
+ DatagramSocketImpl createDatagramSocketImpl();
+} // interface DatagramSocketImplFactory
diff --git a/libjava/classpath/java/net/FileNameMap.java b/libjava/classpath/java/net/FileNameMap.java
new file mode 100644
index 000000000..6f1d25a6a
--- /dev/null
+++ b/libjava/classpath/java/net/FileNameMap.java
@@ -0,0 +1,65 @@
+/* FileNameMap.java -- Maps filenames to MIME types
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * 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.
+ */
+/**
+ * This interface has one method which, when passed a filename, returns
+ * the MIME type associated with that filename.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ */
+public interface FileNameMap
+{
+ /**
+ * This method is passed a filename and is responsible for determining
+ * the appropriate MIME type for that file.
+ *
+ * @param filename The name of the file to generate a MIME type for.
+ *
+ * @return The MIME type for the filename passed in.
+ */
+ String getContentTypeFor(String filename);
+} // interface FileNameMap
diff --git a/libjava/classpath/java/net/HttpURLConnection.java b/libjava/classpath/java/net/HttpURLConnection.java
new file mode 100644
index 000000000..72dd67d91
--- /dev/null
+++ b/libjava/classpath/java/net/HttpURLConnection.java
@@ -0,0 +1,589 @@
+/* HttpURLConnection.java -- Subclass of communications links using
+ Hypertext Transfer Protocol.
+ Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.security.Permission;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * This class provides a common abstract implementation for those
+ * URL connection classes that will connect using the HTTP protocol.
+ * In addition to the functionality provided by the URLConnection
+ * class, it defines constants for HTTP return code values and
+ * methods for setting the HTTP request method and determining whether
+ * or not to follow redirects.
+ *
+ * @since 1.1
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class HttpURLConnection extends URLConnection
+{
+ /* HTTP Success Response Codes */
+
+ /**
+ * Indicates that the client may continue with its request. This value
+ * is specified as part of RFC 2068 but was not included in Sun's JDK, so
+ * beware of using this value
+ */
+ static final int HTTP_CONTINUE = 100;
+
+ /**
+ * Indicates the request succeeded.
+ */
+ public static final int HTTP_OK = 200;
+
+ /**
+ * The requested resource has been created.
+ */
+ public static final int HTTP_CREATED = 201;
+
+ /**
+ * The request has been accepted for processing but has not completed.
+ * There is no guarantee that the requested action will actually ever
+ * be completed succesfully, but everything is ok so far.
+ */
+ public static final int HTTP_ACCEPTED = 202;
+
+ /**
+ * The meta-information returned in the header is not the actual data
+ * from the original server, but may be from a local or other copy.
+ * Normally this still indicates a successful completion.
+ */
+ public static final int HTTP_NOT_AUTHORITATIVE = 203;
+
+ /**
+ * The server performed the request, but there is no data to send
+ * back. This indicates that the user's display should not be changed.
+ */
+ public static final int HTTP_NO_CONTENT = 204;
+
+ /**
+ * The server performed the request, but there is no data to sent back,
+ * however, the user's display should be "reset" to clear out any form
+ * fields entered.
+ */
+ public static final int HTTP_RESET = 205;
+
+ /**
+ * The server completed the partial GET request for the resource.
+ */
+ public static final int HTTP_PARTIAL = 206;
+
+ /* HTTP Redirection Response Codes */
+
+ /**
+ * There is a list of choices available for the requested resource.
+ */
+ public static final int HTTP_MULT_CHOICE = 300;
+
+ /**
+ * The resource has been permanently moved to a new location.
+ */
+ public static final int HTTP_MOVED_PERM = 301;
+
+ /**
+ * The resource requested has been temporarily moved to a new location.
+ */
+ public static final int HTTP_MOVED_TEMP = 302;
+
+ /**
+ * The response to the request issued is available at another location.
+ */
+ public static final int HTTP_SEE_OTHER = 303;
+
+ /**
+ * The document has not been modified since the criteria specified in
+ * a conditional GET.
+ */
+ public static final int HTTP_NOT_MODIFIED = 304;
+
+ /**
+ * The requested resource needs to be accessed through a proxy.
+ */
+ public static final int HTTP_USE_PROXY = 305;
+
+ /* HTTP Client Error Response Codes */
+
+ /**
+ * The request was misformed or could not be understood.
+ */
+ public static final int HTTP_BAD_REQUEST = 400;
+
+ /**
+ * The request made requires user authorization. Try again with
+ * a correct authentication header.
+ */
+ public static final int HTTP_UNAUTHORIZED = 401;
+
+ /**
+ * Code reserved for future use - I hope way in the future.
+ */
+ public static final int HTTP_PAYMENT_REQUIRED = 402;
+
+ /**
+ * There is no permission to access the requested resource.
+ */
+ public static final int HTTP_FORBIDDEN = 403;
+
+ /**
+ * The requested resource was not found.
+ */
+ public static final int HTTP_NOT_FOUND = 404;
+
+ /**
+ * The specified request method is not allowed for this resource.
+ */
+ public static final int HTTP_BAD_METHOD = 405;
+
+ /**
+ * Based on the input headers sent, the resource returned in response
+ * to the request would not be acceptable to the client.
+ */
+ public static final int HTTP_NOT_ACCEPTABLE = 406;
+
+ /**
+ * The client must authenticate with a proxy prior to attempting this
+ * request.
+ */
+ public static final int HTTP_PROXY_AUTH = 407;
+
+ /**
+ * The request timed out.
+ */
+ public static final int HTTP_CLIENT_TIMEOUT = 408;
+
+ /**
+ * There is a conflict between the current state of the resource and the
+ * requested action.
+ */
+ public static final int HTTP_CONFLICT = 409;
+
+ /**
+ * The requested resource is no longer available. This ususally indicates
+ * a permanent condition.
+ */
+ public static final int HTTP_GONE = 410;
+
+ /**
+ * A Content-Length header is required for this request, but was not
+ * supplied.
+ */
+ public static final int HTTP_LENGTH_REQUIRED = 411;
+
+ /**
+ * A client specified pre-condition was not met on the server.
+ */
+ public static final int HTTP_PRECON_FAILED = 412;
+
+ /**
+ * The request sent was too large for the server to handle.
+ */
+ public static final int HTTP_ENTITY_TOO_LARGE = 413;
+
+ /**
+ * The name of the resource specified was too long.
+ */
+ public static final int HTTP_REQ_TOO_LONG = 414;
+
+ /**
+ * The request is in a format not supported by the requested resource.
+ */
+ public static final int HTTP_UNSUPPORTED_TYPE = 415;
+
+ /* HTTP Server Error Response Codes */
+
+ /**
+ * This error code indicates that some sort of server error occurred.
+ *
+ * @deprecated
+ */
+ public static final int HTTP_SERVER_ERROR = 500;
+
+ /**
+ * The server encountered an unexpected error (such as a CGI script crash)
+ * that prevents the request from being fulfilled.
+ */
+ public static final int HTTP_INTERNAL_ERROR = 500;
+
+ /**
+ * The server does not support the requested functionality.
+ * @since 1.3
+ */
+ public static final int HTTP_NOT_IMPLEMENTED = 501;
+
+ /**
+ * The proxy encountered a bad response from the server it was proxy-ing for
+ */
+ public static final int HTTP_BAD_GATEWAY = 502;
+
+ /**
+ * The HTTP service is not availalble, such as because it is overloaded
+ * and does not want additional requests.
+ */
+ public static final int HTTP_UNAVAILABLE = 503;
+
+ /**
+ * The proxy timed out getting a reply from the remote server it was
+ * proxy-ing for.
+ */
+ public static final int HTTP_GATEWAY_TIMEOUT = 504;
+
+ /**
+ * This server does not support the protocol version requested.
+ */
+ public static final int HTTP_VERSION = 505;
+
+ // Non-HTTP response static variables
+
+ /**
+ * Flag to indicate whether or not redirects should be automatically
+ * followed by default.
+ */
+ private static boolean followRedirects = true;
+
+ /**
+ * This is a list of valid request methods, separated by "|" characters.
+ */
+ private static final String valid_methods =
+ "|GET|POST|HEAD|OPTIONS|PUT|DELETE|TRACE|";
+
+ // Instance Variables
+
+ /**
+ * The requested method in use for this connection. Default is GET.
+ */
+ protected String method = "GET";
+
+ /**
+ * The response code received from the server
+ */
+ protected int responseCode = -1;
+
+ /**
+ * The response message string received from the server.
+ */
+ protected String responseMessage;
+
+ /**
+ * If this instance should follow redirect requests.
+ */
+ protected boolean instanceFollowRedirects = followRedirects;
+
+ /**
+ * Whether we already got a valid response code for this connection.
+ * Used by <code>getResponseCode()</code> and
+ * <code>getResponseMessage()</code>.
+ */
+ private boolean gotResponseVals;
+
+ /**
+ * Create an HttpURLConnection for the specified URL
+ *
+ * @param url The URL to create this connection for.
+ */
+ protected HttpURLConnection(URL url)
+ {
+ super(url);
+ }
+
+ /**
+ * Closes the connection to the server.
+ */
+ public abstract void disconnect();
+
+ /**
+ * Returns a boolean indicating whether or not this connection is going
+ * through a proxy
+ *
+ * @return true if through a proxy, false otherwise
+ */
+ public abstract boolean usingProxy();
+
+ /**
+ * Sets whether HTTP redirects (requests with response code 3xx) should be
+ * automatically followed by this class. True by default
+ *
+ * @param set true if redirects should be followed, false otherwis.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ 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;
+ }
+
+ /**
+ * Returns a boolean indicating whether or not HTTP redirects will
+ * automatically be followed or not.
+ *
+ * @return true if redirects will be followed, false otherwise
+ */
+ public static boolean getFollowRedirects()
+ {
+ return followRedirects;
+ }
+
+ /**
+ * Returns the value of this HttpURLConnection's instanceFollowRedirects
+ * field
+ *
+ * @return true if following redirects is enabled, false otherwise
+ */
+ public boolean getInstanceFollowRedirects()
+ {
+ return instanceFollowRedirects;
+ }
+
+ /**
+ * Sets the value of this HttpURLConnection's instanceFollowRedirects field
+ *
+ * @param follow true to enable following redirects, false otherwise
+ */
+ public void setInstanceFollowRedirects(boolean follow)
+ {
+ instanceFollowRedirects = follow;
+ }
+
+ /**
+ * Set the method for the URL request, one of:
+ * GET POST HEAD OPTIONS PUT DELETE TRACE are legal
+ *
+ * @param method the method to use
+ *
+ * @exception ProtocolException If the method cannot be reset or if the
+ * requested method isn't valid for HTTP
+ */
+ public void setRequestMethod(String method) throws ProtocolException
+ {
+ if (connected)
+ throw new ProtocolException("Already connected");
+
+ method = method.toUpperCase();
+ if (valid_methods.indexOf("|" + method + "|") != -1)
+ this.method = method;
+ else
+ throw new ProtocolException("Invalid HTTP request method: " + method);
+ }
+
+ /**
+ * The request method currently in use for this connection.
+ *
+ * @return The request method
+ */
+ public String getRequestMethod()
+ {
+ return method;
+ }
+
+ /**
+ * Gets the status code from an HTTP response message, or -1 if
+ * the response code could not be determined.
+ * Note that all valid response codes have class variables
+ * defined for them in this class.
+ *
+ * @return The response code
+ *
+ * @exception IOException If an error occurs
+ */
+ public int getResponseCode() throws IOException
+ {
+ if (! gotResponseVals)
+ getResponseVals();
+ return responseCode;
+ }
+
+ /**
+ * Gets the HTTP response message, if any, returned along with the
+ * response code from a server. Null if no response message was set
+ * or an error occured while connecting.
+ *
+ * @return The response message
+ *
+ * @exception IOException If an error occurs
+ */
+ public String getResponseMessage() throws IOException
+ {
+ if (! gotResponseVals)
+ getResponseVals();
+ return responseMessage;
+ }
+
+ private void getResponseVals() throws IOException
+ {
+ // getHeaderField() will connect for us, but do it here first in
+ // order to pick up IOExceptions.
+ if (! connected)
+ connect();
+
+ gotResponseVals = true;
+
+ // If responseCode not yet explicitly set by subclass
+ if (responseCode == -1)
+ {
+ // Response is the first header received from the connection.
+ String respField = getHeaderField(0);
+
+ if (respField == null || ! respField.startsWith("HTTP/"))
+ {
+ // Set to default values on failure.
+ responseCode = -1;
+ responseMessage = null;
+ return;
+ }
+
+ int firstSpc;
+ int 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;
+ }
+ }
+ }
+
+ /**
+ * Returns a permission object representing the permission necessary to make
+ * the connection represented by this object
+ *
+ * @return the permission necessary for this connection
+ *
+ * @exception IOException If an error occurs
+ */
+ public Permission getPermission() throws IOException
+ {
+ URL url = getURL();
+ String host = url.getHost();
+ int port = url.getPort();
+ if (port == -1)
+ port = 80;
+
+ host = host + ":" + port;
+
+ return new SocketPermission(host, "connect");
+ }
+
+ /**
+ * This method allows the caller to retrieve any data that might have
+ * been sent despite the fact that an error occurred. For example, the
+ * HTML page sent along with a 404 File Not Found error. If the socket
+ * is not connected, or if no error occurred or no data was returned,
+ * this method returns <code>null</code>.
+ *
+ * @return An <code>InputStream</code> for reading error data.
+ */
+ public InputStream getErrorStream()
+ {
+ if (! connected)
+ return null;
+
+ int code;
+ try
+ {
+ code = getResponseCode();
+ }
+ catch (IOException e)
+ {
+ code = -1;
+ }
+
+ if (code == -1)
+ return null;
+
+ if (((code / 100) != 4) || ((code / 100) != 5))
+ return null;
+
+ try
+ {
+ PushbackInputStream pbis = new PushbackInputStream(getInputStream());
+
+ int i = pbis.read();
+ if (i == -1)
+ return null;
+
+ pbis.unread(i);
+ return pbis;
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value of the named field parsed as date
+ *
+ * @param key the key of the header field
+ * @param value the default value if the header field is not present
+ *
+ * @return the value of the header field
+ */
+ public long getHeaderFieldDate(String key, long value)
+ {
+ // FIXME: implement this correctly
+ // http://www.w3.org/Protocols/HTTP-NG/ng-notes.txt
+ return super.getHeaderFieldDate(key, value);
+ }
+}
diff --git a/libjava/classpath/java/net/Inet4Address.java b/libjava/classpath/java/net/Inet4Address.java
new file mode 100644
index 000000000..e3cff7b13
--- /dev/null
+++ b/libjava/classpath/java/net/Inet4Address.java
@@ -0,0 +1,273 @@
+/* Inet4Address.java --
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.ObjectStreamException;
+
+/*
+ * Written using on-line Java Platform 1.4 API Specification and
+ * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt),
+ * RFC 1918 (http://www.ietf.org/rfc/rfc1918.txt),
+ * RFC 2365 (http://www.ietf.org/rfc/rfc2365.txt)
+ *
+ * @author Michael Koch
+ * @status Believed complete and correct.
+ */
+public final class Inet4Address extends InetAddress
+{
+ /**
+ * For compatability with Sun's JDK 1.4.2 rev. 5
+ */
+ static final long serialVersionUID = 3286316764910316507L;
+
+ /**
+ * The address family of these addresses (used for serialization).
+ */
+ private static final int AF_INET = 2;
+
+ /**
+ * Inet4Address objects are serialized as InetAddress objects.
+ */
+ private Object writeReplace() throws ObjectStreamException
+ {
+ return new InetAddress(addr, hostName, AF_INET);
+ }
+
+ /**
+ * Initializes this object's addr instance variable from the passed in
+ * byte array. Note that this constructor is protected and is called
+ * only by static methods in this class.
+ *
+ * @param addr The IP number of this address as an array of bytes
+ * @param host The hostname of this IP address.
+ */
+ Inet4Address(byte[] addr, String host)
+ {
+ super(addr, host, AF_INET);
+ }
+
+ /**
+ * Checks if the address is a multicast address
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ return (addr[0] & 0xf0) == 0xe0;
+ }
+
+ /**
+ * Checks if this address is a loopback address
+ */
+ public boolean isLoopbackAddress()
+ {
+ return (addr[0] & 0xff) == 0x7f;
+ }
+
+ /**
+ * Checks if this address is a wildcard address
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ return equals(InetAddress.ANY_IF);
+ }
+
+ /**
+ * Checks if this address is a link local address
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ return false;
+ }
+
+ /**
+ * Checks if this address is a site local address
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ // 10.0.0.0/8
+ if ((addr[0] & 0xff) == 0x0a)
+ return true;
+
+ // 172.16.0.0/12
+ if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
+ return true;
+
+ // 192.168.0.0/16
+ if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Checks if this multicast address has global scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ return false;
+ }
+
+ /**
+ * Checks if this multicast address has node scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ return false;
+ }
+
+ /**
+ * Checks if this multicast address has link scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return ((addr[0] & 0xff) == 0xe0
+ && (addr[1] & 0xff) == 0x00
+ && (addr[2] & 0xff) == 0x00);
+ }
+
+ /**
+ * Checks if this multicast address has site scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ return false;
+ }
+
+ /**
+ * Checks if this multicast address has organization scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ return false;
+ }
+
+ /**
+ * Returns the address of the current instance
+ */
+ public byte[] getAddress()
+ {
+ return (byte[]) addr.clone();
+ }
+
+ /**
+ * Returns the address as string
+ *
+ * @since 1.0.2
+ */
+ public String getHostAddress()
+ {
+ CPStringBuilder sb = new CPStringBuilder(40);
+
+ int len = addr.length;
+ int i = 0;
+
+ for ( ; ; )
+ {
+ sb.append(addr[i] & 0xff);
+ i++;
+
+ if (i == len)
+ break;
+
+ sb.append('.');
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Computes the hashcode of the instance
+ */
+ public int hashCode()
+ {
+ int hash = 0;
+ int len = addr.length;
+ int i = len > 4 ? len - 4 : 0;
+
+ for (; i < len; i++)
+ hash = (hash << 8) | (addr[i] & 0xFF);
+
+ return hash;
+ }
+
+ /**
+ * Compare the current Inet4Address instance with obj
+ *
+ * @param obj Object to compare with
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof InetAddress))
+ return false;
+
+ byte[] addr1 = addr;
+ byte[] addr2 = ((InetAddress) obj).addr;
+
+ if (addr1.length != addr2.length)
+ return false;
+
+ for (int i = addr1.length; --i >= 0;)
+ if (addr1[i] != addr2[i])
+ return false;
+
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/net/Inet6Address.java b/libjava/classpath/java/net/Inet6Address.java
new file mode 100644
index 000000000..60c406587
--- /dev/null
+++ b/libjava/classpath/java/net/Inet6Address.java
@@ -0,0 +1,429 @@
+/* Inet6Address.java --
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.util.Arrays;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+
+/*
+ * Written using on-line Java Platform 1.4 API Specification and
+ * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
+ *
+ * @author Michael Koch
+ * @status Updated to 1.5. Serialization compatibility is tested.
+ */
+public final class Inet6Address extends InetAddress
+{
+ static final long serialVersionUID = 6880410070516793377L;
+
+ /**
+ * Needed for serialization
+ */
+ byte[] ipaddress;
+
+ /**
+ * The scope ID, if any.
+ * @since 1.5
+ * @serial
+ */
+ private int scope_id;
+
+ /**
+ * The scope ID, if any.
+ * @since 1.5
+ * @serial
+ */
+ private boolean scope_id_set;
+
+ /**
+ * Whether ifname is set or not.
+ * @since 1.5
+ * @serial
+ */
+ private boolean scope_ifname_set;
+
+ /**
+ * Name of the network interface, used only by the serialization methods
+ * @since 1.5
+ * @serial
+ */
+ private String ifname;
+
+ /**
+ * Scope network interface, or <code>null</code>.
+ */
+ private transient NetworkInterface nif;
+
+ /**
+ * The address family of these addresses (used for serialization).
+ */
+ private static final int AF_INET6 = 10;
+
+ /**
+ * Create an Inet6Address object
+ *
+ * @param addr The IP address
+ * @param host The hostname
+ */
+ Inet6Address(byte[] addr, String host)
+ {
+ super(addr, host, AF_INET6);
+ // Super constructor clones the addr. Get a reference to the clone.
+ this.ipaddress = this.addr;
+ ifname = null;
+ scope_ifname_set = scope_id_set = false;
+ scope_id = 0;
+ nif = null;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an IP multicast address
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ return ipaddress[0] == (byte) 0xFF;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress in a wildcard address
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ return Arrays.equals(ipaddress, anylocal);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a loopback address
+ *
+ * @since 1.4
+ */
+ public boolean isLoopbackAddress()
+ {
+ byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+ return Arrays.equals(ipaddress, loopback);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an link local address
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ return ipaddress[0] == 0xFA;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a site local address
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ return ipaddress[0] == 0xFB;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has global scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0xE;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has node scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x1;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has link scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x2;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has site scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x5;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has organization scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x8;
+ }
+
+ /**
+ * Returns the raw IP address of this InetAddress object. The result is in
+ * network byte order: the highest order byte of the address is i
+ * n getAddress()[0]
+ */
+ public byte[] getAddress()
+ {
+ return (byte[]) ipaddress.clone();
+ }
+
+ /**
+ * Creates a scoped Inet6Address where the scope has an integer id.
+ *
+ * @throws UnkownHostException if the address is an invalid number of bytes.
+ * @since 1.5
+ */
+ public static Inet6Address getByAddress(String host, byte[] addr,
+ int scopeId)
+ throws UnknownHostException
+ {
+ if( addr.length != 16 )
+ throw new UnknownHostException("Illegal address length: " + addr.length
+ + " bytes.");
+ Inet6Address ip = new Inet6Address( addr, host );
+ ip.scope_id = scopeId;
+ ip.scope_id_set = true;
+ return ip;
+ }
+
+ /**
+ * Creates a scoped Inet6Address where the scope is a given
+ * NetworkInterface.
+ *
+ * @throws UnkownHostException if the address is an invalid number of bytes.
+ * @since 1.5
+ */
+ public static Inet6Address getByAddress(String host, byte[] addr,
+ NetworkInterface nif)
+ throws UnknownHostException
+ {
+ if( addr.length != 16 )
+ throw new UnknownHostException("Illegal address length: " + addr.length
+ + " bytes.");
+ Inet6Address ip = new Inet6Address( addr, host );
+ ip.nif = nif;
+
+ return ip;
+ }
+
+ /**
+ * Returns the <code>NetworkInterface</code> of the address scope
+ * if it is a scoped address and the scope is given in the form of a
+ * NetworkInterface.
+ * (I.e. the address was created using the
+ * getByAddress(String, byte[], NetworkInterface) method)
+ * Otherwise this method returns <code>null</code>.
+ * @since 1.5
+ */
+ public NetworkInterface getScopedInterface()
+ {
+ return nif;
+ }
+
+ /**
+ * Returns the scope ID of the address scope if it is a scoped adress using
+ * an integer to identify the scope.
+ *
+ * Otherwise this method returns 0.
+ * @since 1.5
+ */
+ public int getScopeId()
+ {
+ // check scope_id_set because some JDK-serialized objects seem to have
+ // scope_id set to a nonzero value even when scope_id_set == false
+ if( scope_id_set )
+ return scope_id;
+ return 0;
+ }
+
+ /**
+ * Returns the IP address string in textual presentation
+ */
+ public String getHostAddress()
+ {
+ CPStringBuilder sbuf = new CPStringBuilder(40);
+
+ for (int i = 0; i < 16; i += 2)
+ {
+ int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
+
+ if (i > 0)
+ sbuf.append(':');
+
+ sbuf.append(Integer.toHexString(x));
+ }
+ if( nif != null )
+ sbuf.append( "%" + nif.getName() );
+ else if( scope_id_set )
+ sbuf.append( "%" + scope_id );
+
+ return sbuf.toString();
+ }
+
+ /**
+ * Returns a hashcode for this IP address
+ * (The hashcode is independent of scope)
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * Compares this object against the specified object
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Inet6Address))
+ return false;
+
+ Inet6Address ip = (Inet6Address)obj;
+ if (ipaddress.length != ip.ipaddress.length)
+ return false;
+
+ for (int i = 0; i < ip.ipaddress.length; i++)
+ if (ipaddress[i] != ip.ipaddress[i])
+ return false;
+
+ if( ip.nif != null && nif != null )
+ return nif.equals( ip.nif );
+ if( ip.nif != nif )
+ return false;
+ if( ip.scope_id_set != scope_id_set )
+ return false;
+ if( scope_id_set )
+ return (scope_id == ip.scope_id);
+ return true;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an
+ * IPv4 compatible IPv6 address
+ *
+ * @since 1.4
+ */
+ public boolean isIPv4CompatibleAddress()
+ {
+ if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
+ || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
+ || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
+ || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
+ || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
+ || ipaddress[11] != 0x00)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Required for 1.5-compatible serialization.
+ * @since 1.5
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ try
+ {
+ if( scope_ifname_set )
+ nif = NetworkInterface.getByName( ifname );
+ }
+ catch( SocketException se )
+ {
+ // FIXME: Ignore this? or throw an IOException?
+ }
+ }
+
+ /**
+ * Required for 1.5-compatible serialization.
+ * @since 1.5
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ if( nif != null )
+ {
+ ifname = nif.getName();
+ scope_ifname_set = true;
+ }
+ s.defaultWriteObject();
+ }
+}
diff --git a/libjava/classpath/java/net/InetAddress.java b/libjava/classpath/java/net/InetAddress.java
new file mode 100644
index 000000000..1a9dc6202
--- /dev/null
+++ b/libjava/classpath/java/net/InetAddress.java
@@ -0,0 +1,655 @@
+/* InetAddress.java -- Class to model an Internet address
+ Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+/**
+ * This class models an Internet address. It does not have a public
+ * constructor. Instead, new instances of this objects are created
+ * using the static methods getLocalHost(), getByName(), and
+ * getAllByName().
+ *
+ * <p>This class fulfills the function of the C style functions gethostname(),
+ * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
+ * into their corresponding numeric addresses and vice versa.</p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ * @author Gary Benson (gbenson@redhat.com)
+ *
+ * @specnote This class is not final since JDK 1.4
+ */
+public class InetAddress implements Serializable
+{
+ private static final long serialVersionUID = 3286316764910316507L;
+
+ /**
+ * Dummy InetAddress, used to bind socket to any (all) network interfaces.
+ */
+ static InetAddress ANY_IF;
+ static
+ {
+ byte[] addr;
+ try
+ {
+ addr = VMInetAddress.lookupInaddrAny();
+ }
+ catch (UnknownHostException e)
+ {
+ // Make one up and hope it works.
+ addr = new byte[] {0, 0, 0, 0};
+ }
+ try
+ {
+ ANY_IF = getByAddress(addr);
+ }
+ catch (UnknownHostException e)
+ {
+ throw (InternalError) new InternalError().initCause(e);
+ }
+ ANY_IF.hostName = ANY_IF.getHostName();
+ }
+
+ /**
+ * Stores static localhost address object.
+ */
+ static InetAddress LOCALHOST;
+ static
+ {
+ try
+ {
+ LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1});
+ }
+ catch (UnknownHostException e)
+ {
+ throw (InternalError) new InternalError().initCause(e);
+ }
+ }
+
+ /**
+ * The Serialized Form specifies that an int 'address' is saved/restored.
+ * This class uses a byte array internally so we'll just do the conversion
+ * at serialization time and leave the rest of the algorithm as is.
+ */
+ private int address;
+
+ /**
+ * An array of octets representing an IP address.
+ */
+ transient byte[] addr;
+
+ /**
+ * The name of the host for this address.
+ */
+ String hostName;
+
+ /**
+ * Needed for serialization.
+ */
+ private int family;
+
+ /**
+ * Constructor. Prior to the introduction of IPv6 support in 1.4,
+ * methods such as InetAddress.getByName() would return InetAddress
+ * objects. From 1.4 such methods returned either Inet4Address or
+ * Inet6Address objects, but for compatibility Inet4Address objects
+ * are serialized as InetAddresses. As such, there are only two
+ * places where it is appropriate to invoke this constructor: within
+ * subclasses constructors and within Inet4Address.writeReplace().
+ *
+ * @param ipaddr The IP number of this address as an array of bytes
+ * @param hostname The hostname of this IP address.
+ * @param family The address family of this IP address.
+ */
+ InetAddress(byte[] ipaddr, String hostname, int family)
+ {
+ addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
+ hostName = hostname;
+ this.family = family;
+ }
+
+ /**
+ * Returns true if this address is a multicast address, false otherwise.
+ * An address is multicast if the high four bits are "1110". These are
+ * also known as "Class D" addresses.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @return true if mulitcast, false if not
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if the InetAddress in a wildcard address
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a loopback address
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isLoopbackAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a link local address
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a site local address
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a global multicast address
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a node local multicast address.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a link local multicast address.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a site local multicast address.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a organization local
+ * multicast address.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the hostname for this address. This will return the IP address
+ * as a String if there is no hostname available for this address
+ *
+ * @return The hostname for this address
+ */
+ public String getHostName()
+ {
+ if (hostName == null)
+ hostName = getCanonicalHostName();
+
+ return hostName;
+ }
+
+ /**
+ * Returns the canonical hostname represented by this InetAddress
+ */
+ String internalGetCanonicalHostName()
+ {
+ try
+ {
+ return ResolverCache.getHostByAddr(addr);
+ }
+ catch (UnknownHostException e)
+ {
+ return getHostAddress();
+ }
+ }
+
+ /**
+ * Returns the canonical hostname represented by this InetAddress
+ *
+ * @since 1.4
+ */
+ public String getCanonicalHostName()
+ {
+ String hostname = internalGetCanonicalHostName();
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ try
+ {
+ sm.checkConnect(hostname, -1);
+ }
+ catch (SecurityException e)
+ {
+ return getHostAddress();
+ }
+ }
+
+ return hostname;
+ }
+
+ /**
+ * Returns the IP address of this object as a byte array.
+ *
+ * @return IP address
+ */
+ 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[]) addr.clone();
+ }
+
+ /**
+ * Returns the IP address of this object as a String.
+ *
+ * <p>This method cannot be abstract for backward compatibility reasons. By
+ * default it always throws {@link UnsupportedOperationException} unless
+ * overridden.</p>
+ *
+ * @return The IP address of this object in String form
+ *
+ * @since 1.0.2
+ */
+ public String getHostAddress()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a hash value for this address. Useful for creating hash
+ * tables. Overrides Object.hashCode()
+ *
+ * @return A hash value for this address.
+ */
+ 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 = addr.length;
+ int i = len > 4 ? len - 4 : 0;
+
+ for (; i < len; i++)
+ hash = (hash << 8) | (addr[i] & 0xff);
+
+ return hash;
+ }
+
+ /**
+ * Tests this address for equality against another InetAddress. The two
+ * addresses are considered equal if they contain the exact same octets.
+ * This implementation overrides Object.equals()
+ *
+ * @param obj The address to test for equality
+ *
+ * @return true if the passed in object's address is equal to this one's,
+ * false otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (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 experimentation
+ // shows that the latter is correct.
+ byte[] addr2 = ((InetAddress) obj).addr;
+
+ if (addr.length != addr2.length)
+ return false;
+
+ for (int i = 0; i < addr.length; i++)
+ if (addr[i] != addr2[i])
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Converts this address to a String. This string contains the IP in
+ * dotted decimal form. For example: "127.0.0.1" This method is equivalent
+ * to getHostAddress() and overrides Object.toString()
+ *
+ * @return This address in String form
+ */
+ public String toString()
+ {
+ String addr = getHostAddress();
+ String host = (hostName != null) ? hostName : "";
+ return host + "/" + addr;
+ }
+
+ /**
+ * Returns an InetAddress object given the raw IP address.
+ *
+ * The argument is in network byte order: the highest order byte of the
+ * address is in getAddress()[0].
+ *
+ * @param addr The IP address to create the InetAddress object from
+ *
+ * @exception UnknownHostException If IP address has illegal length
+ *
+ * @since 1.4
+ */
+ public static InetAddress getByAddress(byte[] addr)
+ throws UnknownHostException
+ {
+ return getByAddress(null, addr);
+ }
+
+ /**
+ * Creates an InetAddress based on the provided host name and IP address.
+ * No name service is checked for the validity of the address.
+ *
+ * @param host The hostname of the InetAddress object to create
+ * @param addr The IP address to create the InetAddress object from
+ *
+ * @exception UnknownHostException If IP address is of illegal length
+ *
+ * @since 1.4
+ */
+ public static InetAddress getByAddress(String host, byte[] addr)
+ throws UnknownHostException
+ {
+ if (addr.length == 4)
+ return new Inet4Address(addr, host);
+
+ if (addr.length == 16)
+ {
+ for (int i = 0; i < 12; i++)
+ {
+ if (addr[i] != (i < 10 ? 0 : (byte) 0xFF))
+ return new Inet6Address(addr, host);
+ }
+
+ byte[] ip4addr = new byte[4];
+ ip4addr[0] = addr[12];
+ ip4addr[1] = addr[13];
+ ip4addr[2] = addr[14];
+ ip4addr[3] = addr[15];
+ return new Inet4Address(ip4addr, host);
+ }
+
+ throw new UnknownHostException("IP address has illegal length");
+ }
+
+ /**
+ * Returns an InetAddress object representing the IP address of
+ * the given literal IP address in dotted decimal format such as
+ * "127.0.0.1". This is used by SocketPermission.setHostPort()
+ * to parse literal IP addresses without performing a DNS lookup.
+ *
+ * @param literal The literal IP address to create the InetAddress
+ * object from
+ *
+ * @return The address of the host as an InetAddress object, or
+ * null if the IP address is invalid.
+ */
+ static InetAddress getByLiteral(String literal)
+ {
+ byte[] address = VMInetAddress.aton(literal);
+ if (address == null)
+ return null;
+
+ try
+ {
+ return getByAddress(address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw (InternalError) new InternalError().initCause(e);
+ }
+ }
+
+ /**
+ * Returns an InetAddress object representing the IP address of the given
+ * hostname. This name can be either a hostname such as "www.urbanophile.com"
+ * or an IP address in dotted decimal format such as "127.0.0.1". If the
+ * hostname is null or "", the hostname of the local machine is supplied by
+ * default. This method is equivalent to returning the first element in
+ * the InetAddress array returned from GetAllByName.
+ *
+ * @param hostname The name of the desired host, or null for the local
+ * loopback address.
+ *
+ * @return The address of the host as an InetAddress object.
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public static InetAddress getByName(String hostname)
+ throws UnknownHostException
+ {
+ InetAddress[] addresses = getAllByName(hostname);
+ return addresses[0];
+ }
+
+ /**
+ * Returns an array of InetAddress objects representing all the host/ip
+ * addresses of a given host, given the host's name. This name can be
+ * either a hostname such as "www.urbanophile.com" or an IP address in
+ * dotted decimal format such as "127.0.0.1". If the value is null, the
+ * hostname of the local machine is supplied by default.
+ *
+ * @param hostname The name of the desired host, or null for the
+ * local loopback address.
+ *
+ * @return All addresses of the host as an array of InetAddress objects.
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public static InetAddress[] getAllByName(String hostname)
+ throws UnknownHostException
+ {
+ // If null or the empty string is supplied, the loopback address
+ // is returned.
+ if (hostname == null || hostname.length() == 0)
+ return new InetAddress[] {LOCALHOST};
+
+ // Check if hostname is an IP address
+ InetAddress address = getByLiteral(hostname);
+ if (address != null)
+ return new InetAddress[] {address};
+
+ // Perform security check before resolving
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(hostname, -1);
+
+ // Resolve the hostname
+ byte[][] iplist = ResolverCache.getHostByName(hostname);
+ if (iplist.length == 0)
+ throw new UnknownHostException(hostname);
+
+ InetAddress[] addresses = new InetAddress[iplist.length];
+ for (int i = 0; i < iplist.length; i++)
+ addresses[i] = getByAddress(hostname, iplist[i]);
+
+ return addresses;
+ }
+
+ /**
+ * Returns an InetAddress object representing the address of the current
+ * host.
+ *
+ * @return The local host's address
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ */
+ public static InetAddress getLocalHost() throws UnknownHostException
+ {
+ String hostname = VMInetAddress.getLocalHostname();
+ try
+ {
+ return getByName(hostname);
+ }
+ catch (SecurityException e)
+ {
+ return LOCALHOST;
+ }
+ }
+
+ /**
+ * Inet4Address objects are serialized as InetAddress objects.
+ * This deserializes them back into Inet4Address objects.
+ */
+ private Object readResolve() throws ObjectStreamException
+ {
+ return new Inet4Address(addr, hostName);
+ }
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+ addr = new byte[4];
+ addr[3] = (byte) address;
+
+ for (int i = 2; i >= 0; --i)
+ addr[i] = (byte) (address >>= 8);
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException
+ {
+ // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
+ // or a 16 byte IPv6 address.
+ int len = addr.length;
+ int i = len - 4;
+
+ for (; i < len; i++)
+ address = address << 8 | (addr[i] & 0xff);
+
+ oos.defaultWriteObject();
+ }
+}
diff --git a/libjava/classpath/java/net/InetSocketAddress.java b/libjava/classpath/java/net/InetSocketAddress.java
new file mode 100644
index 000000000..2126f7703
--- /dev/null
+++ b/libjava/classpath/java/net/InetSocketAddress.java
@@ -0,0 +1,261 @@
+/* InetSocketAddress.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * InetSocketAddress instances represent socket addresses
+ * in the java.nio package. They encapsulate a InetAddress and
+ * a port number.
+ *
+ * @since 1.4
+ */
+public class InetSocketAddress extends SocketAddress
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ private static final long serialVersionUID = 5076001401234631237L;
+
+ /**
+ * Name of host.
+ */
+ private String hostname;
+
+ /**
+ * Address of host.
+ */
+ private InetAddress addr;
+
+ /**
+ * Port of host.
+ */
+ private int port;
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param addr Address of the socket
+ * @param port Port if the socket
+ *
+ * @exception IllegalArgumentException If the port number is illegel
+ */
+ public InetSocketAddress(InetAddress addr, int port)
+ throws IllegalArgumentException
+ {
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Bad port number: " + port);
+
+ if (addr == null)
+ addr = InetAddress.ANY_IF;
+
+ this.addr = addr;
+ this.port = port;
+ }
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param port Port if the socket
+ *
+ * @exception IllegalArgumentException If the port number is illegal
+ */
+ public InetSocketAddress(int port) throws IllegalArgumentException
+ {
+ this((InetAddress) null, port);
+ }
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param hostname The hostname for the socket address
+ * @param port The port for the socket address
+ *
+ * @exception IllegalArgumentException If the port number is illegal or
+ * the hostname argument is null
+ */
+ public InetSocketAddress(String hostname, int port)
+ {
+ this(hostname, port, true);
+ }
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param hostname The hostname for the socket address
+ * @param port The port for the socket address
+ * @param resolve <code>true</code> if the address has to be resolved,
+ * <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException If the port number is illegal or
+ * the hostname argument is null
+ */
+ private InetSocketAddress(String hostname, int port, boolean resolve)
+ {
+ if (hostname == null)
+ throw new IllegalArgumentException("Null host name value");
+
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Bad port number: " + port);
+
+ this.port = port;
+ this.hostname = hostname;
+ this.addr = null;
+
+ if (resolve)
+ {
+ try
+ {
+ this.addr = InetAddress.getByName(hostname);
+ }
+ catch (Exception e) // UnknownHostException, SecurityException
+ {
+ // Do nothing here. this.addr is already set to null.
+ }
+ }
+
+ }
+
+ /**
+ * Creates an unresolved <code>InetSocketAddress</code> object.
+ *
+ * @param hostname The hostname for the socket address
+ * @param port The port for the socket address
+ *
+ * @exception IllegalArgumentException If the port number is illegal or
+ * the hostname argument is null
+ *
+ * @since 1.5
+ */
+ public static InetSocketAddress createUnresolved(String hostname, int port)
+ {
+ return new InetSocketAddress(hostname, port, false);
+ }
+
+ /**
+ * Test if obj is a <code>InetSocketAddress</code> and
+ * has the same address and port
+ *
+ * @param obj The obj to compare this address with.
+ *
+ * @return True if obj is equal.
+ */
+ public final boolean equals(Object obj)
+ {
+ // InetSocketAddress objects are equal when addr and port are equal.
+ // The hostname may differ.
+ if (obj instanceof InetSocketAddress)
+ {
+ InetSocketAddress sa = (InetSocketAddress) obj;
+
+ if (addr == null && sa.addr != null)
+ return false;
+ else if (addr == null && sa.addr == null) // we know hostname != null
+ return hostname.equals(sa.hostname) && sa.port == port;
+ else
+ return addr.equals(sa.addr) && sa.port == port;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the <code>InetAddress</code> or
+ * <code>null</code> if its unresolved
+ *
+ * @return The IP address of this address.
+ */
+ public final InetAddress getAddress()
+ {
+ return addr;
+ }
+
+ /**
+ * Returns <code>hostname</code>
+ *
+ * @return The hostname of this address.
+ */
+ public final String getHostName()
+ {
+ if (hostname == null) // we know addr != null
+ hostname = addr.getHostName();
+
+ return hostname;
+ }
+
+ /**
+ * Returns the <code>port</code>
+ *
+ * @return The port of this address.
+ */
+ public final int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the hashcode of the <code>InetSocketAddress</code>
+ *
+ * @return The hashcode for this address.
+ */
+ public final int hashCode()
+ {
+ return port + addr.hashCode();
+ }
+
+ /**
+ * Checks wether the address has been resolved or not
+ *
+ * @return True if address is unresolved.
+ */
+ public final boolean isUnresolved()
+ {
+ return addr == null;
+ }
+
+ /**
+ * Returns the <code>InetSocketAddress</code> as string
+ *
+ * @return A string representation of this address.
+ */
+ public String toString()
+ {
+ // Note: if addr is null, then hostname != null.
+ return (addr == null ? hostname : addr.toString()) + ":" + port;
+ }
+}
diff --git a/libjava/classpath/java/net/JarURLConnection.java b/libjava/classpath/java/net/JarURLConnection.java
new file mode 100644
index 000000000..0ffd1afac
--- /dev/null
+++ b/libjava/classpath/java/net/JarURLConnection.java
@@ -0,0 +1,229 @@
+/* JarURLConnection.java -- Class for manipulating remote jar files
+ Copyright (C) 1998, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+
+/**
+ * This abstract class represents a common superclass for implementations
+ * of jar URL's. A jar URL is a special type of URL that allows JAR
+ * files on remote systems to be accessed. It has the form:
+ * <p>
+ * jar:&lt;standard URL pointing to jar filei&gt;!/file/within/jarfile
+ * <p> for example:
+ * <p>
+ * jar:http://www.urbanophile.com/java/foo.jar!/com/urbanophile/bar.class
+ * <p>
+ * That example URL points to the file /com/urbanophile/bar.class in the
+ * remote JAR file http://www.urbanophile.com/java/foo.jar. The HTTP
+ * protocol is used only as an example. Any supported remote protocol
+ * can be used.
+ * <p>
+ * This class currently works by retrieving the entire jar file into a
+ * local cache file, then performing standard jar operations on it.
+ * (At least this is true for the default protocol implementation).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Kresten Krab Thorup (krab@gnu.org)
+ * @date Aug 10, 1999.
+ *
+ * @since 1.2
+ */
+public abstract class JarURLConnection extends URLConnection
+{
+ /**
+ * This is the actual URL that points the remote jar file. This is parsed
+ * out of the jar URL by the constructor.
+ */
+ private final URL jarFileURL;
+
+ /**
+ * The connection to the jar file itself. A JarURLConnection
+ * can represent an entry in a jar file or an entire jar file. In
+ * either case this describes just the jar file itself.
+ */
+ protected URLConnection jarFileURLConnection;
+
+ /**
+ * This is the jar file "entry name" or portion after the "!/" in the
+ * URL which represents the pathname inside the actual jar file.
+ */
+ private final String entryName;
+
+ /**
+ * Creates a JarURLConnection from an URL object
+ *
+ * @param url The URL object for this connection.
+ *
+ * @exception MalformedURLException If url is invalid
+ *
+ * @specnote This constructor is protected since JDK 1.4
+ */
+ protected JarURLConnection(URL url) throws MalformedURLException
+ {
+ super(url);
+
+ if (! url.getProtocol().equals("jar"))
+ throw new MalformedURLException(url + ": Not jar protocol.");
+
+ String spec = url.getFile();
+ int bang = spec.indexOf("!/");
+ if (bang == -1)
+ throw new MalformedURLException(url + ": No `!/' in spec.");
+
+ // Extract the url for the jar itself.
+ jarFileURL = new URL(spec.substring(0, bang));
+
+ // Get the name of the entry, if any.
+ entryName = spec.length() == (bang + 2) ? null : spec.substring(bang + 2);
+ }
+
+ /**
+ * This method returns the "real" URL where the JarFile is located.
+ * //****Is this right?*****
+ *
+ * @return The remote URL
+ */
+ public URL getJarFileURL()
+ {
+ return jarFileURL;
+ }
+
+ /**
+ * Returns the "entry name" portion of the jar URL. This is the portion
+ * after the "!/" in the jar URL that represents the pathname inside the
+ * actual jar file.
+ *
+ * @return The entry name.
+ */
+ public String getEntryName()
+ {
+ return entryName;
+ }
+
+ /**
+ * Returns the entry in this jar file specified by the URL.
+ *
+ * @return The jar entry
+ *
+ * @exception IOException If an error occurs
+ */
+ public JarEntry getJarEntry() throws IOException
+ {
+ if (entryName == null)
+ return null;
+ JarFile jarFile = getJarFile();
+ return jarFile != null ? jarFile.getJarEntry(entryName) : null;
+ }
+
+ /**
+ * Returns a read-only JarFile object for the remote jar file
+ *
+ * @return The JarFile object
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract JarFile getJarFile() throws IOException;
+
+ /**
+ * Returns an array of Certificate objects for the jar file entry specified
+ * by this URL or null if there are none
+ *
+ * @return A Certificate array
+ *
+ * @exception IOException If an error occurs
+ */
+ public Certificate[] getCertificates() throws IOException
+ {
+ JarEntry entry = getJarEntry();
+
+ return entry != null ? entry.getCertificates() : null;
+ }
+
+ /**
+ * Returns the main Attributes for the jar file specified in the URL or
+ * null if there are none
+ *
+ * @return The main Attributes for the JAR file for this connection
+ *
+ * @exception IOException If an error occurs
+ */
+ public Attributes getMainAttributes() throws IOException
+ {
+ Manifest manifest = getManifest();
+
+ return manifest != null ? manifest.getMainAttributes() : null;
+ }
+
+ /**
+ * Returns the Attributes for the Jar entry specified by the URL or null
+ * if none
+ *
+ * @return The Attributes object for this connection if the URL for it points
+ * to a JAR file entry, null otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ public Attributes getAttributes() throws IOException
+ {
+ JarEntry entry = getJarEntry();
+
+ return entry != null ? entry.getAttributes() : null;
+ }
+
+ /**
+ * Returns a Manifest object for this jar file, or null if there is no
+ * manifest.
+ *
+ * @return The Manifest for this connection, or null if none
+ *
+ * @exception IOException If an error occurs
+ */
+ public Manifest getManifest() throws IOException
+ {
+ JarFile file = getJarFile();
+
+ return file != null ? file.getManifest() : null;
+ }
+}
diff --git a/libjava/classpath/java/net/MalformedURLException.java b/libjava/classpath/java/net/MalformedURLException.java
new file mode 100644
index 000000000..27e201886
--- /dev/null
+++ b/libjava/classpath/java/net/MalformedURLException.java
@@ -0,0 +1,74 @@
+/* MalformedURLException.java -- A URL was not in a valid format
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that a URL passed to an object was not in a
+ * valid format.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class MalformedURLException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -182787522200415866L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public MalformedURLException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public MalformedURLException(String message)
+ {
+ super(message);
+ }
+} // class MalformedURLException
diff --git a/libjava/classpath/java/net/MimeTypeMapper.java b/libjava/classpath/java/net/MimeTypeMapper.java
new file mode 100644
index 000000000..3e4379291
--- /dev/null
+++ b/libjava/classpath/java/net/MimeTypeMapper.java
@@ -0,0 +1,346 @@
+/* MimeTypeMapper.java -- A class for mapping file names to MIME types
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+
+/**
+ * This non-public class is used to implement the FileNameMap interface
+ * which defines a mechanism for mapping filenames to MIME types.
+ *
+ * @version 0.5
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+class MimeTypeMapper implements FileNameMap
+{
+ /**
+ * This array of strings is used to identify a MIME type based on a file
+ * extension. This is list is based on the Apache mime.types file.
+ */
+ protected static final String[][] mime_strings =
+ {
+ { "ai", "application/postscript" }
+ , { "aif", "audio/x-aiff" }
+ , { "aifc", "audio/x-aiff" }
+ , { "aiff", "audio/x-aiff" }
+ , { "asc", "text/plain" }
+ , { "au", "audio/basic" }
+ , { "avi", "video/x-msvideo" }
+ , { "bcpio", "application/x-bcpio" }
+ , { "bin", "application/octet-stream" }
+ , { "bmp", "image/bmp" }
+ , { "bz2", "application/x-bzip2" }
+ , { "cdf", "application/x-netcdf" }
+ , { "chrt", "application/x-kchart" }
+ , { "class", "application/octet-stream" }
+ , { "cpio", "application/x-cpio" }
+ , { "cpt", "application/mac-compactpro" }
+ , { "csh", "application/x-csh" }
+ , { "css", "text/css" }
+ , { "dcr", "application/x-director" }
+ , { "dir", "application/x-director" }
+ , { "djv", "image/vnd.djvu" }
+ , { "djvu", "image/vnd.djvu" }
+ , { "dll", "application/octet-stream" }
+ , { "dms", "application/octet-stream" }
+ , { "doc", "application/msword" }
+ , { "dvi", "application/x-dvi" }
+ , { "dxr", "application/x-director" }
+ , { "eps", "application/postscript" }
+ , { "etx", "text/x-setext" }
+ , { "exe", "application/octet-stream" }
+ , { "ez", "application/andrew-inset" }
+ , { "gif", "image/gif" }
+ , { "gtar", "application/x-gtar" }
+ , { "gz", "application/x-gzip" }
+ , { "hdf", "application/x-hdf" }
+ , { "hqx", "application/mac-binhex40" }
+ , { "htm", "text/html" }
+ , { "html", "text/html" }
+ , { "ice", "x-conference/x-cooltalk" }
+ , { "ief", "image/ief" }
+ , { "iges", "model/iges" }
+ , { "igs", "model/iges" }
+ , { "img", "application/octet-stream" }
+ , { "iso", "application/octet-stream" }
+ , { "jpe", "image/jpeg" }
+ , { "jpeg", "image/jpeg" }
+ , { "jpg", "image/jpeg" }
+ , { "js", "application/x-javascript" }
+ , { "kar", "audio/midi" }
+ , { "kil", "application/x-killustrator" }
+ , { "kpr", "application/x-kpresenter" }
+ , { "kpt", "application/x-kpresenter" }
+ , { "ksp", "application/x-kspread" }
+ , { "kwd", "application/x-kword" }
+ , { "kwt", "application/x-kword" }
+ , { "latex", "application/x-latex" }
+ , { "lha", "application/octet-stream" }
+ , { "lzh", "application/octet-stream" }
+ , { "m3u", "audio/x-mpegurl" }
+ , { "man", "application/x-troff-man" }
+ , { "me", "application/x-troff-me" }
+ , { "mesh", "model/mesh" }
+ , { "mid", "audio/midi" }
+ , { "midi", "audio/midi" }
+ , { "mif", "application/vnd.mif" }
+ , { "mov", "video/quicktime" }
+ , { "movie", "video/x-sgi-movie" }
+ , { "mp2", "audio/mpeg" }
+ , { "mp3", "audio/mpeg" }
+ , { "mpe", "video/mpeg" }
+ , { "mpeg", "video/mpeg" }
+ , { "mpg", "video/mpeg" }
+ , { "mpga", "audio/mpeg" }
+ , { "ms", "application/x-troff-ms" }
+ , { "msh", "model/mesh" }
+ , { "mxu", "video/vnd.mpegurl" }
+ , { "nc", "application/x-netcdf" }
+ , { "ogg", "application/ogg" }
+ , { "pbm", "image/x-portable-bitmap" }
+ , { "pdb", "chemical/x-pdb" }
+ , { "pdf", "application/pdf" }
+ , { "pgm", "image/x-portable-graymap" }
+ , { "pgn", "application/x-chess-pgn" }
+ , { "png", "image/png" }
+ , { "pnm", "image/x-portable-anymap" }
+ , { "ppm", "image/x-portable-pixmap" }
+ , { "ppt", "application/vnd.ms-powerpoint" }
+ , { "ps", "application/postscript" }
+ , { "qt", "video/quicktime" }
+ , { "ra", "audio/x-realaudio" }
+ , { "ram", "audio/x-pn-realaudio" }
+ , { "ras", "image/x-cmu-raster" }
+ , { "rgb", "image/x-rgb" }
+ , { "rm", "audio/x-pn-realaudio" }
+ , { "roff", "application/x-troff" }
+ , { "rpm", "application/x-rpm" }
+ , { "rtf", "text/rtf" }
+ , { "rtx", "text/richtext" }
+ , { "sgm", "text/sgml" }
+ , { "sgml", "text/sgml" }
+ , { "sh", "application/x-sh" }
+ , { "shar", "application/x-shar" }
+ , { "silo", "model/mesh" }
+ , { "sit", "application/x-stuffit" }
+ , { "skd", "application/x-koan" }
+ , { "skm", "application/x-koan" }
+ , { "skp", "application/x-koan" }
+ , { "skt", "application/x-koan" }
+ , { "smi", "application/smil" }
+ , { "smil", "application/smil" }
+ , { "snd", "audio/basic" }
+ , { "so", "application/octet-stream" }
+ , { "spl", "application/x-futuresplash" }
+ , { "src", "application/x-wais-source" }
+ , { "stc", "application/vnd.sun.xml.calc.template" }
+ , { "std", "application/vnd.sun.xml.draw.template" }
+ , { "sti", "application/vnd.sun.xml.impress.template" }
+ , { "stw", "application/vnd.sun.xml.writer.template" }
+ , { "sv4cpio", "application/x-sv4cpio" }
+ , { "sv4crc", "application/x-sv4crc" }
+ , { "swf", "application/x-shockwave-flash" }
+ , { "sxc", "application/vnd.sun.xml.calc" }
+ , { "sxd", "application/vnd.sun.xml.draw" }
+ , { "sxg", "application/vnd.sun.xml.writer.global" }
+ , { "sxi", "application/vnd.sun.xml.impress" }
+ , { "sxm", "application/vnd.sun.xml.math" }
+ , { "sxw", "application/vnd.sun.xml.writer" }
+ , { "t", "application/x-troff" }
+ , { "tar", "application/x-tar" }
+ , { "tcl", "application/x-tcl" }
+ , { "tex", "application/x-tex" }
+ , { "texi", "application/x-texinfo" }
+ , { "texinfo", "application/x-texinfo" }
+ , { "tgz", "application/x-gzip" }
+ , { "tif", "image/tiff" }
+ , { "tiff", "image/tiff" }
+ , { "torrent", "application/x-bittorrent" }
+ , { "tr", "application/x-troff" }
+ , { "tsv", "text/tab-separated-values" }
+ , { "txt", "text/plain" }
+ , { "ustar", "application/x-ustar" }
+ , { "vcd", "application/x-cdlink" }
+ , { "vrml", "model/vrml" }
+ , { "wav", "audio/x-wav" }
+ , { "wbmp", "image/vnd.wap.wbmp" }
+ , { "wbxml", "application/vnd.wap.wbxml" }
+ , { "wml", "text/vnd.wap.wml" }
+ , { "wmlc", "application/vnd.wap.wmlc" }
+ , { "wmls", "text/vnd.wap.wmlscript" }
+ , { "wmlsc", "application/vnd.wap.wmlscriptc" }
+ , { "wrl", "model/vrml" }
+ , { "xbm", "image/x-xbitmap" }
+ , { "xht", "application/xhtml+xml" }
+ , { "xhtml", "application/xhtml+xml" }
+ , { "xls", "application/vnd.ms-excel" }
+ , { "xml", "text/xml" }
+ , { "xpm", "image/x-xpixmap" }
+ , { "xsl", "text/xml" }
+ , { "xwd", "image/x-xwindowdump" }
+ , { "xyz", "chemical/x-xyz" }
+ , { "zip", "application/zip" }
+ };
+
+ /**
+ * The MIME types above are put into this Hashtable for faster lookup.
+ */
+ private Hashtable<String, String> mime_types
+ = new Hashtable<String, String>(150);
+
+ /**
+ * Create a new <code>MimeTypeMapper</code> object.
+ */
+ public MimeTypeMapper()
+ {
+ for (int i = 0; i < mime_strings.length; i++)
+ mime_types.put(mime_strings[i][0], mime_strings[i][1]);
+
+ // Now read from the system mime database, if it exists. Entries found
+ // here override our internal ones.
+ try
+ {
+ // On Linux this usually means /etc/mime.types.
+ String file
+ = SystemProperties.getProperty("gnu.classpath.mime.types.file");
+ if (file != null)
+ fillFromFile(mime_types, file);
+ }
+ catch (IOException ignore)
+ {
+ }
+ }
+
+ public static void fillFromFile (Map<String, String> table, String fname)
+ throws IOException
+ {
+ LineNumberReader reader =
+ new LineNumberReader (new FileReader (fname));
+
+ while (reader.ready ())
+ {
+ StringTokenizer tokenizer =
+ new StringTokenizer (reader.readLine ());
+
+ try
+ {
+ String t = tokenizer.nextToken ();
+
+ if (! t.startsWith ("#"))
+ {
+ while (true)
+ {
+ // Read the next extension
+ String e = tokenizer.nextToken ();
+ if ((e != null) && (! e.startsWith ("#")))
+ table.put (e, t);
+ else
+ break;
+ }
+ }
+ }
+ catch (NoSuchElementException ex)
+ {
+ // Do nothing.
+ }
+ }
+ }
+
+ /**
+ * The method returns the MIME type of the filename passed as an argument.
+ * The value returned is based on the extension of the filename. The
+ * default content type returned if this method cannot determine the
+ * actual content type is "application/octet-stream"
+ *
+ * @param filename The name of the file to return the MIME type for
+ *
+ * @return The MIME type
+ */
+ public String getContentTypeFor(String filename)
+ {
+ int index = filename.lastIndexOf(".");
+ if (index != -1)
+ {
+ if (index == filename.length())
+ return "application/octet-stream";
+ else
+ filename = filename.substring(index + 1);
+ }
+
+ String type = (String) mime_types.get(filename);
+ if (type == null)
+ return "application/octet-stream";
+ else
+ return type;
+ }
+
+ /**
+ * Run this class as a program to create a new mime_strings table.
+ */
+ public static void main(String[] args) throws IOException
+ {
+ TreeMap<String, String> map = new TreeMap<String, String>();
+ // It is fine to hard-code the name here. This is only ever
+ // used by maintainers, who can hack it if they need to re-run
+ // it.
+ fillFromFile(map, "/etc/mime.types");
+ Iterator<String> it = map.keySet().iterator();
+ boolean first = true;
+ while (it.hasNext())
+ {
+ String key = it.next();
+ String value = map.get(key);
+ // Put the "," first since it is easier to make correct syntax this way.
+ System.out.println(" " + (first ? " " : ", ")
+ + "{ \"" + key + "\", \"" + value + "\" }");
+ first = false;
+ }
+ }
+}
diff --git a/libjava/classpath/java/net/MulticastSocket.java b/libjava/classpath/java/net/MulticastSocket.java
new file mode 100644
index 000000000..5014b6a8e
--- /dev/null
+++ b/libjava/classpath/java/net/MulticastSocket.java
@@ -0,0 +1,518 @@
+/* MulticastSocket.java -- Class for using multicast sockets
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2007
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+
+/**
+ * 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.
+ */
+/**
+ * This class models a multicast UDP socket. A multicast address is a
+ * class D internet address (one whose most significant bits are 1110).
+ * A multicast group consists of a multicast address and a well known
+ * port number. All members of the group listening on that address and
+ * port will receive all the broadcasts to the group.
+ * <p>
+ * Please note that applets are not allowed to use multicast sockets
+ *
+ * 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.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com) (Documentation comments)
+ * @since 1.1
+ * @date May 18, 1999.
+ */
+public class MulticastSocket extends DatagramSocket
+{
+ /**
+ * Create a MulticastSocket that this not bound to any address
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public MulticastSocket() throws IOException
+ {
+ this(new InetSocketAddress(0));
+ }
+
+ /**
+ * Create a multicast socket bound to the specified port
+ *
+ * @param port The port to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public MulticastSocket(int port) throws IOException
+ {
+ this(new InetSocketAddress(port));
+ }
+
+ /**
+ * Create a multicast socket bound to the specified SocketAddress.
+ *
+ * @param address The SocketAddress the multicast socket will be bound to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public MulticastSocket(SocketAddress address) throws IOException
+ {
+ super((SocketAddress) null);
+ setReuseAddress(true);
+ if (address != null)
+ bind(address);
+ }
+
+ /**
+ * Returns the interface being used for multicast packets
+ *
+ * @return The multicast interface
+ *
+ * @exception SocketException If an error occurs
+ */
+ public InetAddress getInterface() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ return (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
+ }
+
+ /**
+ * Returns the current value of the "Time to Live" option. This is the
+ * number of hops a packet can make before it "expires". This method id
+ * deprecated. Use <code>getTimeToLive</code> instead.
+ *
+ * @return The TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated 1.2 Replaced by getTimeToLive()
+ *
+ * @see MulticastSocket#getTimeToLive()
+ */
+ public byte getTTL() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // Use getTTL here rather than getTimeToLive in case we're using an impl
+ // other than the default PlainDatagramSocketImpl and it doesn't have
+ // getTimeToLive yet.
+ return getImpl().getTTL();
+ }
+
+ /**
+ * Returns the current value of the "Time to Live" option. This is the
+ * number of hops a packet can make before it "expires".
+ *
+ * @return The TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public int getTimeToLive() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ return getImpl().getTimeToLive();
+ }
+
+ /**
+ * Sets the interface to use for sending multicast packets.
+ *
+ * @param addr The new interface to use.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public void setInterface(InetAddress addr) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.IP_MULTICAST_IF, addr);
+ }
+
+ /**
+ * Sets the local network interface used to send multicast messages
+ *
+ * @param netIf The local network interface used to send multicast messages
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see MulticastSocket#getNetworkInterface()
+ *
+ * @since 1.4
+ */
+ public void setNetworkInterface(NetworkInterface netIf)
+ throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ InetAddress address;
+ if (netIf != null)
+ out:
+ {
+ Enumeration e = netIf.getInetAddresses();
+ if (getLocalAddress() instanceof Inet4Address)
+ {
+ // Search for a IPv4 address.
+ while (e.hasMoreElements())
+ {
+ address = (InetAddress) e.nextElement();
+ if (address instanceof Inet4Address)
+ break out;
+ }
+ throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
+ }
+ else if (getLocalAddress() instanceof Inet6Address)
+ {
+ // Search for a IPv6 address.
+ while (e.hasMoreElements())
+ {
+ address = (InetAddress) e.nextElement();
+ if (address instanceof Inet6Address)
+ break out;
+ }
+ throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
+ }
+ else
+ throw new SocketException("interface " + netIf.getName() + " has no suitable IP address");
+ }
+ else
+ address = InetAddress.ANY_IF;
+
+
+ getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
+ }
+
+ /**
+ * Gets the local network interface which is used to send multicast messages
+ *
+ * @return The local network interface to send multicast messages
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public NetworkInterface getNetworkInterface() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ InetAddress address =
+ (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
+
+ if (address.isAnyLocalAddress())
+ return NetworkInterface.createAnyInterface();
+
+ NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
+
+ return netIf;
+ }
+
+ /**
+ * Disable/Enable local loopback of multicast packets. The option is used by
+ * the platform's networking code as a hint for setting whether multicast
+ * data will be looped back to the local socket.
+ *
+ * Because this option is a hint, applications that want to verify what
+ * loopback mode is set to should call #getLoopbackMode
+ *
+ * @param disable True to disable loopback mode
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setLoopbackMode(boolean disable) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
+ Boolean.valueOf(disable));
+ }
+
+ /**
+ * Checks if local loopback mode is enabled
+ *
+ * @return true if loopback mode is enabled, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getLoopbackMode() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the "Time to Live" value for a socket. The value must be between
+ * 1 and 255.
+ *
+ * @param ttl The new TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
+ *
+ * @see MulticastSocket#setTimeToLive(int ttl)
+ */
+ public void setTTL(byte ttl) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // Use setTTL here rather than setTimeToLive in case we're using an impl
+ // other than the default PlainDatagramSocketImpl and it doesn't have
+ // setTimeToLive yet.
+ getImpl().setTTL(ttl);
+ }
+
+ /**
+ * Sets the "Time to Live" value for a socket. The value must be between
+ * 0 and 255, inclusive.
+ *
+ * @param ttl The new TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public void setTimeToLive(int ttl) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (ttl < 0 || ttl > 255)
+ throw new IllegalArgumentException("Invalid ttl: " + ttl);
+
+ getImpl().setTimeToLive(ttl);
+ }
+
+ /**
+ * Joins the specified multicast group.
+ *
+ * @param mcastaddr The address of the group to join
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ */
+ public void joinGroup(InetAddress mcastaddr) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! mcastaddr.isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(mcastaddr);
+
+ getImpl().join(mcastaddr);
+ }
+
+ /**
+ * Leaves the specified multicast group
+ *
+ * @param mcastaddr The address of the group to leave
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ */
+ public void leaveGroup(InetAddress mcastaddr) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! mcastaddr.isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(mcastaddr);
+
+ getImpl().leave(mcastaddr);
+ }
+
+ /**
+ * Joins the specified mulitcast group on a specified interface.
+ *
+ * @param mcastaddr The multicast address to join
+ * @param netIf The local network interface to receive the multicast
+ * messages on or null to defer the interface set by #setInterface or
+ * #setNetworkInterface
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ *
+ * @see MulticastSocket#setInterface(InetAddress addr)
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (mcastaddr instanceof InetSocketAddress))
+ throw new IllegalArgumentException("SocketAddress type not supported");
+
+ InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
+
+ if (! tmp.getAddress().isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(tmp.getAddress());
+
+ getImpl().joinGroup(mcastaddr, netIf);
+ }
+
+ /**
+ * Leaves the specified mulitcast group on a specified interface.
+ *
+ * @param mcastaddr The multicast address to leave
+ * @param netIf The local networki interface or null to defer to the
+ * interface set by setInterface or setNetworkInterface
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ *
+ * @see MulticastSocket#setInterface(InetAddress addr)
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
+
+ if (! tmp.getAddress().isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(tmp.getAddress());
+
+ getImpl().leaveGroup(mcastaddr, netIf);
+ }
+
+ /**
+ * Sends a packet of data to a multicast address with a TTL that is
+ * different from the default TTL on this socket. The default TTL for
+ * the socket is not changed.
+ *
+ * @param packet The packet of data to send
+ * @param ttl The TTL for this packet
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect or checkMulticast method doesn't allow the operation
+ *
+ * @deprecated
+ */
+ public synchronized void send(DatagramPacket packet, byte ttl)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ {
+ InetAddress addr = packet.getAddress();
+ if (addr.isMulticastAddress())
+ s.checkPermission(new SocketPermission(addr.getHostName()
+ + packet.getPort(),
+ "accept,connect"));
+ else
+ s.checkConnect(addr.getHostAddress(), packet.getPort());
+ }
+
+ int oldttl = getImpl().getTimeToLive();
+ getImpl().setTimeToLive(((int) ttl) & 0xFF);
+ getImpl().send(packet);
+ getImpl().setTimeToLive(oldttl);
+ }
+}
diff --git a/libjava/classpath/java/net/NetPermission.java b/libjava/classpath/java/net/NetPermission.java
new file mode 100644
index 000000000..cabe54e06
--- /dev/null
+++ b/libjava/classpath/java/net/NetPermission.java
@@ -0,0 +1,90 @@
+/* NetPermission.java -- A class for basic miscellaneous network permission
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.security.BasicPermission;
+
+
+/**
+ * This class is used to model miscellaneous network permissions. It is
+ * a subclass of <code>BasicPermission</code>. This means that it models a
+ * "boolean" permission. One that you either have or do not have. Thus
+ * there is no permitted action list associated with this object.
+ *
+ * The following permission names are defined for this class:
+ *
+ * <ul>
+ * <li>setDefaultAuthenticator - Grants the ability to install a facility
+ * to collect username and password information when requested by a
+ * web site or proxy server.</li>
+ * <li>requestPasswordAuthentication - Grants the ability to ask the
+ * authentication facility for the user's password.</li>
+ * <li>specifyStreamHandler - Grants the permission to specify the
+ * stream handler class used when loading from a URL.</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public final class NetPermission extends BasicPermission
+{
+ static final long serialVersionUID = -8343910153355041693L;
+
+ /**
+ * Initializes a new instance of <code>NetPermission</code> with the
+ * specified name.
+ *
+ * @param name The name of this permission.
+ */
+ public NetPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Initializes a new instance of <code>NetPermission</code> with the
+ * specified name and perms. Note that the perms field is irrelevant and is
+ * ignored. This constructor should never need to be used.
+ *
+ * @param name The name of this permission
+ * @param perms The permitted actions of this permission (ignored)
+ */
+ public NetPermission(String name, String perms)
+ {
+ super(name);
+ }
+}
diff --git a/libjava/classpath/java/net/NetworkInterface.java b/libjava/classpath/java/net/NetworkInterface.java
new file mode 100644
index 000000000..127dfba78
--- /dev/null
+++ b/libjava/classpath/java/net/NetworkInterface.java
@@ -0,0 +1,316 @@
+/* NetworkInterface.java --
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.classpath.SystemProperties;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ * This class models a network interface on the host computer. A network
+ * interface contains a name (typically associated with a specific
+ * hardware adapter) and a list of addresses that are bound to it.
+ * For example, an ethernet interface may be named "eth0" and have the
+ * address 192.168.1.101 assigned to it.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ */
+public final class NetworkInterface
+{
+ private final VMNetworkInterface netif;
+
+ private NetworkInterface(VMNetworkInterface netif)
+ {
+ this.netif = netif;
+ }
+
+ /** Creates an NetworkInterface instance which
+ * represents any interface in the system. Its only
+ * address is <code>0.0.0.0/0.0.0.0</code>. This
+ * method is needed by {@link MulticastSocket#getNetworkInterface}
+ */
+ static NetworkInterface createAnyInterface()
+ {
+ return new NetworkInterface(new VMNetworkInterface());
+ }
+
+ /**
+ * Returns the name of the network interface
+ *
+ * @return The name of the interface.
+ */
+ public String getName()
+ {
+ return netif.name;
+ }
+
+ /**
+ * Returns all available addresses of the network interface
+ *
+ * If a @see SecurityManager is available all addresses are checked
+ * with @see SecurityManager::checkConnect() if they are available.
+ * Only <code>InetAddresses</code> are returned where the security manager
+ * doesn't throw an exception.
+ *
+ * @return An enumeration of all addresses.
+ */
+ public Enumeration<InetAddress> getInetAddresses()
+ {
+ SecurityManager s = System.getSecurityManager();
+ Vector<InetAddress> inetAddresses
+ = new Vector<InetAddress>(netif.addresses);
+
+ if (s == null)
+ return inetAddresses.elements();
+
+ Vector<InetAddress> tmpInetAddresses = new Vector<InetAddress>(1, 1);
+
+ for (Enumeration<InetAddress> addresses = inetAddresses.elements();
+ addresses.hasMoreElements();)
+ {
+ InetAddress addr = addresses.nextElement();
+ try
+ {
+ s.checkConnect(addr.getHostAddress(), -1);
+ tmpInetAddresses.add(addr);
+ }
+ catch (SecurityException e)
+ {
+ // Ignore.
+ }
+ }
+
+ return tmpInetAddresses.elements();
+ }
+
+ /**
+ * Returns the display name of the interface
+ *
+ * @return The display name of the interface
+ */
+ public String getDisplayName()
+ {
+ return netif.name;
+ }
+
+ /**
+ * Returns an network interface by name
+ *
+ * @param name The name of the interface to return
+ *
+ * @return a <code>NetworkInterface</code> object representing the interface,
+ * or null if there is no interface with that name.
+ *
+ * @exception SocketException If an error occurs
+ * @exception NullPointerException If the specified name is null
+ */
+ public static NetworkInterface getByName(String name)
+ throws SocketException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
+ {
+ if (netifs[i].name.equals(name))
+ return new NetworkInterface(netifs[i]);
+ }
+ return null;
+ }
+
+ /**
+ * Return a network interface by its address
+ *
+ * @param addr The address of the interface to return
+ *
+ * @return the interface, or <code>null</code> if none found
+ *
+ * @exception SocketException If an error occurs
+ * @exception NullPointerException If the specified addess is null
+ */
+ public static NetworkInterface getByInetAddress(InetAddress addr)
+ throws SocketException
+ {
+ if (addr == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
+ {
+ if (netifs[i].addresses.contains(addr))
+ return new NetworkInterface(netifs[i]);
+ }
+ return null;
+ }
+
+ /**
+ * Return an <code>Enumeration</code> of all available network interfaces
+ *
+ * @return all interfaces
+ *
+ * @exception SocketException If an error occurs
+ */
+ public static Enumeration<NetworkInterface> getNetworkInterfaces()
+ throws SocketException
+ {
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ Vector<NetworkInterface> networkInterfaces =
+ new Vector<NetworkInterface>(netifs.length);
+ for (int i = 0; i < netifs.length; i++)
+ {
+ if (!netifs[i].addresses.isEmpty())
+ networkInterfaces.add(new NetworkInterface(netifs[i]));
+ }
+ return networkInterfaces.elements();
+ }
+
+ /**
+ * Checks if the current instance is equal to obj
+ *
+ * @param obj The object to compare with
+ *
+ * @return <code>true</code> if equal, <code>false</code> otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof NetworkInterface))
+ return false;
+
+ NetworkInterface tmp = (NetworkInterface) obj;
+
+ if (netif.name == null)
+ return tmp.netif.name == null;
+
+ return (netif.name.equals(tmp.netif.name)
+ && (netif.addresses.equals(tmp.netif.addresses)));
+ }
+
+ /**
+ * Returns the hashcode of the current instance
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // FIXME: hash correctly
+ int hc = netif.addresses.hashCode();
+
+ if (netif.name != null)
+ hc += netif.name.hashCode();
+
+ return hc;
+ }
+
+ /**
+ * Returns a string representation of the interface
+ *
+ * @return the string
+ */
+ public String toString()
+ {
+ // FIXME: check if this is correct
+ CPStringBuilder result;
+ String separator = SystemProperties.getProperty("line.separator");
+
+ result = new CPStringBuilder();
+
+ result.append("name: ");
+ result.append(getDisplayName());
+ result.append(" (").append(getName()).append(") addresses:");
+ result.append(separator);
+
+ for (Iterator it = netif.addresses.iterator(); it.hasNext(); )
+ {
+ InetAddress address = (InetAddress) it.next();
+ result.append(address.toString()).append(";").append(separator);
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Determines whether this interface is ready to transfer data.
+ *
+ * @return whether the interface is up
+ */
+ public boolean isUp()
+ throws SocketException
+ {
+ return VMNetworkInterface.isUp(netif.name);
+ }
+
+ /**
+ * Determines whether this interface does point to point
+ * transmission.
+ *
+ * @return whether the interface does point to point transmission
+ */
+ public boolean isPointToPoint()
+ throws SocketException
+ {
+ return VMNetworkInterface.isPointToPoint(netif.name);
+ }
+
+ /**
+ * Determines whether this interface is the loopback interface.
+ *
+ * @return whether the interface is the loopback interface
+ */
+ public boolean isLoopback()
+ throws SocketException
+ {
+ return VMNetworkInterface.isLoopback(netif.name);
+ }
+
+ /**
+ * Determines whether this interface supports multicast transmission.
+ *
+ * @return whether the interface supports multicast transmission.
+ */
+ public boolean supportsMulticast()
+ throws SocketException
+ {
+ return VMNetworkInterface.supportsMulticast(netif.name);
+ }
+
+}
diff --git a/libjava/classpath/java/net/NoRouteToHostException.java b/libjava/classpath/java/net/NoRouteToHostException.java
new file mode 100644
index 000000000..48c3a8e60
--- /dev/null
+++ b/libjava/classpath/java/net/NoRouteToHostException.java
@@ -0,0 +1,74 @@
+/* NoRouteToHostException.java -- Cannot connect to a host
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that there is no TCP/IP route to the requested
+ * host. This is often due to a misconfigured routing table.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NoRouteToHostException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1897550894873493790L;
+
+ /**
+ * Create an instance without a descriptive error message.
+ */
+ public NoRouteToHostException()
+ {
+ }
+
+ /**
+ * Create an instance with a descriptive error message, such as the text
+ * from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public NoRouteToHostException(String message)
+ {
+ super(message);
+ }
+} // class NoRouteToHostException
diff --git a/libjava/classpath/java/net/PasswordAuthentication.java b/libjava/classpath/java/net/PasswordAuthentication.java
new file mode 100644
index 000000000..1d4ec8961
--- /dev/null
+++ b/libjava/classpath/java/net/PasswordAuthentication.java
@@ -0,0 +1,92 @@
+/* PasswordAuthentication.java -- Container class for username/password pairs
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This class serves a container for username/password pairs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @since 1.2
+ */
+public final class PasswordAuthentication
+{
+ /**
+ * The username
+ */
+ private String username;
+
+ /**
+ * The password
+ */
+ private char[] password;
+
+ /**
+ * Creates a new <code>PasswordAuthentication</code> object from the
+ * specified username and password.
+ *
+ * @param username The username for this object
+ * @param password The password for this object
+ */
+ public PasswordAuthentication(String username, char[] password)
+ {
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Returns the username associated with this object
+ *
+ * @return The username
+ */
+ public String getUserName()
+ {
+ return username;
+ }
+
+ /**
+ * Returns the password associated with this object
+ *
+ * @return The password
+ */
+ public char[] getPassword()
+ {
+ return password;
+ }
+}
diff --git a/libjava/classpath/java/net/PortUnreachableException.java b/libjava/classpath/java/net/PortUnreachableException.java
new file mode 100644
index 000000000..49a8c9ea1
--- /dev/null
+++ b/libjava/classpath/java/net/PortUnreachableException.java
@@ -0,0 +1,72 @@
+/* PortUnreachableException.java -- received an ICMP port unreachable datagram
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception signals that an ICMP port unreachable datagram has been
+ * received.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class PortUnreachableException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8462541992376507323L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public PortUnreachableException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public PortUnreachableException(String message)
+ {
+ super(message);
+ }
+} // class PortUnreachableException
diff --git a/libjava/classpath/java/net/ProtocolException.java b/libjava/classpath/java/net/ProtocolException.java
new file mode 100644
index 000000000..27718a979
--- /dev/null
+++ b/libjava/classpath/java/net/ProtocolException.java
@@ -0,0 +1,75 @@
+/* ProtocolException.java -- a low level protocol error occurred
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that some sort of low level protocol
+ * exception occurred. Look in the descriptive message (if any) for
+ * details on what went wrong.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ProtocolException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -6098449442062388080L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public ProtocolException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public ProtocolException(String message)
+ {
+ super(message);
+ }
+} // class ProtocolException
diff --git a/libjava/classpath/java/net/Proxy.java b/libjava/classpath/java/net/Proxy.java
new file mode 100644
index 000000000..36a25fa80
--- /dev/null
+++ b/libjava/classpath/java/net/Proxy.java
@@ -0,0 +1,139 @@
+/* Proxy.java -- Represends a proxy for a network connection
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Defines a proxy setting. This setting contains a type (https, socks,
+ * direct) and a socket address.
+ *
+ * @since 1.5
+ */
+public class Proxy
+{
+ /**
+ * Represents the proxy type.
+ */
+ public enum Type
+ {
+ DIRECT, HTTP, SOCKS;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = -2231209257930100533L;
+ }
+
+ public static final Proxy NO_PROXY = new Proxy(Type.DIRECT, null);
+
+ private Type type;
+ private SocketAddress address;
+
+ /**
+ * Creates a new <code>Proxy</code> object.
+ *
+ * @param type The type for this proxy
+ * @param address The address of this proxy
+ */
+ public Proxy(Type type, SocketAddress address)
+ {
+ this.type = type;
+ this.address = address;
+ }
+
+ /**
+ * Returns the socket address for this proxy object.
+ *
+ * @return the socket address
+ */
+ public SocketAddress address()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the of this proxy instance.
+ *
+ * @return the type
+ *
+ * @see Type
+ */
+ public Type type()
+ {
+ return type;
+ }
+
+ /**
+ * Compares the given object with this object.
+ *
+ * @return <code>true</code> if both objects or equals,
+ * <code>false</code> otherwise.
+ */
+ public final boolean equals(Object obj)
+ {
+ if (! (obj instanceof Proxy))
+ return false;
+
+ Proxy tmp = (Proxy) obj;
+
+ return (type.equals(tmp.type)
+ && (address == null ? tmp.address == null
+ : address.equals(tmp.address)));
+ }
+
+ /**
+ * Returns the hashcode for this <code>Proxy</code> object.
+ *
+ * @return the hashcode
+ */
+ public final int hashCode()
+ {
+ return type.hashCode() ^ (address == null ? 0 : address.hashCode());
+ }
+
+ /**
+ * Returns a string representation of this <code>Proxy</code> object.
+ *
+ * @return the string
+ */
+ public String toString()
+ {
+ return type.toString() + (address == null ? ""
+ : (":" + address.toString()));
+ }
+}
diff --git a/libjava/classpath/java/net/ProxySelector.java b/libjava/classpath/java/net/ProxySelector.java
new file mode 100644
index 000000000..6c85f99c7
--- /dev/null
+++ b/libjava/classpath/java/net/ProxySelector.java
@@ -0,0 +1,117 @@
+/* ProxySelector.java -- A proxy selector class
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.DefaultProxySelector;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Class for handling proxies for different connections.
+ *
+ * @since 1.5
+ */
+public abstract class ProxySelector
+{
+ /**
+ * Default proxy selector.
+ */
+ private static ProxySelector defaultSelector = new DefaultProxySelector();
+
+ /**
+ * Creates a new <code>ProxySelector</code> object.
+ */
+ public ProxySelector()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the default proxy selector.
+ *
+ * @return the default proxy selector
+ *
+ * @throws SecurityException If a security manager is installed and it
+ * denies NetPermission("getProxySelector")
+ */
+ public static ProxySelector getDefault()
+ {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null)
+ sm.checkPermission(new NetPermission("getProxySelector"));
+
+ return defaultSelector;
+ }
+
+ /**
+ * Sets the default proxy selector.
+ *
+ * @param selector the defualt proxy selector
+ *
+ * @throws SecurityException If a security manager is installed and it
+ * denies NetPermission("setProxySelector")
+ */
+ public static void setDefault(ProxySelector selector)
+ {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null)
+ sm.checkPermission(new NetPermission("setProxySelector"));
+
+ defaultSelector = selector;
+ }
+
+ /**
+ * Signals to the selector that a proxy was no available.
+ *
+ * @throws IllegalArgumentException If one argument is null
+ */
+ public abstract void connectFailed(URI uri, SocketAddress address,
+ IOException exception);
+
+ /**
+ * Returns the list of proxy settings for a given URI.
+ *
+ * @return list of proxy settings
+ *
+ * @throws IllegalArgumentException If uri is null
+ */
+ public abstract List<Proxy> select(URI uri);
+}
diff --git a/libjava/classpath/java/net/ResolverCache.java b/libjava/classpath/java/net/ResolverCache.java
new file mode 100644
index 000000000..d7e5ed407
--- /dev/null
+++ b/libjava/classpath/java/net/ResolverCache.java
@@ -0,0 +1,269 @@
+/* ResolverCache.java -- A cache of resolver lookups for InetAddress.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.security.Security;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * This class provides a cache of name service resolutions. By
+ * default successful resolutions are cached forever to guard
+ * against DNS spoofing attacks and failed resolutions are cached
+ * for 10 seconds to improve performance. The length of time that
+ * results remain in the cache is determined by the following
+ * security properties:
+ * <dl>
+ * <dt><code>networkaddress.cache.ttl</code></dt>
+ * <dd>
+ * This property specifies the length of time in seconds that
+ * successful resolutions remain in the cache. The default is
+ * -1, indicating to cache forever.
+ * </dd>
+ * <dt><code>networkaddress.cache.negative.ttl</code></dt>
+ * <dd>
+ * This property specifies the length of time in seconds that
+ * unsuccessful resolutions remain in the cache. The default
+ * is 10, indicating to cache for 10 seconds.
+ * </dd>
+ * In both cases, a value of -1 indicates to cache forever and a
+ * value of 0 indicates not to cache.
+ *
+ * @author Gary Benson (gbenson@redhat.com)
+ */
+class ResolverCache
+{
+ /**
+ * The time in seconds for which successful lookups are cached.
+ */
+ private static final int POSITIVE_TTL =
+ getTTL("networkaddress.cache.ttl", -1);
+
+ /**
+ * The time in seconds for which unsuccessful lookups are cached.
+ */
+ private static final int NEGATIVE_TTL =
+ getTTL("networkaddress.cache.negative.ttl", 10);
+
+ /**
+ * Helper function to set the TTLs.
+ */
+ private static int getTTL(String propName, int defaultValue)
+ {
+ String propValue = Security.getProperty(propName);
+ if (propValue == null)
+ return defaultValue;
+
+ return Integer.parseInt(propValue);
+ }
+
+ /**
+ * The cache itself.
+ */
+ private static HashMap<Object, Entry> cache = new HashMap<Object, Entry>();
+
+ /**
+ * List of entries which may expire.
+ */
+ private static LinkedList<Entry> killqueue = new LinkedList<Entry>();
+
+ /**
+ * Return the hostname for the specified IP address.
+ *
+ * @param addr The IP address as a byte array
+ *
+ * @return The hostname
+ *
+ * @exception UnknownHostException If the reverse lookup fails
+ */
+ public static String getHostByAddr(byte[] addr) throws UnknownHostException
+ {
+ Object key = makeHashableAddress(addr);
+ Entry entry = get(key);
+ if (entry != null)
+ {
+ if (entry.value == null)
+ throw new UnknownHostException();
+ return (String) entry.value;
+ }
+
+ try
+ {
+ String hostname = VMInetAddress.getHostByAddr(addr);
+ put(new Entry(key, hostname));
+ return hostname;
+ }
+ catch (UnknownHostException e)
+ {
+ put(new Entry(key, null));
+ throw e;
+ }
+ }
+
+ /**
+ * Return a list of all IP addresses for the specified hostname.
+ *
+ * @param hostname The hostname
+ *
+ * @return An list of IP addresses as byte arrays
+ *
+ * @exception UnknownHostException If the lookup fails
+ */
+ public static byte[][] getHostByName(String hostname)
+ throws UnknownHostException
+ {
+ Entry entry = get(hostname);
+ if (entry != null)
+ {
+ if (entry.value == null)
+ throw new UnknownHostException();
+ return (byte[][]) entry.value;
+ }
+
+ try
+ {
+ byte[][] addrs = VMInetAddress.getHostByName(hostname);
+ put(new Entry(hostname, addrs));
+ return addrs;
+ }
+ catch (UnknownHostException e)
+ {
+ put(new Entry(hostname, null));
+ throw e;
+ }
+ }
+
+ /**
+ * Convert an IP address expressed as a byte array into something
+ * we can use as a hashtable key.
+ */
+ private static Object makeHashableAddress(byte[] addr)
+ {
+ char[] chars = new char[addr.length];
+ for (int i = 0; i < addr.length; i++)
+ chars[i] = (char) addr[i];
+ return new String(chars);
+ }
+
+ /**
+ * Return the entry in the cache associated with the supplied key,
+ * or <code>null</code> if the cache does not contain an entry
+ * associated with this key.
+ */
+ private static synchronized Entry get(Object key)
+ {
+ reap();
+ return (Entry) cache.get(key);
+ }
+
+ /**
+ * Insert the supplied entry into the cache.
+ */
+ private static synchronized void put(Entry entry)
+ {
+ reap();
+ if (entry.expires != 0)
+ {
+ if (entry.expires != -1)
+ killqueue.add(entry);
+ cache.put(entry.key, entry);
+ }
+ }
+
+ /**
+ * Clear expired entries. This method is not synchronized, so
+ * it must only be called by methods that are.
+ */
+ private static void reap()
+ {
+ if (!killqueue.isEmpty())
+ {
+ long now = System.currentTimeMillis();
+
+ Iterator iter = killqueue.iterator();
+ while (iter.hasNext())
+ {
+ Entry entry = (Entry) iter.next();
+ if (entry.expires > now)
+ break;
+ cache.remove(entry.key);
+ iter.remove();
+ }
+ }
+ }
+
+ /**
+ * An entry in the cache.
+ */
+ private static class Entry
+ {
+ /**
+ * The key by which this entry is referenced.
+ */
+ public final Object key;
+
+ /**
+ * The entry itself. A null value indicates a failed lookup.
+ */
+ public final Object value;
+
+ /**
+ * The time when this cache entry expires. If set to -1 then
+ * this entry will never expire. If set to 0 then this entry
+ * expires immediately and will not be inserted into the cache.
+ */
+ public final long expires;
+
+ /**
+ * Constructor.
+ */
+ public Entry(Object key, Object value)
+ {
+ this.key = key;
+ this.value = value;
+
+ int ttl = value != null ? POSITIVE_TTL : NEGATIVE_TTL;
+ if (ttl < 1)
+ expires = ttl;
+ else
+ expires = System.currentTimeMillis() + ttl * 1000;
+ }
+ }
+}
diff --git a/libjava/classpath/java/net/STATUS b/libjava/classpath/java/net/STATUS
new file mode 100644
index 000000000..25dff963e
--- /dev/null
+++ b/libjava/classpath/java/net/STATUS
@@ -0,0 +1,48 @@
+X ContentHandlerFactory
+X FileNameMap
+X SocketImplFactory
+X URLStreamHandlerFactory
+* Authenticator
+* ContentHandler
++ DatagramPacket
++ DatagramSocket
++ DatagramSocketImpl
++ HttpURLConnection
++ InetAddress
+* JarURLConnection
++ MulticastSocket
+* NetPermission
+* PasswordAuthentication
++ PlainDatagramSocketImpl
++ PlainSocketImpl (internal)
++ ServerSocket
++ Socket
++ SocketImpl
++ SocketInputStream (internal)
++ SocketOptions (internal)
++ SocketOutputStream (internal)
+* SocketPermission
++ URL
+ URLClassLoader
++ URLConnection
+* URLEncoder
++ URLStreamHandler
+X BindException
+X ConnectException
+X MalformedURLException
+X NoRouteToHostException
+X ProtocolException
+X SocketException
+X UnknownHostException
+X UnknownServiceException
+
+---------------
++ Native InetAddress
++ Native SocketImpl
++ Native DatagramSocketImpl
++ Protocol Handler for HTTP
+ Protocol Handler for FTP
++ ContentHandler for text
+ ContentHandler for gif
+ ContentHandler for jpeg
+
diff --git a/libjava/classpath/java/net/ServerSocket.java b/libjava/classpath/java/net/ServerSocket.java
new file mode 100644
index 000000000..1dbd7636c
--- /dev/null
+++ b/libjava/classpath/java/net/ServerSocket.java
@@ -0,0 +1,627 @@
+/* ServerSocket.java -- Class for implementing server side sockets
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.PlainSocketImpl;
+
+import java.io.IOException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.ServerSocketChannel;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented.
+ */
+
+/**
+ * This class models server side sockets. The basic model is that the
+ * server socket is created and bound to some well known port. It then
+ * listens for and accepts connections. At that point the client and
+ * server sockets are ready to communicate with one another utilizing
+ * whatever application layer protocol they desire.
+ *
+ * As with the <code>Socket</code> class, most instance methods of this class
+ * simply redirect their calls to an implementation class.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class ServerSocket
+{
+ /**
+ * This is the user defined SocketImplFactory, if one is supplied
+ */
+ private static SocketImplFactory factory;
+
+ /**
+ * This is the SocketImp object to which most instance methods in this
+ * class are redirected
+ */
+ private SocketImpl impl;
+
+ /**
+ * We need to retain the local address even after the socket is closed.
+ */
+ private InetSocketAddress local;
+ private int port;
+
+ /*
+ * This constructor is only used by java.nio.
+ */
+
+ ServerSocket(PlainSocketImpl impl) throws IOException
+ {
+ if (impl == null)
+ throw new NullPointerException("impl may not be null");
+
+ this.impl = impl;
+ this.impl.create(true);
+ setReuseAddress(true);
+ }
+
+ /*
+ * This method is only used by java.nio.
+ */
+
+ SocketImpl getImpl()
+ {
+ return impl;
+ }
+
+ /**
+ * Constructor that simply sets the implementation.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @specnote This constructor is public since JDK 1.4
+ */
+ public ServerSocket() throws IOException
+ {
+ if (factory != null)
+ impl = factory.createSocketImpl();
+ else
+ impl = new PlainSocketImpl();
+
+ impl.create(true);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to 50.
+ *
+ * @param port The port number to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public ServerSocket(int port) throws IOException
+ {
+ this(port, 50);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to the value passed as
+ * arg2.
+ *
+ * @param port The port number to bind to
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public ServerSocket(int port, int backlog) throws IOException
+ {
+ this(port, backlog, null);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to the value passed as
+ * backlog. The third argument specifies a particular local address to
+ * bind t or null to bind to all local address.
+ *
+ * @param port The port number to bind to
+ * @param backlog The length of the pending connection queue
+ * @param bindAddr The address to bind to, or null to bind to all addresses
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.1
+ */
+ public ServerSocket(int port, int backlog, InetAddress bindAddr)
+ throws IOException
+ {
+ this();
+
+ // bind/listen socket
+ bind(new InetSocketAddress(bindAddr, port), backlog);
+ }
+
+ /**
+ * Binds the server socket to a specified socket address
+ *
+ * @param endpoint The socket address to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress endpoint) throws IOException
+ {
+ bind(endpoint, 50);
+ }
+
+ /**
+ * Binds the server socket to a specified socket address
+ *
+ * @param endpoint The socket address to bind to
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress endpoint, int backlog)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (isBound())
+ throw new SocketException("Already bound");
+
+ InetAddress addr;
+ int port;
+
+ if (endpoint == null)
+ {
+ addr = InetAddress.ANY_IF;
+ port = 0;
+ }
+ else if (! (endpoint instanceof InetSocketAddress))
+ {
+ throw new IllegalArgumentException("Address type not supported");
+ }
+ else
+ {
+ InetSocketAddress tmp = (InetSocketAddress) endpoint;
+ if (tmp.isUnresolved())
+ throw new SocketException("Unresolved address");
+ addr = tmp.getAddress();
+ port = tmp.getPort();
+ }
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkListen(port);
+
+ try
+ {
+ impl.bind(addr, port);
+ impl.listen(backlog);
+ this.port = port;
+ local = new InetSocketAddress(
+ (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR),
+ impl.getLocalPort());
+ }
+ finally
+ {
+ try
+ {
+ if (local == null)
+ close();
+ }
+ catch (IOException _)
+ {
+ }
+ }
+ }
+
+ /**
+ * This method returns the local address to which this socket is bound
+ *
+ * @return The socket's local address
+ */
+ public InetAddress getInetAddress()
+ {
+ if (local == null)
+ return null;
+
+ return local.getAddress();
+ }
+
+ /**
+ * This method returns the local port number to which this socket is bound
+ *
+ * @return The socket's port number
+ */
+ public int getLocalPort()
+ {
+ if (local == null)
+ return -1;
+
+ return local.getPort();
+ }
+
+ /**
+ * Returns the local socket address
+ *
+ * @return the local socket address, null if not bound
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ return local;
+ }
+
+ /**
+ * Accepts a new connection and returns a connected <code>Socket</code>
+ * instance representing that connection. This method will block until a
+ * connection is available.
+ *
+ * @return socket object for the just accepted connection
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ * @exception SocketTimeoutException If a timeout was previously set with
+ * setSoTimeout and the timeout has been reached
+ */
+ public Socket accept() throws IOException
+ {
+ Socket socket = new Socket();
+
+ try
+ {
+ implAccept(socket);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e2)
+ {
+ // Ignore.
+ }
+
+ throw e;
+ }
+ catch (SecurityException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e2)
+ {
+ // Ignore.
+ }
+
+ throw e;
+ }
+
+ return socket;
+ }
+
+ /**
+ * This protected method is used to help subclasses override
+ * <code>ServerSocket.accept()</code>. The passed in socket will be
+ * connected when this method returns.
+ *
+ * @param socket The socket that is used for the accepted connection
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ *
+ * @since 1.1
+ */
+ protected final void implAccept(Socket socket) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ impl.accept(socket.impl);
+ socket.bound = true;
+ socket.implCreated = true;
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkAccept(socket.getInetAddress().getHostAddress(),
+ socket.getPort());
+ }
+
+ /**
+ * Closes this socket and stops listening for connections
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ if (impl != null)
+ {
+ impl.close();
+ impl = null;
+ }
+ }
+
+ /**
+ * Returns the unique <code>ServerSocketChannel</code> object
+ * associated with this socket, if any.
+ *
+ * <p>The socket only has a <code>ServerSocketChannel</code> if its created
+ * by <code>ServerSocketChannel.open()</code>.</p>
+ *
+ * @return the associated socket channel, null if none exists
+ *
+ * @since 1.4
+ */
+ public ServerSocketChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Returns true when the socket is bound, otherwise false
+ *
+ * @return true if socket is bound, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ return local != null;
+ }
+
+ /**
+ * Returns true if the socket is closed, otherwise false
+ *
+ * @return true if socket is closed, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ ServerSocketChannel channel = getChannel();
+ return impl == null || (channel != null && ! channel.isOpen());
+ }
+
+ /**
+ * Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is
+ * disabled (ie, operations never time out). This is the number of
+ * milliseconds a socket operation can block before an
+ * InterruptedIOException is thrown.
+ *
+ * @param timeout The new SO_TIMEOUT value
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.1
+ */
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
+
+ impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
+ }
+
+ /**
+ * Retrieves the current value of the SO_TIMEOUT setting. A value of 0
+ * implies that SO_TIMEOUT is disabled (ie, operations never time out).
+ * This is the number of milliseconds a socket operation can block before
+ * an InterruptedIOException is thrown.
+ *
+ * @return The value of SO_TIMEOUT
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.1
+ */
+ public int getSoTimeout() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
+
+ if (! (timeout instanceof Integer))
+ throw new IOException("Internal Error");
+
+ return ((Integer) timeout).intValue();
+ }
+
+ /**
+ * Enables/Disables the SO_REUSEADDR option
+ *
+ * @param on true if SO_REUSEADDR should be enabled, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
+ }
+
+ /**
+ * Checks if the SO_REUSEADDR option is enabled
+ *
+ * @return true if SO_REUSEADDR is set, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object reuseaddr = impl.getOption(SocketOptions.SO_REUSEADDR);
+
+ if (! (reuseaddr instanceof Boolean))
+ throw new SocketException("Internal Error");
+
+ return ((Boolean) reuseaddr).booleanValue();
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.4
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
+
+ impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.4
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
+
+ if (! (buf instanceof Integer))
+ throw new SocketException("Internal Error: Unexpected type");
+
+ return ((Integer) buf).intValue();
+ }
+
+ /**
+ * Returns the value of this socket as a <code>String</code>.
+ *
+ * @return This socket represented as a <code>String</code>.
+ */
+ public String toString()
+ {
+ if (! isBound())
+ return "ServerSocket[unbound]";
+
+ return ("ServerSocket[addr=" + getInetAddress() + ",port="
+ + port + ",localport=" + getLocalPort() + "]");
+ }
+
+ /**
+ * Sets the <code>SocketImplFactory</code> for all
+ * <code>ServerSocket</code>'s. This may only be done
+ * once per virtual machine. Subsequent attempts will generate an
+ * exception. Note that a <code>SecurityManager</code> check is made prior
+ * to setting the factory. If insufficient privileges exist to set the
+ * factory, an exception will be thrown
+ *
+ * @param fac the factory to set
+ *
+ * @exception SecurityException If this operation is not allowed by the
+ * <code>SecurityManager</code>.
+ * @exception SocketException If the factory object is already defined
+ * @exception IOException If any other error occurs
+ */
+ public static synchronized void setSocketFactory(SocketImplFactory fac)
+ throws IOException
+ {
+ if (factory != null)
+ throw new SocketException("SocketFactory already defined");
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
+ factory = fac;
+ }
+}
diff --git a/libjava/classpath/java/net/Socket.java b/libjava/classpath/java/net/Socket.java
new file mode 100644
index 000000000..d61e81f5e
--- /dev/null
+++ b/libjava/classpath/java/net/Socket.java
@@ -0,0 +1,1288 @@
+/* Socket.java -- Client socket implementation
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.PlainSocketImpl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented.
+ */
+
+/**
+ * This class models a client site socket. A socket is a TCP/IP endpoint
+ * for network communications conceptually similar to a file handle.
+ * <p>
+ * This class does not actually do any work. Instead, it redirects all of
+ * its calls to a socket implementation object which implements the
+ * <code>SocketImpl</code> interface. The implementation class is
+ * instantiated by factory class that implements the
+ * <code>SocketImplFactory interface</code>. A default
+ * factory is provided, however the factory may be set by a call to
+ * the <code>setSocketImplFactory</code> method. Note that this may only be
+ * done once per virtual machine. If a subsequent attempt is made to set the
+ * factory, a <code>SocketException</code> will be thrown.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class Socket
+{
+ /**
+ * This is the user SocketImplFactory for this class. If this variable is
+ * null, a default factory is used.
+ */
+ static SocketImplFactory factory;
+
+ /**
+ * The implementation object to which calls are redirected
+ */
+ // package-private because ServerSocket.implAccept() needs to access it.
+ SocketImpl impl;
+
+ /**
+ * True if impl.create() has been called.
+ */
+ // package-private because ServerSocket.implAccept() needs to access it.
+ boolean implCreated;
+
+ /**
+ * True if the socket is bound.
+ * Package private so it can be set from ServerSocket when accept is called.
+ */
+ boolean bound;
+
+ /**
+ * True if input is shutdown.
+ */
+ private boolean inputShutdown;
+
+ /**
+ * True if output is shutdown.
+ */
+ private boolean outputShutdown;
+
+ /**
+ * Initializes a new instance of <code>Socket</code> object without
+ * connecting to a remote host. This useful for subclasses of socket that
+ * might want this behavior.
+ *
+ * @specnote This constructor is public since JDK 1.4
+ * @since 1.1
+ */
+ public Socket()
+ {
+ if (factory != null)
+ impl = factory.createSocketImpl();
+ else
+ impl = new PlainSocketImpl();
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> object without
+ * connecting to a remote host. This is useful for subclasses of socket
+ * that might want this behavior.
+ * <p>
+ * Additionally, this socket will be created using the supplied
+ * implementation class instead the default class or one returned by a
+ * factory. If this value is <code>null</code>, the default Socket
+ * implementation is used.
+ *
+ * @param impl The <code>SocketImpl</code> to use for this
+ * <code>Socket</code>
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.1
+ */
+ protected Socket(SocketImpl impl) throws SocketException
+ {
+ if (impl == null)
+ this.impl = new PlainSocketImpl();
+ else
+ this.impl = impl;
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * hostname and port specified as arguments.
+ *
+ * @param host The name of the host to connect to
+ * @param port The port number to connect to
+ *
+ * @exception UnknownHostException If the hostname cannot be resolved to a
+ * network address.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public Socket(String host, int port)
+ throws UnknownHostException, IOException
+ {
+ this(InetAddress.getByName(host), port, null, 0, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments.
+ *
+ * @param address The address to connect to
+ * @param port The port number to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public Socket(InetAddress address, int port) throws IOException
+ {
+ this(address, port, null, 0, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> that connects to the
+ * named host on the specified port and binds to the specified local address
+ * and port.
+ *
+ * @param host The name of the remote host to connect to.
+ * @param port The remote port to connect to.
+ * @param localAddr The local address to bind to.
+ * @param localPort The local port to bind to.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code>
+ * exists and does not allow a connection to the specified host/port or
+ * binding to the specified local host/port.
+ * @exception IOException If a connection error occurs.
+ *
+ * @since 1.1
+ */
+ public Socket(String host, int port, InetAddress localAddr, int localPort)
+ throws IOException
+ {
+ this(InetAddress.getByName(host), port, localAddr, localPort, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments, plus binds to the
+ * specified local address and port.
+ *
+ * @param address The remote address to connect to
+ * @param port The remote port to connect to
+ * @param localAddr The local address to connect to
+ * @param localPort The local port to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @since 1.1
+ */
+ public Socket(InetAddress address, int port, InetAddress localAddr,
+ int localPort) throws IOException
+ {
+ this(address, port, localAddr, localPort, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * hostname and port specified as arguments. If the stream argument is set
+ * to <code>true</code>, then a stream socket is created. If it is
+ * <code>false</code>, a datagram socket is created.
+ *
+ * @param host The name of the host to connect to
+ * @param port The port to connect to
+ * @param stream <code>true</code> for a stream socket, <code>false</code>
+ * for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @deprecated Use the <code>DatagramSocket</code> class to create
+ * datagram oriented sockets.
+ */
+ public Socket(String host, int port, boolean stream)
+ throws IOException
+ {
+ this(InetAddress.getByName(host), port, null, 0, stream);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments. If the stream param is
+ * <code>true</code>, a stream socket will be created, otherwise a datagram
+ * socket is created.
+ *
+ * @param host The address to connect to
+ * @param port The port number to connect to
+ * @param stream <code>true</code> to create a stream socket,
+ * <code>false</code> to create a datagram socket.
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @deprecated Use the <code>DatagramSocket</code> class to create
+ * datagram oriented sockets.
+ */
+ public Socket(InetAddress host, int port, boolean stream)
+ throws IOException
+ {
+ this(host, port, null, 0, stream);
+ }
+
+ /**
+ * This constructor is where the real work takes place. Connect to the
+ * specified address and port. Use default local values if not specified,
+ * otherwise use the local host and port passed in. Create as stream or
+ * datagram based on "stream" argument.
+ * <p>
+ *
+ * @param raddr The remote address to connect to
+ * @param rport The remote port to connect to
+ * @param laddr The local address to connect to
+ * @param lport The local port to connect to
+ * @param stream true for a stream socket, false for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
+ boolean stream) throws IOException
+ {
+ this();
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(raddr.getHostAddress(), rport);
+
+ // bind socket
+ SocketAddress bindaddr =
+ laddr == null ? null : new InetSocketAddress(laddr, lport);
+ bind(bindaddr);
+
+ // Connect socket in case of Exceptions we must close the socket
+ // because an exception in the constructor means that the caller will
+ // not have a reference to this instance.
+ // Note: You may have the idea that the exception treatment
+ // should be moved into connect() but there is a Mauve test which
+ // shows that a failed connect should not close the socket.
+ try
+ {
+ connect(new InetSocketAddress(raddr, rport));
+ }
+ catch (IOException ioe)
+ {
+ impl.close();
+ throw ioe;
+ }
+ catch (RuntimeException re)
+ {
+ impl.close();
+ throw re;
+ }
+
+ // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
+ // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
+ // that default. JDK 1.2 doc infers not to do a bind.
+ }
+
+ private SocketImpl getImpl() throws SocketException
+ {
+ if (! implCreated)
+ {
+ try
+ {
+ impl.create(true);
+ }
+ catch (IOException x)
+ {
+ throw (SocketException) new SocketException().initCause(x);
+ }
+ implCreated = true;
+ }
+ return impl;
+ }
+
+ /**
+ * Binds the socket to the given local address/port
+ *
+ * @param bindpoint The address/port to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ * @exception IllegalArgumentException If the address type is not supported
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress bindpoint) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
+ // socket will be bound to an ephemeral port and a valid local address.
+ if (bindpoint == null)
+ bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
+
+ if (! (bindpoint instanceof InetSocketAddress))
+ throw new IllegalArgumentException();
+
+ InetSocketAddress tmp = (InetSocketAddress) bindpoint;
+
+ // bind to address/port
+ try
+ {
+ getImpl().bind(tmp.getAddress(), tmp.getPort());
+ bound = true;
+ }
+ catch (IOException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ close();
+ throw error;
+ }
+ }
+
+ /**
+ * Connects the socket with a remote address.
+ *
+ * @param endpoint The address to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If the addess type is not supported
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress endpoint) throws IOException
+ {
+ connect(endpoint, 0);
+ }
+
+ /**
+ * Connects the socket with a remote address. A timeout of zero is
+ * interpreted as an infinite timeout. The connection will then block
+ * until established or an error occurs.
+ *
+ * @param endpoint The address to connect to
+ * @param timeout The length of the timeout in milliseconds, or
+ * 0 to indicate no timeout.
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If the address type is not supported
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ * @exception SocketTimeoutException If the timeout is reached
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress endpoint, int timeout)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (endpoint instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ if (! isBound())
+ bind(null);
+
+ getImpl().connect(endpoint, timeout);
+ }
+
+ /**
+ * Returns the address of the remote end of the socket. If this socket
+ * is not connected, then <code>null</code> is returned.
+ *
+ * @return The remote address this socket is connected to
+ */
+ public InetAddress getInetAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ try
+ {
+ return getImpl().getInetAddress();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the local address to which this socket is bound. If this socket
+ * is not connected, then a wildcard address, for which
+ * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
+ *
+ * @return The local address
+ *
+ * @since 1.1
+ */
+ public InetAddress getLocalAddress()
+ {
+ if (! isBound())
+ return InetAddress.ANY_IF;
+
+ InetAddress addr = null;
+
+ if (impl instanceof PlainSocketImpl)
+ addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();
+
+ if (addr == null)
+ {
+ try
+ {
+ addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+ }
+ catch (SocketException e)
+ {
+ // (hopefully) shouldn't happen
+ // throw new java.lang.InternalError
+ // ("Error in PlainSocketImpl.getOption");
+ return null;
+ }
+ }
+
+ // FIXME: According to libgcj, checkConnect() is supposed to be called
+ // before performing this operation. Problems: 1) We don't have the
+ // addr until after we do it, so we do a post check. 2). The docs I
+ // see don't require this in the Socket case, only DatagramSocket, but
+ // we'll assume they mean both.
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(addr.getHostName(), getLocalPort());
+
+ return addr;
+ }
+
+ /**
+ * Returns the port number of the remote end of the socket connection. If
+ * this socket is not connected, then 0 is returned.
+ *
+ * @return The remote port this socket is connected to
+ */
+ public int getPort()
+ {
+ if (! isConnected())
+ return 0;
+
+ try
+ {
+ return getImpl().getPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns the local port number to which this socket is bound. If this
+ * socket is not connected, then -1 is returned.
+ *
+ * @return The local port
+ */
+ public int getLocalPort()
+ {
+ if (! isBound())
+ return -1;
+
+ try
+ {
+ if (getImpl() != null)
+ return getImpl().getLocalPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns local socket address.
+ *
+ * @return the local socket address, null if not bound
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (! isBound())
+ return null;
+
+ InetAddress addr = getLocalAddress();
+
+ try
+ {
+ return new InetSocketAddress(addr, getImpl().getLocalPort());
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return null;
+ }
+ }
+
+ /**
+ * Returns the remote socket address.
+ *
+ * @return the remote socket address, null of not connected
+ *
+ * @since 1.4
+ */
+ public SocketAddress getRemoteSocketAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ try
+ {
+ return new InetSocketAddress(getImpl().getInetAddress(),
+ getImpl().getPort());
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ return null;
+ }
+ }
+
+ /**
+ * Returns an InputStream for reading from this socket.
+ *
+ * @return The InputStream object
+ *
+ * @exception IOException If an error occurs or Socket is not connected
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! isConnected())
+ throw new IOException("not connected");
+
+ return getImpl().getInputStream();
+ }
+
+ /**
+ * Returns an OutputStream for writing to this socket.
+ *
+ * @return The OutputStream object
+ *
+ * @exception IOException If an error occurs or Socket is not connected
+ */
+ public OutputStream getOutputStream() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! isConnected())
+ throw new IOException("not connected");
+
+ return getImpl().getOutputStream();
+ }
+
+ /**
+ * Sets the TCP_NODELAY option on the socket.
+ *
+ * @param on true to enable, false to disable
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.1
+ */
+ public void setTcpNoDelay(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
+ }
+
+ /**
+ * Tests whether or not the TCP_NODELAY option is set on the socket.
+ * Returns true if enabled, false if disabled. When on it disables the
+ * Nagle algorithm which means that packets are always send immediatly and
+ * never merged together to reduce network trafic.
+ *
+ * @return Whether or not TCP_NODELAY is set
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
+
+ if (on instanceof Boolean)
+ return (((Boolean) on).booleanValue());
+ else
+ throw new SocketException("Internal Error");
+ }
+
+ /**
+ * Sets the value of the SO_LINGER option on the socket. If the
+ * SO_LINGER option is set on a socket and there is still data waiting to
+ * be sent when the socket is closed, then the close operation will block
+ * until either that data is delivered or until the timeout period
+ * expires. The linger interval is specified in hundreths of a second
+ * (platform specific?)
+ *
+ * @param on true to enable SO_LINGER, false to disable
+ * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
+ * SO_LINGER not set.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ * @exception IllegalArgumentException If linger is negative
+ *
+ * @since 1.1
+ */
+ public void setSoLinger(boolean on, int linger) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (on)
+ {
+ if (linger < 0)
+ throw new IllegalArgumentException("SO_LINGER must be >= 0");
+
+ if (linger > 65535)
+ linger = 65535;
+
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
+ }
+ else
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
+ }
+
+ /**
+ * Returns the value of the SO_LINGER option on the socket. If the
+ * SO_LINGER option is set on a socket and there is still data waiting to
+ * be sent when the socket is closed, then the close operation will block
+ * until either that data is delivered or until the timeout period
+ * expires. This method either returns the timeouts (in hundredths of
+ * of a second (platform specific?)) if SO_LINGER is set, or -1 if
+ * SO_LINGER is not set.
+ *
+ * @return The SO_LINGER timeout in hundreths of a second or -1
+ * if SO_LINGER not set
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.1
+ */
+ public int getSoLinger() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
+
+ if (linger instanceof Integer)
+ return (((Integer) linger).intValue());
+ else
+ return -1;
+ }
+
+ /**
+ * Sends urgent data through the socket
+ *
+ * @param data The data to send.
+ * Only the lowest eight bits of data are sent
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void sendUrgentData(int data) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().sendUrgentData(data);
+ }
+
+ /**
+ * Enables/disables the SO_OOBINLINE option
+ *
+ * @param on True if SO_OOBLINE should be enabled
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setOOBInline(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
+ }
+
+ /**
+ * Returns the current setting of the SO_OOBINLINE option for this socket
+ *
+ * @return True if SO_OOBINLINE is set, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getOOBInline() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
+
+ if (buf instanceof Boolean)
+ return (((Boolean) buf).booleanValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * Sets the value of the SO_TIMEOUT option on the socket. If this value
+ * is set, and an read/write is performed that does not complete within
+ * the timeout period, a short count is returned (or an EWOULDBLOCK signal
+ * would be sent in Unix if no data had been read). A value of 0 for
+ * this option implies that there is no timeout (ie, operations will
+ * block forever). On systems that have separate read and write timeout
+ * values, this method returns the read timeout. This
+ * value is in milliseconds.
+ *
+ * @param timeout The length of the timeout in milliseconds, or
+ * 0 to indicate no timeout.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public synchronized void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
+
+ getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
+ }
+
+ /**
+ * Returns the value of the SO_TIMEOUT option on the socket. If this value
+ * is set, and an read/write is performed that does not complete within
+ * the timeout period, a short count is returned (or an EWOULDBLOCK signal
+ * would be sent in Unix if no data had been read). A value of 0 for
+ * this option implies that there is no timeout (ie, operations will
+ * block forever). On systems that have separate read and write timeout
+ * values, this method returns the read timeout. This
+ * value is in thousandths of a second (implementation specific?).
+ *
+ * @return The length of the timeout in thousandth's of a second or 0
+ * if not set
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public synchronized int getSoTimeout() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
+ if (timeout instanceof Integer)
+ return (((Integer) timeout).intValue());
+ else
+ return 0;
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_SNDBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new send buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.2
+ */
+ public void setSendBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
+
+ getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_SNDBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The send buffer size.
+ *
+ * @exception SocketException If an error occurs or socket not connected
+ *
+ * @since 1.2
+ */
+ public int getSendBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
+
+ if (buf instanceof Integer)
+ return (((Integer) buf).intValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.2
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
+
+ getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.2
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
+
+ if (buf instanceof Integer)
+ return (((Integer) buf).intValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * This method sets the value for the socket level socket option
+ * SO_KEEPALIVE.
+ *
+ * @param on True if SO_KEEPALIVE should be enabled
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.3
+ */
+ public void setKeepAlive(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
+ }
+
+ /**
+ * This method returns the value of the socket level socket option
+ * SO_KEEPALIVE.
+ *
+ * @return The setting
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.3
+ */
+ public boolean getKeepAlive() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
+
+ if (buf instanceof Boolean)
+ return (((Boolean) buf).booleanValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * Closes the socket.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void close() throws IOException
+ {
+ if (isClosed())
+ return;
+
+ impl.close();
+ impl = null;
+ }
+
+ /**
+ * Converts this <code>Socket</code> to a <code>String</code>.
+ *
+ * @return The <code>String</code> representation of this <code>Socket</code>
+ */
+ public String toString()
+ {
+ try
+ {
+ if (isConnected())
+ return (super.toString()
+ + " [addr=" + getImpl().getInetAddress() + ",port="
+ + getImpl().getPort() + ",localport="
+ + getImpl().getLocalPort() + "]");
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return super.toString() + " [unconnected]";
+ }
+
+ /**
+ * Sets the <code>SocketImplFactory</code>. This may be done only once per
+ * virtual machine. Subsequent attempts will generate a
+ * <code>SocketException</code>. Note that a <code>SecurityManager</code>
+ * check is made prior to setting the factory. If
+ * insufficient privileges exist to set the factory, then an
+ * <code>IOException</code> will be thrown.
+ *
+ * @param fac the factory to set
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> does
+ * not allow this operation.
+ * @exception SocketException If the SocketImplFactory is already defined
+ * @exception IOException If any other error occurs
+ */
+ public static synchronized void setSocketImplFactory(SocketImplFactory fac)
+ throws IOException
+ {
+ // See if already set
+ if (factory != null)
+ throw new SocketException("SocketImplFactory already defined");
+
+ // Check permissions
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
+ if (fac == null)
+ throw new SocketException("SocketImplFactory cannot be null");
+
+ factory = fac;
+ }
+
+ /**
+ * Closes the input side of the socket stream.
+ *
+ * @exception IOException If an error occurs.
+ *
+ * @since 1.3
+ */
+ public void shutdownInput() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().shutdownInput();
+ inputShutdown = true;
+ }
+
+ /**
+ * Closes the output side of the socket stream.
+ *
+ * @exception IOException If an error occurs.
+ *
+ * @since 1.3
+ */
+ public void shutdownOutput() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().shutdownOutput();
+ outputShutdown = true;
+ }
+
+ /**
+ * Returns the socket channel associated with this socket.
+ *
+ * @return the associated socket channel,
+ * null if no associated channel exists
+ *
+ * @since 1.4
+ */
+ public SocketChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Checks if the SO_REUSEADDR option is enabled
+ *
+ * @return True if SO_REUSEADDR is set, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
+
+ if (! (reuseaddr instanceof Boolean))
+ throw new SocketException("Internal Error");
+
+ return ((Boolean) reuseaddr).booleanValue();
+ }
+
+ /**
+ * Enables/Disables the SO_REUSEADDR option
+ *
+ * @param reuseAddress true if SO_REUSEADDR should be enabled,
+ * false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean reuseAddress) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_REUSEADDR,
+ Boolean.valueOf(reuseAddress));
+ }
+
+ /**
+ * Returns the current traffic class
+ *
+ * @return The current traffic class.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see Socket#setTrafficClass(int tc)
+ *
+ * @since 1.4
+ */
+ public int getTrafficClass() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object obj = getImpl().getOption(SocketOptions.IP_TOS);
+
+ if (obj instanceof Integer)
+ return ((Integer) obj).intValue();
+ else
+ throw new SocketException("Unexpected type");
+ }
+
+ /**
+ * Sets the traffic class value
+ *
+ * @param tc The traffic class
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If tc value is illegal
+ *
+ * @see Socket#getTrafficClass()
+ *
+ * @since 1.4
+ */
+ public void setTrafficClass(int tc) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (tc < 0 || tc > 255)
+ throw new IllegalArgumentException();
+
+ getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
+ }
+
+ /**
+ * Checks if the socket is connected
+ *
+ * @return True if socket is connected, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isConnected()
+ {
+ if (impl == null)
+ return false;
+
+ return impl.getInetAddress() != null;
+ }
+
+ /**
+ * Checks if the socket is already bound.
+ *
+ * @return True if socket is bound, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ if (isClosed())
+ return false;
+ if (impl instanceof PlainSocketImpl)
+ {
+ InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress();
+ return addr != null && addr.getAddress() != null;
+ }
+ return bound;
+ }
+
+ /**
+ * Checks if the socket is closed.
+ *
+ * @return True if socket is closed, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ SocketChannel channel = getChannel();
+
+ return impl == null || (channel != null && ! channel.isOpen());
+ }
+
+ /**
+ * Checks if the socket's input stream is shutdown
+ *
+ * @return True if input is shut down.
+ *
+ * @since 1.4
+ */
+ public boolean isInputShutdown()
+ {
+ return inputShutdown;
+ }
+
+ /**
+ * Checks if the socket's output stream is shutdown
+ *
+ * @return True if output is shut down.
+ *
+ * @since 1.4
+ */
+ public boolean isOutputShutdown()
+ {
+ return outputShutdown;
+ }
+}
diff --git a/libjava/classpath/java/net/SocketAddress.java b/libjava/classpath/java/net/SocketAddress.java
new file mode 100644
index 000000000..48ab01009
--- /dev/null
+++ b/libjava/classpath/java/net/SocketAddress.java
@@ -0,0 +1,63 @@
+/* SocketAddress.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.Serializable;
+
+
+/**
+ * Abstract base class for InetSocketAddress.
+ * InetSocketAddress is to my knowledge the only derived
+ * class. [Ronald]
+ *
+ * @since 1.4
+ */
+public abstract class SocketAddress implements Serializable
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ static final long serialVersionUID = 5215720748342549866L;
+
+ /**
+ * Initializes the socket address.
+ */
+ public SocketAddress()
+ {
+ }
+}
diff --git a/libjava/classpath/java/net/SocketException.java b/libjava/classpath/java/net/SocketException.java
new file mode 100644
index 000000000..37b2f6fba
--- /dev/null
+++ b/libjava/classpath/java/net/SocketException.java
@@ -0,0 +1,75 @@
+/* SocketException.java -- An exception occurred while performing a socket op
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that a generic error occurred related to an
+ * operation on a socket. Check the descriptive message (if any) for
+ * details on the nature of this error
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ * @status updated to 1.4
+ */
+public class SocketException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5935874303556886934L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public SocketException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public SocketException(String message)
+ {
+ super(message);
+ }
+} // class SocketException
diff --git a/libjava/classpath/java/net/SocketImpl.java b/libjava/classpath/java/net/SocketImpl.java
new file mode 100644
index 000000000..77f470be3
--- /dev/null
+++ b/libjava/classpath/java/net/SocketImpl.java
@@ -0,0 +1,321 @@
+/* SocketImpl.java -- Abstract socket implementation class
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct.
+ */
+
+/**
+ * This abstract class serves as the parent class for socket implementations.
+ * The implementation class serves an intermediary to native routines that
+ * perform system specific socket operations.
+ * <p>
+ * A default implementation is provided by the system, but this can be
+ * changed via installing a <code>SocketImplFactory</code> (through a call
+ * to the static method <code>Socket.setSocketImplFactory</code>). A
+ * subclass of <code>Socket</code> can also pass in a <code>SocketImpl</code>
+ * to the <code>Socket(SocketImpl)</code> constructor to use an
+ * implementation different from the system default without installing
+ * a factory.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public abstract class SocketImpl implements SocketOptions
+{
+ /**
+ * The address of the remote end of the socket connection
+ */
+ protected InetAddress address;
+
+ /**
+ * A FileDescriptor object representing this socket connection.
+ */
+ protected FileDescriptor fd;
+
+ /**
+ * The port number the socket is bound to locally
+ */
+ protected int localport = -1;
+
+ /**
+ * The port number of the remote end of the socket connection
+ */
+ protected int port;
+
+ /**
+ * Default, no-argument constructor for use by subclasses.
+ */
+ public SocketImpl()
+ {
+ }
+
+ /**
+ * Creates a new socket that is not bound to any local address/port and
+ * is not connected to any remote address/port. This will be created as
+ * a stream socket if the stream parameter is true, or a datagram socket
+ * if the stream parameter is false.
+ *
+ * @param stream true for a stream socket, false for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void create(boolean stream) throws IOException;
+
+ /**
+ * Connects to the remote hostname and port specified as arguments.
+ *
+ * @param host The remote hostname to connect to
+ * @param port The remote port to connect to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void connect(String host, int port)
+ throws IOException;
+
+ /**
+ * Connects to the remote address and port specified as arguments.
+ *
+ * @param host The remote address to connect to
+ * @param port The remote port to connect to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void connect(InetAddress host, int port)
+ throws IOException;
+
+ /**
+ * Connects to the socket to the host specified in address. This
+ * method blocks until successful connected or the timeout occurs.
+ * A timeout of zero means no timout.
+ *
+ * @param address Data of remote host
+ * @param timeout time to wait to stop connecting
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void connect(SocketAddress address, int timeout)
+ throws IOException;
+
+ /**
+ * Binds to the specified port on the specified addr. Note that this addr
+ * must represent a local IP address.
+ * <p>
+ * Note that it is unspecified how to bind to all interfaces on the localhost
+ * (INADDR_ANY).
+ *
+ * @param host The address to bind to
+ * @param port The port number to bind to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void bind(InetAddress host, int port)
+ throws IOException;
+
+ /**
+ * Starts listening for connections on a socket. The backlog parameter
+ * is how many pending connections will queue up waiting to be serviced
+ * before being accept'ed. If the queue of pending requests exceeds this
+ * number, additional connections will be refused.
+ *
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void listen(int backlog) throws IOException;
+
+ /**
+ * Accepts a connection on this socket.
+ *
+ * @param s The implementation object for the accepted connection.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void accept(SocketImpl s) throws IOException;
+
+ /**
+ * Returns an <code>InputStream</code> object for reading from this socket.
+ *
+ * @return An <code>InputStream</code> for reading from this socket.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract InputStream getInputStream() throws IOException;
+
+ /**
+ * Returns an <code>OutputStream</code> object for writing to this socket
+ *
+ * @return An <code>OutputStream</code> for writing to this socket.
+ *
+ * @exception IOException If an error occurs.
+ */
+ protected abstract OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Returns the number of bytes that the caller can read from this socket
+ * without blocking.
+ *
+ * @return The number of readable bytes before blocking
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract int available() throws IOException;
+
+ /**
+ * Closes the socket. This will normally cause any resources, such as the
+ * InputStream, OutputStream and associated file descriptors to be freed.
+ * <p>
+ * Note that if the SO_LINGER option is set on this socket, then the
+ * operation could block.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void close() throws IOException;
+
+ /**
+ * Returns the FileDescriptor objects for this socket.
+ *
+ * @return A FileDescriptor for this socket.
+ */
+ protected FileDescriptor getFileDescriptor()
+ {
+ return fd;
+ }
+
+ /**
+ * Returns the remote address this socket is connected to
+ *
+ * @return The remote address
+ */
+ protected InetAddress getInetAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the remote port this socket is connected to
+ *
+ * @return The remote port
+ */
+ protected int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns true or false when this socket supports sending urgent data
+ * or not.
+ *
+ * @return true if the socket implementation supports sending urgent data,
+ * false otherwise
+ *
+ * @since 1.4
+ */
+ protected boolean supportsUrgentData()
+ {
+ // This method has to be overwritten by socket classes that support
+ // sending urgend data.
+ return false;
+ }
+
+ /**
+ * Sends one byte of urgent data to the socket.
+ *
+ * @param data The byte to send, the low eight bits of it
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void sendUrgentData(int data) throws IOException;
+
+ /**
+ * Returns the local port this socket is bound to
+ *
+ * @return The local port
+ */
+ protected int getLocalPort()
+ {
+ return localport;
+ }
+
+ /**
+ * Returns a <code>String</code> representing the remote host and port of
+ * this socket.
+ *
+ * @return A <code>String</code> for this socket.
+ */
+ public String toString()
+ {
+ return "[addr="
+ + ((address == null) ? "0.0.0.0/0.0.0.0" : address.toString())
+ + ",port=" + port + ",localport=" + localport + "]";
+ }
+
+ /**
+ * Shut down the input side of this socket. Subsequent reads will
+ * return end-of-file.
+ *
+ * @exception IOException if an error occurs
+ */
+ protected void shutdownInput() throws IOException
+ {
+ throw new IOException("Not implemented in this socket class");
+ }
+
+ /**
+ * Shut down the output side of this socket. Subsequent writes will
+ * fail with an IOException.
+ *
+ * @exception IOException if an error occurs
+ */
+ protected void shutdownOutput() throws IOException
+ {
+ throw new IOException("Not implemented in this socket class");
+ }
+}
diff --git a/libjava/classpath/java/net/SocketImplFactory.java b/libjava/classpath/java/net/SocketImplFactory.java
new file mode 100644
index 000000000..b7cb10ca6
--- /dev/null
+++ b/libjava/classpath/java/net/SocketImplFactory.java
@@ -0,0 +1,59 @@
+/* SocketImplFactory.java -- Interface to create a SocketImpl object
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface defines one method which returns a <code>SocketImpl</code>
+ * object. This should not be needed by ordinary applications.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public interface SocketImplFactory
+{
+ /**
+ * This method returns an instance of the <code>SocketImpl</code> object
+ *
+ * @return A <code>SocketImpl</code> object
+ */
+ SocketImpl createSocketImpl();
+} // interface SocketImplFactory
diff --git a/libjava/classpath/java/net/SocketOptions.java b/libjava/classpath/java/net/SocketOptions.java
new file mode 100644
index 000000000..659bf750c
--- /dev/null
+++ b/libjava/classpath/java/net/SocketOptions.java
@@ -0,0 +1,166 @@
+/* SocketOptions.java -- Implements options for sockets (duh!)
+ Copyright (C) 1998, 1999, 2000, 2001,
+ 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface is used by <code>SocketImpl</code> and
+ * <code>DatagramSocketImpl</code> to implement options
+ * on sockets.
+ *
+ * @since 1.2
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status should be completely JDK 1.4 compatible
+ */
+public interface SocketOptions
+{
+ /**
+ * Option id for the SO_KEEPALIVE value
+ * @since 1.3
+ */
+ int SO_KEEPALIVE = 0x8;
+
+ /**
+ * Option id for the SO_LINGER value
+ */
+ int SO_LINGER = 0x80; // 128
+
+ /**
+ * Option id for the SO_TIMEOUT value
+ */
+ int SO_TIMEOUT = 0x1006; // 4102
+
+ /**
+ * Retrieve the local address to which the socket is bound.
+ */
+ int SO_BINDADDR = 0x0F; // 15
+
+ /**
+ * Option id for the send buffer size
+ * @since 1.2
+ */
+ int SO_SNDBUF = 0x1001; // 4097
+
+ /**
+ * Option id for the receive buffer size
+ * @since 1.2
+ */
+ int SO_RCVBUF = 0x1002; // 4098
+
+ /**
+ * Sets the SO_REUSEADDR parameter on a socket
+ */
+ int SO_REUSEADDR = 0x04; // 4
+
+ /**
+ * Sets SO_BROADCAST for a socket
+ * @since 1.4
+ */
+ int SO_BROADCAST = 0x20; // 32
+
+ /**
+ * Sets SO_OOBINLINE for a socket
+ * @since 1.4
+ */
+ int SO_OOBINLINE = 0x1003; // 4099
+
+ /**
+ * Option id for the TCP_NODELAY value
+ */
+ int TCP_NODELAY = 0x01; // 1
+
+ /**
+ * Options id for the IP_MULTICAST_IF value
+ */
+ int IP_MULTICAST_IF = 0x10; // 16
+
+ /**
+ * same as above
+ * @since 1.4
+ */
+ int IP_MULTICAST_IF2 = 0x1F; // 31
+
+ /**
+ * This option enables or disables local loopback of multicast datagrams.
+ * @since 1.4
+ */
+ int IP_MULTICAST_LOOP = 0x12; // 18
+
+ /**
+ * This option sets the type-of-service or traffic class field in the
+ * IP header for a TCP or UDP socket.
+ * @since 1.4
+ */
+ int IP_TOS = 0x03; // 3
+
+ /**
+ * Sets the specified option on a socket to the passed in object. For
+ * options that take an integer argument, the passed in object is an
+ * <code>Integer</code>. For options that are set to on or off, the
+ * value passed will be a <code>Boolean</code>. The <code>optionId</code>
+ * parameter is one of the defined constants in this interface.
+ *
+ * @param optionId The identifier of the option
+ * @param val The value to set the option to
+ *
+ * @exception SocketException If an error occurs
+ */
+ void setOption(int optionId, Object val) throws SocketException;
+
+ /**
+ * Returns the current setting of the specified option. The
+ * <code>Object</code> returned will be an <code>Integer</code> for options
+ * that have integer values. For options that are set to on or off, a
+ * <code>Boolean</code> will be returned. The <code>optionId</code>
+ * parameter is one of the defined constants in this interface.
+ *
+ * @param optionId The option identifier
+ *
+ * @return The current value of the option
+ *
+ * @exception SocketException If an error occurs
+ */
+ Object getOption(int optionId) throws SocketException;
+} // interface SocketOptions
diff --git a/libjava/classpath/java/net/SocketPermission.java b/libjava/classpath/java/net/SocketPermission.java
new file mode 100644
index 000000000..ce16a79a0
--- /dev/null
+++ b/libjava/classpath/java/net/SocketPermission.java
@@ -0,0 +1,636 @@
+/* SocketPermission.java -- Class modeling permissions for socket operations
+ Copyright (C) 1998, 2000, 2001, 2002, 2004, 2006 Free Software
+ Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.StringTokenizer;
+
+
+/**
+ * This class models a specific set of permssions for connecting to a
+ * host. There are two elements to this, the host/port combination and
+ * the permission list.
+ * <p>
+ * The host/port combination is specified as followed
+ * <p>
+ * <pre>
+ * hostname[:[-]port[-[port]]]
+ * </pre>
+ * <p>
+ * The hostname portion can be either a hostname or IP address. If it is
+ * a hostname, a wildcard is allowed in hostnames. This wildcard is a "*"
+ * and matches one or more characters. Only one "*" may appear in the
+ * host and it must be the leftmost character. For example,
+ * "*.urbanophile.com" matches all hosts in the "urbanophile.com" domain.
+ * <p>
+ * The port portion can be either a single value, or a range of values
+ * treated as inclusive. The first or the last port value in the range
+ * can be omitted in which case either the minimum or maximum legal
+ * value for a port (respectively) is used by default. Here are some
+ * examples:
+ * <p><ul>
+ * <li>8080 - Represents port 8080 only</li>
+ * <li>2000-3000 - Represents ports 2000 through 3000 inclusive</li>
+ * <li>-4000 - Represents ports 0 through 4000 inclusive</li>
+ * <li>1024- - Represents ports 1024 through 65535 inclusive</li>
+ * </ul><p>
+ * The permission list is a comma separated list of individual permissions.
+ * These individual permissions are:
+ * <p>
+ * <pre>
+ * accept
+ * connect
+ * listen
+ * resolve
+ * </pre>
+ * <p>
+ * The "listen" permission is only relevant if the host is localhost. If
+ * any permission at all is specified, then resolve permission is implied to
+ * exist.
+ * <p>
+ * Here are a variety of examples of how to create SocketPermission's
+ * <p><pre>
+ * SocketPermission("www.urbanophile.com", "connect");
+ * Can connect to any port on www.urbanophile.com
+ * SocketPermission("www.urbanophile.com:80", "connect,accept");
+ * Can connect to or accept connections from www.urbanophile.com on port 80
+ * SocketPermission("localhost:1024-", "listen,accept,connect");
+ * Can connect to, accept from, an listen on any local port number 1024
+ * and up.
+ * SocketPermission("*.edu", "connect");
+ * Can connect to any host in the edu domain
+ * SocketPermission("197.197.20.1", "accept");
+ * Can accept connections from 197.197.20.1
+ * </pre><p>
+ *
+ * This class also supports IPv6 addresses. These should be specified
+ * in either RFC 2732 format or in full uncompressed form.
+ *
+ * @since 1.2
+ *
+ * @author Written by Aaron M. Renn (arenn@urbanophile.com)
+ * @author Extensively modified by Gary Benson (gbenson@redhat.com)
+ */
+public final class SocketPermission extends Permission implements Serializable
+{
+ static final long serialVersionUID = -7204263841984476862L;
+
+ /**
+ * A hostname (possibly wildcarded). Will be set if and only if
+ * this object was initialized with a hostname.
+ */
+ private transient String hostname = null;
+
+ /**
+ * An IP address (IPv4 or IPv6). Will be set if and only if this
+ * object was initialized with a single literal IP address.
+ */
+ private transient InetAddress address = null;
+
+ /**
+ * A range of ports.
+ */
+ private transient int minport;
+ private transient int maxport;
+
+ /**
+ * Values used for minimum and maximum ports when one or both bounds
+ * are omitted. This class is essentially independent of the
+ * networking code it describes, so we do not limit ports to the
+ * usual network limits of 1 and 65535.
+ */
+ private static final int MIN_PORT = 0;
+ private static final int MAX_PORT = Integer.MAX_VALUE;
+
+ /**
+ * The actions for which we have permission. This field is present
+ * to make the serialized form correct and should not be used by
+ * anything other than writeObject: everything else should use
+ * actionmask.
+ */
+ private String actions;
+
+ /**
+ * A bitmask representing the actions for which we have permission.
+ */
+ private transient int actionmask;
+
+ /**
+ * The available actions, in the canonical order required for getActions().
+ */
+ private static final String[] ACTIONS = new String[] {
+ "connect", "listen", "accept", "resolve"};
+
+ /**
+ * Initializes a new instance of <code>SocketPermission</code> with the
+ * specified host/port combination and actions string.
+ *
+ * @param hostport The hostname/port number combination
+ * @param actions The actions string
+ */
+ public SocketPermission(String hostport, String actions)
+ {
+ super(processHostport(hostport));
+
+ setHostPort(getName());
+ setActions(actions);
+ }
+
+ /**
+ * There are two cases in which hostport needs rewriting before
+ * being passed to the superclass constructor. If hostport is an
+ * empty string then it is substituted with "localhost". And if
+ * the host part of hostport is a literal IPv6 address in the full
+ * uncompressed form not enclosed with "[" and "]" then we enclose
+ * it with them.
+ */
+ private static String processHostport(String hostport)
+ {
+ if (hostport.length() == 0)
+ return "localhost";
+
+ if (hostport.charAt(0) == '[')
+ return hostport;
+
+ int colons = 0;
+ boolean colon_allowed = true;
+ for (int i = 0; i < hostport.length(); i++)
+ {
+ if (hostport.charAt(i) == ':')
+ {
+ if (!colon_allowed)
+ throw new IllegalArgumentException("Ambiguous hostport part");
+ colons++;
+ colon_allowed = false;
+ }
+ else
+ colon_allowed = true;
+ }
+
+ switch (colons)
+ {
+ case 0:
+ case 1:
+ // a hostname or IPv4 address
+ return hostport;
+
+ case 7:
+ // an IPv6 address with no ports
+ return "[" + hostport + "]";
+
+ case 8:
+ // an IPv6 address with ports
+ int last_colon = hostport.lastIndexOf(':');
+ return "[" + hostport.substring(0, last_colon) + "]"
+ + hostport.substring(last_colon);
+
+ default:
+ throw new IllegalArgumentException("Ambiguous hostport part");
+ }
+ }
+
+ /**
+ * Parse the hostport argument to the constructor.
+ */
+ private void setHostPort(String hostport)
+ {
+ // Split into host and ports
+ String host, ports;
+ if (hostport.charAt(0) == '[')
+ {
+ // host is a bracketed IPv6 address
+ int end = hostport.indexOf("]");
+ if (end == -1)
+ throw new IllegalArgumentException("Unmatched '['");
+ host = hostport.substring(1, end);
+
+ address = InetAddress.getByLiteral(host);
+ if (address == null)
+ throw new IllegalArgumentException("Bad IPv6 address");
+
+ if (end == hostport.length() - 1)
+ ports = "";
+ else if (hostport.charAt(end + 1) == ':')
+ ports = hostport.substring(end + 2);
+ else
+ throw new IllegalArgumentException("Bad character after ']'");
+ }
+ else
+ {
+ // host is a hostname or IPv4 address
+ int sep = hostport.indexOf(":");
+ if (sep == -1)
+ {
+ host = hostport;
+ ports = "";
+ }
+ else
+ {
+ host = hostport.substring(0, sep);
+ ports = hostport.substring(sep + 1);
+ }
+
+ address = InetAddress.getByLiteral(host);
+ if (address == null)
+ {
+ if (host.lastIndexOf('*') > 0)
+ throw new IllegalArgumentException("Bad hostname");
+
+ hostname = host;
+ }
+ }
+
+ // Parse and validate the ports
+ if (ports.length() == 0)
+ {
+ minport = MIN_PORT;
+ maxport = MAX_PORT;
+ }
+ else
+ {
+ int sep = ports.indexOf("-");
+ if (sep == -1)
+ {
+ // a single port
+ minport = maxport = Integer.parseInt(ports);
+ }
+ else
+ {
+ if (ports.indexOf("-", sep + 1) != -1)
+ throw new IllegalArgumentException("Unexpected '-'");
+
+ if (sep == 0)
+ {
+ // an upper bound
+ minport = MIN_PORT;
+ maxport = Integer.parseInt(ports.substring(1));
+ }
+ else if (sep == ports.length() - 1)
+ {
+ // a lower bound
+ minport =
+ Integer.parseInt(ports.substring(0, ports.length() - 1));
+ maxport = MAX_PORT;
+ }
+ else
+ {
+ // a range with two bounds
+ minport = Integer.parseInt(ports.substring(0, sep));
+ maxport = Integer.parseInt(ports.substring(sep + 1));
+ }
+ }
+ }
+ }
+
+ /**
+ * Parse the actions argument to the constructor.
+ */
+ private void setActions(String actionstring)
+ {
+ actionmask = 0;
+
+ boolean resolve_needed = false;
+ boolean resolve_present = false;
+
+ StringTokenizer t = new StringTokenizer(actionstring, ",");
+ while (t.hasMoreTokens())
+ {
+ String action = t.nextToken();
+ action = action.trim().toLowerCase();
+ setAction(action);
+
+ if (action.equals("resolve"))
+ resolve_present = true;
+ else
+ resolve_needed = true;
+ }
+
+ if (resolve_needed && !resolve_present)
+ setAction("resolve");
+ }
+
+ /**
+ * Parse one element of the actions argument to the constructor.
+ */
+ private void setAction(String action)
+ {
+ for (int i = 0; i < ACTIONS.length; i++)
+ {
+ if (action.equals(ACTIONS[i]))
+ {
+ actionmask |= 1 << i;
+ return;
+ }
+ }
+ throw new IllegalArgumentException("Unknown action " + action);
+ }
+
+ /**
+ * Tests this object for equality against another. This will be true if
+ * and only if the passed object is an instance of
+ * <code>SocketPermission</code> and both its hostname/port combination
+ * and permissions string are identical.
+ *
+ * @param obj The object to test against for equality
+ *
+ * @return <code>true</code> if object is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ SocketPermission p;
+
+ if (obj instanceof SocketPermission)
+ p = (SocketPermission) obj;
+ else
+ return false;
+
+ if (p.actionmask != actionmask ||
+ p.minport != minport ||
+ p.maxport != maxport)
+ return false;
+
+ if (address != null)
+ {
+ if (p.address == null)
+ return false;
+ else
+ return p.address.equals(address);
+ }
+ else
+ {
+ if (p.hostname == null)
+ return false;
+ else
+ return p.hostname.equals(hostname);
+ }
+ }
+
+ /**
+ * Returns a hash code value for this object. Overrides the
+ * <code>Permission.hashCode()</code>.
+ *
+ * @return A hash code
+ */
+ public int hashCode()
+ {
+ int code = actionmask + minport + maxport;
+ if (address != null)
+ code += address.hashCode();
+ else
+ code += hostname.hashCode();
+ return code;
+ }
+
+ /**
+ * Returns the list of permission actions in this object in canonical
+ * order. The canonical order is "connect,listen,accept,resolve"
+ *
+ * @return The permitted action string.
+ */
+ public String getActions()
+ {
+ CPStringBuilder sb = new CPStringBuilder("");
+
+ for (int i = 0; i < ACTIONS.length; i++)
+ {
+ if ((actionmask & (1 << i)) != 0)
+ {
+ if (sb.length() != 0)
+ sb.append(",");
+ sb.append(ACTIONS[i]);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Returns a new <code>PermissionCollection</code> object that can hold
+ * <code>SocketPermission</code>'s.
+ *
+ * @return A new <code>PermissionCollection</code>.
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ // FIXME: Implement
+
+ return null;
+ }
+
+ /**
+ * Returns an array of all IP addresses represented by this object.
+ */
+ private InetAddress[] getAddresses()
+ {
+ if (address != null)
+ return new InetAddress[] {address};
+
+ try
+ {
+ return InetAddress.getAllByName(hostname);
+ }
+ catch (UnknownHostException e)
+ {
+ return new InetAddress[0];
+ }
+ }
+
+ /**
+ * Returns the canonical hostname represented by this object,
+ * or null if this object represents a wildcarded domain.
+ */
+ private String getCanonicalHostName()
+ {
+ if (address != null)
+ return address.internalGetCanonicalHostName();
+ if (hostname.charAt(0) == '*')
+ return null;
+ try
+ {
+ return InetAddress.getByName(hostname).internalGetCanonicalHostName();
+ }
+ catch (UnknownHostException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if the permission object passed it is implied by the
+ * this permission. This will be true if:
+ *
+ * <ul>
+ * <li>The argument is of type <code>SocketPermission</code></li>
+ * <li>The actions list of the argument are in this object's actions</li>
+ * <li>The port range of the argument is within this objects port range</li>
+ * <li>The hostname is equal to or a subset of this objects hostname</li>
+ * </ul>
+ *
+ * <p>The argument's hostname will be a subset of this object's hostname if:</p>
+ *
+ * <ul>
+ * <li>The argument's hostname or IP address is equal to this object's.</li>
+ * <li>The argument's canonical hostname is equal to this object's.</li>
+ * <li>The argument's canonical name matches this domains hostname with
+ * wildcards</li>
+ * </ul>
+ *
+ * @param perm The <code>Permission</code> to check against
+ *
+ * @return <code>true</code> if the <code>Permission</code> is implied by
+ * this object, <code>false</code> otherwise.
+ */
+ public boolean implies(Permission perm)
+ {
+ SocketPermission p;
+
+ // First make sure we are the right object type
+ if (perm instanceof SocketPermission)
+ p = (SocketPermission) perm;
+ else
+ return false;
+
+ // If p was initialised with an empty hostname then we do not
+ // imply it. This is not part of the spec, but it seems necessary.
+ if (p.hostname != null && p.hostname.length() == 0)
+ return false;
+
+ // Next check the actions
+ if ((p.actionmask & actionmask) != p.actionmask)
+ return false;
+
+ // Then check the ports
+ if ((p.minport < minport) || (p.maxport > maxport))
+ return false;
+
+ // Finally check the hosts
+ String p_canon = null;
+
+ // Return true if this object was initialized with a single
+ // IP address which one of p's IP addresses is equal to.
+ if (address != null)
+ {
+ InetAddress[] addrs = p.getAddresses();
+ for (int i = 0; i < addrs.length; i++)
+ {
+ if (address.equals(addrs[i]))
+ return true;
+ }
+ }
+
+ // Return true if this object is a wildcarded domain that
+ // p's canonical name matches.
+ if (hostname != null && hostname.charAt(0) == '*')
+ {
+ p_canon = p.getCanonicalHostName();
+ if (p_canon != null && p_canon.endsWith(hostname.substring(1)))
+ return true;
+
+ }
+
+ // Return true if this one of this object's IP addresses
+ // is equal to one of p's.
+ if (address == null)
+ {
+ InetAddress[] addrs = p.getAddresses();
+ InetAddress[] p_addrs = p.getAddresses();
+
+ for (int i = 0; i < addrs.length; i++)
+ {
+ for (int j = 0; j < p_addrs.length; j++)
+ {
+ if (addrs[i].equals(p_addrs[j]))
+ return true;
+ }
+ }
+ }
+
+ // Return true if this object's canonical name equals p's.
+ String canon = getCanonicalHostName();
+ if (canon != null)
+ {
+ if (p_canon == null)
+ p_canon = p.getCanonicalHostName();
+ if (p_canon != null && canon.equals(p_canon))
+ return true;
+ }
+
+ // Didn't make it
+ return false;
+ }
+
+ /**
+ * Deserializes a <code>SocketPermission</code> object from
+ * an input stream.
+ *
+ * @param input the input stream.
+ * @throws IOException if an I/O error occurs in the stream.
+ * @throws ClassNotFoundException if the class of the
+ * serialized object could not be found.
+ */
+ private void readObject(ObjectInputStream input)
+ throws IOException, ClassNotFoundException
+ {
+ input.defaultReadObject();
+ setHostPort(getName());
+ setActions(actions);
+ }
+
+ /**
+ * Serializes a <code>SocketPermission</code> object to an
+ * output stream.
+ *
+ * @param output the output stream.
+ * @throws IOException if an I/O error occurs in the stream.
+ */
+ private void writeObject(ObjectOutputStream output)
+ throws IOException
+ {
+ actions = getActions();
+ output.defaultWriteObject();
+ }
+}
diff --git a/libjava/classpath/java/net/SocketTimeoutException.java b/libjava/classpath/java/net/SocketTimeoutException.java
new file mode 100644
index 000000000..21b0dcd86
--- /dev/null
+++ b/libjava/classpath/java/net/SocketTimeoutException.java
@@ -0,0 +1,73 @@
+/* SocketTimeoutException.java -- the socket timed out
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.InterruptedIOException;
+
+
+/**
+ * This exception signals that a socket read or accept timed out.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class SocketTimeoutException extends InterruptedIOException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -8846654841826352300L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public SocketTimeoutException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public SocketTimeoutException(String message)
+ {
+ super(message);
+ }
+} // class SocketTimeoutException
diff --git a/libjava/classpath/java/net/TODO b/libjava/classpath/java/net/TODO
new file mode 100644
index 000000000..e48969d3a
--- /dev/null
+++ b/libjava/classpath/java/net/TODO
@@ -0,0 +1,24 @@
+-- DNS cache purging.
+
+-- Implement ContentHandler chaining (non-JDK feature)
+
+-- Implement MIME type by file determination chaining using external
+ disk files. (non-JDK feature)
+
+-- Implement determining MIME type from an InputStream
+
+-- Datagram peek()'s
+
+-- Finalize methods for sockets
+
+-- HTTP - caching (supported by JDK?)
+
+-- HTTP - all protocol support beyond basic GET functionality
+
+-- Fix call to Date(String) in URLConnection.getHeaderFieldDate() when
+ I figure out why DateFormat isn't working.
+
+-- Finish off all JDK 1.2 permissions stuff
+
+-- Write URLClassLoader
+
diff --git a/libjava/classpath/java/net/URI.java b/libjava/classpath/java/net/URI.java
new file mode 100644
index 000000000..b5fb9654f
--- /dev/null
+++ b/libjava/classpath/java/net/URI.java
@@ -0,0 +1,1450 @@
+/* URI.java -- An URI class
+ Copyright (C) 2002, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <p>
+ * A URI instance represents that defined by
+ * <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC3986</a>,
+ * with some deviations.
+ * </p>
+ * <p>
+ * At its highest level, a URI consists of:
+ * </p>
+ * <code>[<em>scheme</em><strong>:</strong>]<em>scheme-specific-part</em>
+ * [<strong>#</strong><em>fragment</em>]</code>
+ * </p>
+ * <p>
+ * where <strong>#</strong> and <strong>:</strong> are literal characters,
+ * and those parts enclosed in square brackets are optional.
+ * </p>
+ * <p>
+ * There are two main types of URI. An <em>opaque</em> URI is one
+ * which just consists of the above three parts, and is not further
+ * defined. An example of such a URI would be <em>mailto:</em> URI.
+ * In contrast, <em>hierarchical</em> URIs give further definition
+ * to the scheme-specific part, so as represent some part of a hierarchical
+ * structure.
+ * </p>
+ * <p>
+ * <code>[<strong>//</strong><em>authority</em>][<em>path</em>]
+ * [<strong>?</strong><em>query</em>]</code>
+ * </p>
+ * <p>
+ * with <strong>/</strong> and <strong>?</strong> being literal characters.
+ * When server-based, the authority section is further subdivided into:
+ * </p>
+ * <p>
+ * <code>[<em>user-info</em><strong>@</strong>]<em>host</em>
+ * [<strong>:</strong><em>port</em>]</code>
+ * </p>
+ * <p>
+ * with <strong>@</strong> and <strong>:</strong> as literal characters.
+ * Authority sections that are not server-based are said to be registry-based.
+ * </p>
+ * <p>
+ * Hierarchical URIs can be either relative or absolute. Absolute URIs
+ * always start with a `<strong>/</strong>', while relative URIs don't
+ * specify a scheme. Opaque URIs are always absolute.
+ * </p>
+ * <p>
+ * Each part of the URI may have one of three states: undefined, empty
+ * or containing some content. The former two of these are represented
+ * by <code>null</code> and the empty string in Java, respectively.
+ * The scheme-specific part may never be undefined. It also follows from
+ * this that the path sub-part may also not be undefined, so as to ensure
+ * the former.
+ * </p>
+ * <h2>Character Escaping and Quoting</h2>
+ * <p>
+ * The characters that can be used within a valid URI are restricted.
+ * There are two main classes of characters which can't be used as is
+ * within the URI:
+ * </p>
+ * <ol>
+ * <li><strong>Characters outside the US-ASCII character set</strong>.
+ * These have to be <strong>escaped</strong> in order to create
+ * an RFC-compliant URI; this means replacing the character with the
+ * appropriate hexadecimal value, preceded by a `%'.</li>
+ * <li><strong>Illegal characters</strong> (e.g. space characters,
+ * control characters) are quoted, which results in them being encoded
+ * in the same way as non-US-ASCII characters.</li>
+ * </ol>
+ * <p>
+ * The set of valid characters differs depending on the section of the URI:
+ * </p>
+ * <ul>
+ * <li><strong>Scheme</strong>: Must be an alphanumeric, `-', `.' or '+'.</li>
+ * <li><strong>Authority</strong>:Composed of the username, host, port, `@'
+ * and `:'.</li>
+ * <li><strong>Username</strong>: Allows unreserved or percent-encoded
+ * characters, sub-delimiters and `:'.</li>
+ * <li><strong>Host</strong>: Allows unreserved or percent-encoded
+ * characters, sub-delimiters and square brackets (`[' and `]') for IPv6
+ * addresses.</li>
+ * <li><strong>Port</strong>: Digits only.</li>
+ * <li><strong>Path</strong>: Allows the path characters and `/'.
+ * <li><strong>Query</strong>: Allows the path characters, `?' and '/'.
+ * <li><strong>Fragment</strong>: Allows the path characters, `?' and '/'.
+ * </ul>
+ * <p>
+ * These definitions reference the following sets of characters:
+ * </p>
+ * <ul>
+ * <li><strong>Unreserved characters</strong>: The alphanumerics plus
+ * `-', `.', `_', and `~'.</li>
+ * <li><strong>Sub-delimiters</strong>: `!', `$', `&', `(', `)', `*',
+ * `+', `,', `;', `=' and the single-quote itself.</li>
+ * <li><strong>Path characters</strong>: Unreserved and percent-encoded
+ * characters and the sub-delimiters along with `@' and `:'.</li>
+ * </ul>
+ * <p>
+ * The constructors and accessor methods allow the use and retrieval of
+ * URI components which contain non-US-ASCII characters directly.
+ * They are only escaped when the <code>toASCIIString()</code> method
+ * is used. In contrast, illegal characters are always quoted, with the
+ * exception of the return values of the non-raw accessors.
+ * </p>
+ *
+ * @author Ito Kazumitsu (ito.kazumitsu@hitachi-cable.co.jp)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public final class URI
+ implements Comparable<URI>, Serializable
+{
+ /**
+ * For serialization compatability.
+ */
+ static final long serialVersionUID = -6052424284110960213L;
+
+ /**
+ * Regular expression for parsing URIs.
+ *
+ * Taken from RFC 2396, Appendix B.
+ * This expression doesn't parse IPv6 addresses.
+ */
+ private static final String URI_REGEXP =
+ "^(([^:/?#]+):)?((//([^/?#]*))?([^?#]*)(\\?([^#]*))?)?(#(.*))?";
+
+ /**
+ * Regular expression for parsing the authority segment.
+ */
+ private static final String AUTHORITY_REGEXP =
+ "(([^?#]*)@)?([^?#:]*)(:([0-9]*))?";
+
+ /**
+ * Valid characters (taken from rfc2396/3986)
+ */
+ private static final String RFC2396_DIGIT = "0123456789";
+ private static final String RFC2396_LOWALPHA = "abcdefghijklmnopqrstuvwxyz";
+ private static final String RFC2396_UPALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String RFC2396_ALPHA =
+ RFC2396_LOWALPHA + RFC2396_UPALPHA;
+ private static final String RFC2396_ALPHANUM = RFC2396_DIGIT + RFC2396_ALPHA;
+ private static final String RFC3986_UNRESERVED = RFC2396_ALPHANUM + "-._~";
+ private static final String RFC3986_SUBDELIMS = "!$&'()*+,;=";
+ private static final String RFC3986_REG_NAME =
+ RFC3986_UNRESERVED + RFC3986_SUBDELIMS + "%";
+ private static final String RFC3986_PCHAR = RFC3986_UNRESERVED +
+ RFC3986_SUBDELIMS + ":@%";
+ private static final String RFC3986_SEGMENT = RFC3986_PCHAR;
+ private static final String RFC3986_PATH_SEGMENTS = RFC3986_SEGMENT + "/";
+ private static final String RFC3986_SSP = RFC3986_PCHAR + "?/";
+ private static final String RFC3986_HOST = RFC3986_REG_NAME + "[]";
+ private static final String RFC3986_USERINFO = RFC3986_REG_NAME + ":";
+
+ /**
+ * Index of scheme component in parsed URI.
+ */
+ private static final int SCHEME_GROUP = 2;
+
+ /**
+ * Index of scheme-specific-part in parsed URI.
+ */
+ private static final int SCHEME_SPEC_PART_GROUP = 3;
+
+ /**
+ * Index of authority component in parsed URI.
+ */
+ private static final int AUTHORITY_GROUP = 5;
+
+ /**
+ * Index of path component in parsed URI.
+ */
+ private static final int PATH_GROUP = 6;
+
+ /**
+ * Index of query component in parsed URI.
+ */
+ private static final int QUERY_GROUP = 8;
+
+ /**
+ * Index of fragment component in parsed URI.
+ */
+ private static final int FRAGMENT_GROUP = 10;
+
+ /**
+ * Index of userinfo component in parsed authority section.
+ */
+ private static final int AUTHORITY_USERINFO_GROUP = 2;
+
+ /**
+ * Index of host component in parsed authority section.
+ */
+ private static final int AUTHORITY_HOST_GROUP = 3;
+
+ /**
+ * Index of port component in parsed authority section.
+ */
+ private static final int AUTHORITY_PORT_GROUP = 5;
+
+ /**
+ * The compiled version of the URI regular expression.
+ */
+ private static final Pattern URI_PATTERN;
+
+ /**
+ * The compiled version of the authority regular expression.
+ */
+ private static final Pattern AUTHORITY_PATTERN;
+
+ /**
+ * The set of valid hexadecimal characters.
+ */
+ private static final String HEX = "0123456789ABCDEF";
+
+ private transient String scheme;
+ private transient String rawSchemeSpecificPart;
+ private transient String schemeSpecificPart;
+ private transient String rawAuthority;
+ private transient String authority;
+ private transient String rawUserInfo;
+ private transient String userInfo;
+ private transient String rawHost;
+ private transient String host;
+ private transient int port = -1;
+ private transient String rawPath;
+ private transient String path;
+ private transient String rawQuery;
+ private transient String query;
+ private transient String rawFragment;
+ private transient String fragment;
+ private String string;
+
+ /**
+ * Static initializer to pre-compile the regular expressions.
+ */
+ static
+ {
+ URI_PATTERN = Pattern.compile(URI_REGEXP);
+ AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEXP);
+ }
+
+ private void readObject(ObjectInputStream is)
+ throws ClassNotFoundException, IOException
+ {
+ this.string = (String) is.readObject();
+ try
+ {
+ parseURI(this.string);
+ }
+ catch (URISyntaxException x)
+ {
+ // Should not happen.
+ throw new RuntimeException(x);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream os) throws IOException
+ {
+ if (string == null)
+ string = toString();
+ os.writeObject(string);
+ }
+
+ /**
+ * <p>
+ * Returns the string content of the specified group of the supplied
+ * matcher. The returned value is modified according to the following:
+ * </p>
+ * <ul>
+ * <li>If the resulting string has a length greater than 0, then
+ * that string is returned.</li>
+ * <li>If a string of zero length, is matched, then the content
+ * of the preceding group is considered. If this is also an empty
+ * string, then <code>null</code> is returned to indicate an undefined
+ * value. Otherwise, the value is truly the empty string and this is
+ * the returned value.</li>
+ * </ul>
+ * <p>
+ * This method is used for matching against all parts of the URI
+ * that may be either undefined or empty (i.e. all those but the
+ * scheme-specific part and the path). In each case, the preceding
+ * group is the content of the original group, along with some
+ * additional distinguishing feature. For example, the preceding
+ * group for the query includes the preceding question mark,
+ * while that of the fragment includes the hash symbol. The presence
+ * of these features enables disambiguation between the two cases
+ * of a completely unspecified value and a simple non-existant value.
+ * The scheme differs in that it will never return an empty string;
+ * the delimiter follows the scheme rather than preceding it, so
+ * it becomes part of the following section. The same is true
+ * of the user information.
+ * </p>
+ *
+ * @param match the matcher, which contains the results of the URI
+ * matched against the URI regular expression.
+ * @return either the matched content, <code>null</code> for undefined
+ * values, or an empty string for a URI part with empty content.
+ */
+ private static String getURIGroup(Matcher match, int group)
+ {
+ String matched = match.group(group);
+ if (matched == null || matched.length() == 0)
+ {
+ String prevMatched = match.group(group -1);
+ if (prevMatched == null || prevMatched.length() == 0)
+ return null;
+ else
+ return "";
+ }
+ return matched;
+ }
+
+ /**
+ * Sets fields of this URI by parsing the given string.
+ *
+ * @param str The string to parse
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ private void parseURI(String str) throws URISyntaxException
+ {
+ Matcher matcher = URI_PATTERN.matcher(str);
+
+ if (matcher.matches())
+ {
+ scheme = getURIGroup(matcher, SCHEME_GROUP);
+ rawSchemeSpecificPart = matcher.group(SCHEME_SPEC_PART_GROUP);
+ schemeSpecificPart = unquote(rawSchemeSpecificPart);
+ if (!isOpaque())
+ {
+ rawAuthority = getURIGroup(matcher, AUTHORITY_GROUP);
+ rawPath = matcher.group(PATH_GROUP);
+ rawQuery = getURIGroup(matcher, QUERY_GROUP);
+ }
+ rawFragment = getURIGroup(matcher, FRAGMENT_GROUP);
+ }
+ else
+ throw new URISyntaxException(str,
+ "doesn't match URI regular expression");
+ parseServerAuthority();
+
+ // We must eagerly unquote the parts, because this is the only time
+ // we may throw an exception.
+ authority = unquote(rawAuthority);
+ userInfo = unquote(rawUserInfo);
+ host = unquote(rawHost);
+ path = unquote(rawPath);
+ query = unquote(rawQuery);
+ fragment = unquote(rawFragment);
+ }
+
+ /**
+ * Unquote "%" + hex quotes characters
+ *
+ * @param str The string to unquote or null.
+ *
+ * @return The unquoted string or null if str was null.
+ *
+ * @exception URISyntaxException If the given string contains invalid
+ * escape sequences.
+ */
+ private static String unquote(String str) throws URISyntaxException
+ {
+ if (str == null)
+ return null;
+ byte[] buf = new byte[str.length()];
+ int pos = 0;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (c == '%')
+ {
+ if (i + 2 >= str.length())
+ throw new URISyntaxException(str, "Invalid quoted character");
+ int hi = Character.digit(str.charAt(++i), 16);
+ int lo = Character.digit(str.charAt(++i), 16);
+ if (lo < 0 || hi < 0)
+ throw new URISyntaxException(str, "Invalid quoted character");
+ buf[pos++] = (byte) (hi * 16 + lo);
+ }
+ else
+ buf[pos++] = (byte) c;
+ }
+ try
+ {
+ return new String(buf, 0, pos, "utf-8");
+ }
+ catch (java.io.UnsupportedEncodingException x2)
+ {
+ throw (Error) new InternalError().initCause(x2);
+ }
+ }
+
+ /**
+ * Quote characters illegal in URIs in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quote(String str)
+ {
+ return quote(str, RFC3986_SSP);
+ }
+
+ /**
+ * Quote characters illegal in URI authorities in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteAuthority(String str)
+ {
+ // Technically, we should be using RFC2396_AUTHORITY, but
+ // it contains no additional characters.
+ return quote(str, RFC3986_REG_NAME);
+ }
+
+ /**
+ * Quotes the characters in the supplied string that are not part of
+ * the specified set of legal characters.
+ *
+ * @param str the string to quote
+ * @param legalCharacters the set of legal characters
+ *
+ * @return the quoted string.
+ */
+ private static String quote(String str, String legalCharacters)
+ {
+ CPStringBuilder sb = new CPStringBuilder(str.length());
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if ((legalCharacters.indexOf(c) == -1)
+ && (c <= 127))
+ {
+ sb.append('%');
+ sb.append(HEX.charAt(c / 16));
+ sb.append(HEX.charAt(c % 16));
+ }
+ else
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Quote characters illegal in URI hosts in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteHost(String str)
+ {
+ return quote(str, RFC3986_HOST);
+ }
+
+ /**
+ * Quote characters illegal in URI paths in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quotePath(String str)
+ {
+ // Technically, we should be using RFC2396_PATH, but
+ // it contains no additional characters.
+ return quote(str, RFC3986_PATH_SEGMENTS);
+ }
+
+ /**
+ * Quote characters illegal in URI user infos in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteUserInfo(String str)
+ {
+ return quote(str, RFC3986_USERINFO);
+ }
+
+ /**
+ * Creates an URI from the given string
+ *
+ * @param str The string to create the URI from
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ * @exception NullPointerException If str is null
+ */
+ public URI(String str) throws URISyntaxException
+ {
+ this.string = str;
+ parseURI(str);
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param userInfo The username and authorization info
+ * @param host The hostname
+ * @param port The port number
+ * @param path The path
+ * @param query The query
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String userInfo, String host, int port,
+ String path, String query, String fragment)
+ throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (userInfo == null && host == null && port == -1 ? "" : "//")
+ + (userInfo == null ? "" : quoteUserInfo(userInfo) + "@")
+ + (host == null ? "" : quoteHost(host))
+ + (port == -1 ? "" : ":" + String.valueOf(port))
+ + (path == null ? "" : quotePath(path))
+ + (query == null ? "" : "?" + quote(query))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param authority The authority
+ * @param path The apth
+ * @param query The query
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String authority, String path, String query,
+ String fragment) throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (authority == null ? "" : "//" + quoteAuthority(authority))
+ + (path == null ? "" : quotePath(path))
+ + (query == null ? "" : "?" + quote(query))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param host The hostname
+ * @param path The path
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String host, String path, String fragment)
+ throws URISyntaxException
+ {
+ this(scheme, null, host, -1, path, null, fragment);
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param ssp The scheme specific part
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String ssp, String fragment)
+ throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (ssp == null ? "" : quote(ssp))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given string
+ *
+ * @param str The string to create the URI from
+ *
+ * @exception IllegalArgumentException If the given string violates RFC 2396
+ * @exception NullPointerException If str is null
+ */
+ public static URI create(String str)
+ {
+ try
+ {
+ return new URI(str);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (IllegalArgumentException) new IllegalArgumentException()
+ .initCause(e);
+ }
+ }
+
+ /**
+ * Attempts to parse this URI's authority component, if defined,
+ * into user-information, host, and port components. The purpose
+ * of this method was to disambiguate between some authority sections,
+ * which form invalid server-based authories, but valid registry
+ * based authorities. In the updated RFC 3986, the authority section
+ * is defined differently, with registry-based authorities part of
+ * the host section. Thus, this method is now simply an explicit
+ * way of parsing any authority section.
+ *
+ * @return the URI, with the authority section parsed into user
+ * information, host and port components.
+ * @throws URISyntaxException if the given string violates RFC 2396
+ */
+ public URI parseServerAuthority() throws URISyntaxException
+ {
+ if (rawAuthority != null)
+ {
+ Matcher matcher = AUTHORITY_PATTERN.matcher(rawAuthority);
+
+ if (matcher.matches())
+ {
+ rawUserInfo = getURIGroup(matcher, AUTHORITY_USERINFO_GROUP);
+ rawHost = getURIGroup(matcher, AUTHORITY_HOST_GROUP);
+
+ String portStr = getURIGroup(matcher, AUTHORITY_PORT_GROUP);
+
+ if (portStr != null && ! portStr.isEmpty())
+ try
+ {
+ port = Integer.parseInt(portStr);
+ }
+ catch (NumberFormatException e)
+ {
+ URISyntaxException use =
+ new URISyntaxException
+ (string, "doesn't match URI regular expression");
+ use.initCause(e);
+ throw use;
+ }
+ }
+ else
+ throw new URISyntaxException(string,
+ "doesn't match URI regular expression");
+ }
+ return this;
+ }
+
+ /**
+ * <p>
+ * Returns a normalized version of the URI. If the URI is opaque,
+ * or its path is already in normal form, then this URI is simply
+ * returned. Otherwise, the following transformation of the path
+ * element takes place:
+ * </p>
+ * <ol>
+ * <li>All `.' segments are removed.</li>
+ * <li>Each `..' segment which can be paired with a prior non-`..' segment
+ * is removed along with the preceding segment.</li>
+ * <li>A `.' segment is added to the front if the first segment contains
+ * a colon (`:'). This is a deviation from the RFC, which prevents
+ * confusion between the path and the scheme.</li>
+ * </ol>
+ * <p>
+ * The resulting URI will be free of `.' and `..' segments, barring those
+ * that were prepended or which couldn't be paired, respectively.
+ * </p>
+ *
+ * @return the normalized URI.
+ */
+ public URI normalize()
+ {
+ if (isOpaque() || path.indexOf("/./") == -1 && path.indexOf("/../") == -1)
+ return this;
+ try
+ {
+ return new URI(scheme, authority, normalizePath(path), query,
+ fragment);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Normalized URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * <p>
+ * Normalize the given path. The following transformation takes place:
+ * </p>
+ * <ol>
+ * <li>All `.' segments are removed.</li>
+ * <li>Each `..' segment which can be paired with a prior non-`..' segment
+ * is removed along with the preceding segment.</li>
+ * <li>A `.' segment is added to the front if the first segment contains
+ * a colon (`:'). This is a deviation from the RFC, which prevents
+ * confusion between the path and the scheme.</li>
+ * </ol>
+ * <p>
+ * The resulting URI will be free of `.' and `..' segments, barring those
+ * that were prepended or which couldn't be paired, respectively.
+ * </p>
+ *
+ * @param relativePath the relative path to be normalized.
+ * @return the normalized path.
+ */
+ private String normalizePath(String relativePath)
+ {
+ /*
+ This follows the algorithm in section 5.2.4. of RFC3986,
+ but doesn't modify the input buffer.
+ */
+ CPStringBuilder input = new CPStringBuilder(relativePath);
+ CPStringBuilder output = new CPStringBuilder();
+ int start = 0;
+ while (start < input.length())
+ {
+ /* A */
+ if (input.indexOf("../",start) == start)
+ {
+ start += 3;
+ continue;
+ }
+ if (input.indexOf("./",start) == start)
+ {
+ start += 2;
+ continue;
+ }
+ /* B */
+ if (input.indexOf("/./",start) == start)
+ {
+ start += 2;
+ continue;
+ }
+ if (input.indexOf("/.",start) == start
+ && input.charAt(start + 2) != '.')
+ {
+ start += 1;
+ input.setCharAt(start,'/');
+ continue;
+ }
+ /* C */
+ if (input.indexOf("/../",start) == start)
+ {
+ start += 3;
+ removeLastSegment(output);
+ continue;
+ }
+ if (input.indexOf("/..",start) == start)
+ {
+ start += 2;
+ input.setCharAt(start,'/');
+ removeLastSegment(output);
+ continue;
+ }
+ /* D */
+ if (start == input.length() - 1 && input.indexOf(".",start) == start)
+ {
+ input.delete(0,1);
+ continue;
+ }
+ if (start == input.length() - 2 && input.indexOf("..",start) == start)
+ {
+ input.delete(0,2);
+ continue;
+ }
+ /* E */
+ int indexOfSlash = input.indexOf("/",start);
+ while (indexOfSlash == start)
+ {
+ output.append("/");
+ ++start;
+ indexOfSlash = input.indexOf("/",start);
+ }
+ if (indexOfSlash == -1)
+ indexOfSlash = input.length();
+ output.append(input.substring(start, indexOfSlash));
+ start = indexOfSlash;
+ }
+ return output.toString();
+ }
+
+ /**
+ * Removes the last segment of the path from the specified buffer.
+ *
+ * @param buffer the buffer containing the path.
+ */
+ private void removeLastSegment(CPStringBuilder buffer)
+ {
+ int lastSlash = buffer.lastIndexOf("/");
+ if (lastSlash == -1)
+ buffer.setLength(0);
+ else
+ buffer.setLength(lastSlash);
+ }
+
+ /**
+ * Resolves the given URI against this URI
+ *
+ * @param uri The URI to resolve against this URI
+ *
+ * @return The resulting URI, or null when it couldn't be resolved
+ * for some reason.
+ *
+ * @throws NullPointerException if uri is null
+ */
+ public URI resolve(URI uri)
+ {
+ if (uri.isAbsolute())
+ return uri;
+ if (uri.isOpaque())
+ return uri;
+
+ String scheme = uri.getScheme();
+ String schemeSpecificPart = uri.getSchemeSpecificPart();
+ String authority = uri.getAuthority();
+ String path = uri.getPath();
+ String query = uri.getQuery();
+ String fragment = uri.getFragment();
+
+ try
+ {
+ if (fragment != null && path != null && path.equals("")
+ && scheme == null && authority == null && query == null)
+ return new URI(this.scheme, this.schemeSpecificPart, fragment);
+
+ if (authority == null)
+ {
+ authority = this.authority;
+ if (path == null)
+ path = "";
+ if (! (path.startsWith("/")))
+ {
+ CPStringBuilder basepath = new CPStringBuilder(this.path);
+ int i = this.path.lastIndexOf('/');
+
+ if (i >= 0)
+ basepath.delete(i + 1, basepath.length());
+
+ basepath.append(path);
+ path = normalizePath(basepath.toString());
+ }
+ }
+ return new URI(this.scheme, authority, path, query, fragment);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Resolved URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * Resolves the given URI string against this URI
+ *
+ * @param str The URI as string to resolve against this URI
+ *
+ * @return The resulting URI
+ *
+ * @throws IllegalArgumentException If the given URI string
+ * violates RFC 2396
+ * @throws NullPointerException If uri is null
+ */
+ public URI resolve(String str) throws IllegalArgumentException
+ {
+ return resolve(create(str));
+ }
+
+ /**
+ * <p>
+ * Relativizes the given URI against this URI. The following
+ * algorithm is used:
+ * </p>
+ * <ul>
+ * <li>If either URI is opaque, the given URI is returned.</li>
+ * <li>If the schemes of the URIs differ, the given URI is returned.</li>
+ * <li>If the authority components of the URIs differ, then the given
+ * URI is returned.</li>
+ * <li>If the path of this URI is not a prefix of the supplied URI,
+ * then the given URI is returned.</li>
+ * <li>If all the above conditions hold, a new URI is created using the
+ * query and fragment components of the given URI, along with a path
+ * computed by removing the path of this URI from the start of the path
+ * of the supplied URI.</li>
+ * </ul>
+ *
+ * @param uri the URI to relativize agsint this URI
+ * @return the resulting URI
+ * @throws NullPointerException if the uri is null
+ */
+ public URI relativize(URI uri)
+ {
+ if (isOpaque() || uri.isOpaque())
+ return uri;
+ if (scheme == null && uri.getScheme() != null)
+ return uri;
+ if (scheme != null && !(scheme.equals(uri.getScheme())))
+ return uri;
+ if (rawAuthority == null && uri.getRawAuthority() != null)
+ return uri;
+ if (rawAuthority != null && !(rawAuthority.equals(uri.getRawAuthority())))
+ return uri;
+ String basePath = rawPath;
+ if (!(uri.getRawPath().equals(rawPath)))
+ {
+ if (!(basePath.endsWith("/")))
+ basePath = basePath.concat("/");
+ if (!(uri.getRawPath().startsWith(basePath)))
+ return uri;
+ }
+ try
+ {
+ return new URI(null, null,
+ uri.getRawPath().substring(basePath.length()),
+ uri.getRawQuery(), uri.getRawFragment());
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Relativized URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * Creates an URL from an URI
+ *
+ * @throws MalformedURLException If a protocol handler for the URL could
+ * not be found, or if some other error occurred while constructing the URL
+ * @throws IllegalArgumentException If the URI is not absolute
+ */
+ public URL toURL() throws IllegalArgumentException, MalformedURLException
+ {
+ if (isAbsolute())
+ return new URL(this.toString());
+
+ throw new IllegalArgumentException("not absolute");
+ }
+
+ /**
+ * Returns the scheme of the URI
+ */
+ public String getScheme()
+ {
+ return scheme;
+ }
+
+ /**
+ * Tells whether this URI is absolute or not
+ */
+ public boolean isAbsolute()
+ {
+ return scheme != null;
+ }
+
+ /**
+ * Tell whether this URI is opaque or not
+ */
+ public boolean isOpaque()
+ {
+ return ((scheme != null) && ! (schemeSpecificPart.startsWith("/")));
+ }
+
+ /**
+ * Returns the raw scheme specific part of this URI.
+ * The scheme-specific part is never undefined, though it may be empty
+ */
+ public String getRawSchemeSpecificPart()
+ {
+ return rawSchemeSpecificPart;
+ }
+
+ /**
+ * Returns the decoded scheme specific part of this URI.
+ */
+ public String getSchemeSpecificPart()
+ {
+ return schemeSpecificPart;
+ }
+
+ /**
+ * Returns the raw authority part of this URI
+ */
+ public String getRawAuthority()
+ {
+ return rawAuthority;
+ }
+
+ /**
+ * Returns the decoded authority part of this URI
+ */
+ public String getAuthority()
+ {
+ return authority;
+ }
+
+ /**
+ * Returns the raw user info part of this URI
+ */
+ public String getRawUserInfo()
+ {
+ return rawUserInfo;
+ }
+
+ /**
+ * Returns the decoded user info part of this URI
+ */
+ public String getUserInfo()
+ {
+ return userInfo;
+ }
+
+ /**
+ * Returns the hostname of the URI
+ */
+ public String getHost()
+ {
+ return host;
+ }
+
+ /**
+ * Returns the port number of the URI
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the raw path part of this URI
+ */
+ public String getRawPath()
+ {
+ return rawPath;
+ }
+
+ /**
+ * Returns the path of the URI
+ */
+ public String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Returns the raw query part of this URI
+ */
+ public String getRawQuery()
+ {
+ return rawQuery;
+ }
+
+ /**
+ * Returns the query of the URI
+ */
+ public String getQuery()
+ {
+ return query;
+ }
+
+ /**
+ * Return the raw fragment part of this URI
+ */
+ public String getRawFragment()
+ {
+ return rawFragment;
+ }
+
+ /**
+ * Returns the fragment of the URI
+ */
+ public String getFragment()
+ {
+ return fragment;
+ }
+
+ /**
+ * <p>
+ * Compares the URI with the given object for equality. If the
+ * object is not a <code>URI</code>, then the method returns false.
+ * Otherwise, the following criteria are observed:
+ * </p>
+ * <ul>
+ * <li>The scheme of the URIs must either be null (undefined) in both cases,
+ * or equal, ignorant of case.</li>
+ * <li>The raw fragment of the URIs must either be null (undefined) in both
+ * cases, or equal, ignorant of case.</li>
+ * <li>Both URIs must be of the same type (opaque or hierarchial)</li>
+ * <li><strong>For opaque URIs:</strong></li>
+ * <ul>
+ * <li>The raw scheme-specific parts must be equal.</li>
+ * </ul>
+ * <li>For hierarchical URIs:</li>
+ * <ul>
+ * <li>The raw paths must be equal, ignorant of case.</li>
+ * <li>The raw queries are either both undefined or both equal, ignorant
+ * of case.</li>
+ * <li>The raw authority sections are either both undefined or:</li>
+ * <li><strong>For registry-based authorities:</strong></li>
+ * <ul><li>they are equal.</li></ul>
+ * <li><strong>For server-based authorities:</strong></li>
+ * <ul>
+ * <li>the hosts are equal, ignoring case</li>
+ * <li>the ports are equal</li>
+ * <li>the user information components are equal</li>
+ * </ul>
+ * </ul>
+ * </ul>
+ *
+ * @param obj the obj to compare the URI with.
+ * @return <code>true</code> if the objects are equal, according to
+ * the specification above.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof URI))
+ return false;
+ URI uriObj = (URI) obj;
+ if (scheme == null)
+ {
+ if (uriObj.getScheme() != null)
+ return false;
+ }
+ else
+ if (!(scheme.equalsIgnoreCase(uriObj.getScheme())))
+ return false;
+ if (rawFragment == null)
+ {
+ if (uriObj.getRawFragment() != null)
+ return false;
+ }
+ else
+ if (!(rawFragment.equalsIgnoreCase(uriObj.getRawFragment())))
+ return false;
+ boolean opaqueThis = isOpaque();
+ boolean opaqueObj = uriObj.isOpaque();
+ if (opaqueThis && opaqueObj)
+ return rawSchemeSpecificPart.equals(uriObj.getRawSchemeSpecificPart());
+ else if (!opaqueThis && !opaqueObj)
+ {
+ boolean common = rawPath.equalsIgnoreCase(uriObj.getRawPath())
+ && ((rawQuery == null && uriObj.getRawQuery() == null)
+ || rawQuery.equalsIgnoreCase(uriObj.getRawQuery()));
+ if (rawAuthority == null && uriObj.getRawAuthority() == null)
+ return common;
+ if (host == null)
+ return common
+ && rawAuthority.equalsIgnoreCase(uriObj.getRawAuthority());
+ return common
+ && host.equalsIgnoreCase(uriObj.getHost())
+ && port == uriObj.getPort()
+ && (rawUserInfo == null ?
+ uriObj.getRawUserInfo() == null :
+ rawUserInfo.equalsIgnoreCase(uriObj.getRawUserInfo()));
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Computes the hashcode of the URI
+ */
+ public int hashCode()
+ {
+ return (getScheme() == null ? 0 : 13 * getScheme().hashCode())
+ + 17 * getRawSchemeSpecificPart().hashCode()
+ + (getRawFragment() == null ? 0 : 21 + getRawFragment().hashCode());
+ }
+
+ /**
+ * Compare the URI with another URI.
+ * Undefined components are taken to be less than any other component.
+ * The following criteria are observed:
+ * </p>
+ * <ul>
+ * <li>Two URIs with different schemes are compared according to their
+ * scheme, regardless of case.</li>
+ * <li>A hierarchical URI is less than an opaque URI with the same
+ * scheme.</li>
+ * <li><strong>For opaque URIs:</strong></li>
+ * <ul>
+ * <li>URIs with differing scheme-specific parts are ordered according
+ * to the ordering of the scheme-specific part.</li>
+ * <li>URIs with the same scheme-specific part are ordered by the
+ * raw fragment.</li>
+ * </ul>
+ * <li>For hierarchical URIs:</li>
+ * <ul>
+ * <li>URIs are ordered according to their raw authority sections,
+ * if they are unequal.</li>
+ * <li><strong>For registry-based authorities:</strong></li>
+ * <ul><li>they are ordered according to the ordering of the authority
+ * component.</li></ul>
+ * <li><strong>For server-based authorities:</strong></li>
+ * <ul>
+ * <li>URIs are ordered according to the raw user information.</li>
+ * <li>URIs with the same user information are ordered by the host,
+ * ignoring case.</li>
+ * <lI>URIs with the same host are ordered by the port.</li>
+ * </ul>
+ * <li>URIs with the same authority section are ordered by the raw path.</li>
+ * <li>URIs with the same path are ordered by their raw query.</li>
+ * <li>URIs with the same query are ordered by their raw fragments.</li>
+ * </ul>
+ * </ul>
+ *
+ * @param uri The other URI to compare this URI with
+ * @return a negative integer, zero or a positive integer depending
+ * on whether this URI is less than, equal to or greater
+ * than that supplied, respectively.
+ */
+ public int compareTo(URI uri)
+ throws ClassCastException
+ {
+ if (scheme == null && uri.getScheme() != null)
+ return -1;
+ if (scheme != null)
+ {
+ int sCompare = scheme.compareToIgnoreCase(uri.getScheme());
+ if (sCompare != 0)
+ return sCompare;
+ }
+ boolean opaqueThis = isOpaque();
+ boolean opaqueObj = uri.isOpaque();
+ if (opaqueThis && !opaqueObj)
+ return 1;
+ if (!opaqueThis && opaqueObj)
+ return -1;
+ if (opaqueThis)
+ {
+ int ssCompare =
+ rawSchemeSpecificPart.compareTo(uri.getRawSchemeSpecificPart());
+ if (ssCompare == 0)
+ return compareFragments(uri);
+ else
+ return ssCompare;
+ }
+ if (rawAuthority == null && uri.getRawAuthority() != null)
+ return -1;
+ if (rawAuthority != null)
+ {
+ int aCompare = rawAuthority.compareTo(uri.getRawAuthority());
+ if (aCompare != 0)
+ {
+ if (host == null)
+ return aCompare;
+ if (rawUserInfo == null && uri.getRawUserInfo() != null)
+ return -1;
+ int uCompare = rawUserInfo.compareTo(uri.getRawUserInfo());
+ if (uCompare != 0)
+ return uCompare;
+ if (host == null && uri.getHost() != null)
+ return -1;
+ int hCompare = host.compareTo(uri.getHost());
+ if (hCompare != 0)
+ return hCompare;
+ int uriPort = uri.getPort();
+ return (uriPort == port) ? 0 : (uriPort > port) ? -1 : 1;
+ }
+ }
+ if (rawPath == null && uri.getRawPath() != null)
+ return -1;
+ if (rawPath != null)
+ {
+ int pCompare = rawPath.compareTo(uri.getRawPath());
+ if (pCompare != 0)
+ return pCompare;
+ }
+ if (rawQuery == null && uri.getRawQuery() != null)
+ return -1;
+ if (rawQuery != null)
+ {
+ int qCompare = rawQuery.compareTo(uri.getRawQuery());
+ if (qCompare != 0)
+ return qCompare;
+ }
+ return compareFragments(uri);
+ }
+
+ /**
+ * Compares the fragment of this URI with that of the supplied URI.
+ *
+ * @param uri the URI to compare with this one.
+ * @return a negative integer, zero or a positive integer depending
+ * on whether this uri's fragment is less than, equal to
+ * or greater than the fragment of the uri supplied, respectively.
+ */
+ private int compareFragments(URI uri)
+ {
+ if (rawFragment == null && uri.getRawFragment() != null)
+ return -1;
+ else if (rawFragment == null)
+ return 0;
+ else
+ return rawFragment.compareTo(uri.getRawFragment());
+ }
+
+ /**
+ * Returns the URI as a String. If the URI was created using a constructor,
+ * then this will be the same as the original input string.
+ *
+ * @return a string representation of the URI.
+ */
+ public String toString()
+ {
+ return (scheme == null ? "" : scheme + ":")
+ + rawSchemeSpecificPart
+ + (rawFragment == null ? "" : "#" + rawFragment);
+ }
+
+ /**
+ * Returns the URI as US-ASCII string. This is the same as the result
+ * from <code>toString()</code> for URIs that don't contain any non-US-ASCII
+ * characters. Otherwise, the non-US-ASCII characters are replaced
+ * by their percent-encoded representations.
+ *
+ * @return a string representation of the URI, containing only US-ASCII
+ * characters.
+ */
+ public String toASCIIString()
+ {
+ String strRep = toString();
+ boolean inNonAsciiBlock = false;
+ CPStringBuilder buffer = new CPStringBuilder();
+ CPStringBuilder encBuffer = null;
+ for (int i = 0; i < strRep.length(); i++)
+ {
+ char c = strRep.charAt(i);
+ if (c <= 127)
+ {
+ if (inNonAsciiBlock)
+ {
+ buffer.append(escapeCharacters(encBuffer.toString()));
+ inNonAsciiBlock = false;
+ }
+ buffer.append(c);
+ }
+ else
+ {
+ if (!inNonAsciiBlock)
+ {
+ encBuffer = new CPStringBuilder();
+ inNonAsciiBlock = true;
+ }
+ encBuffer.append(c);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Converts the non-ASCII characters in the supplied string
+ * to their equivalent percent-encoded representations.
+ * That is, they are replaced by "%" followed by their hexadecimal value.
+ *
+ * @param str a string including non-ASCII characters.
+ * @return the string with the non-ASCII characters converted to their
+ * percent-encoded representations.
+ */
+ private static String escapeCharacters(String str)
+ {
+ try
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ // this is far from optimal, but it works
+ byte[] utf8 = str.getBytes("utf-8");
+ for (int j = 0; j < utf8.length; j++)
+ {
+ sb.append('%');
+ sb.append(HEX.charAt((utf8[j] & 0xff) / 16));
+ sb.append(HEX.charAt((utf8[j] & 0xff) % 16));
+ }
+ return sb.toString();
+ }
+ catch (java.io.UnsupportedEncodingException x)
+ {
+ throw (Error) new InternalError("Escaping error").initCause(x);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/net/URISyntaxException.java b/libjava/classpath/java/net/URISyntaxException.java
new file mode 100644
index 000000000..27a70bdb7
--- /dev/null
+++ b/libjava/classpath/java/net/URISyntaxException.java
@@ -0,0 +1,144 @@
+/* URISyntaxException.java -- a string could not be parsed as a URI
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception is thrown when a String cannot be parsed as a URI.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see URI
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class URISyntaxException extends Exception
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 2137979680897488891L;
+
+ /**
+ * The failed input.
+ *
+ * @serial the bad URI
+ */
+ private final String input;
+
+ /**
+ * The index of failure.
+ *
+ * @serial the location of the problem
+ */
+ private final int index;
+
+ /**
+ * Create an exception from the invalid string, with the index set to -1.
+ *
+ * @param input the bad URI
+ * @param msg the descriptive error message
+ * @throws NullPointerException if input or msg are null
+ */
+ public URISyntaxException(String input, String msg)
+ {
+ this(input, msg, -1);
+ }
+
+ /**
+ * Create an exception from the invalid string, with the index of the
+ * point of failure.
+ *
+ * @param input the bad URI
+ * @param msg the descriptive error message
+ * @param index the index of the parse error, or -1
+ * @throws NullPointerException if input or msg are null
+ * @throws IllegalArgumentException if index &lt; -1
+ */
+ public URISyntaxException(String input, String msg, int index)
+ {
+ // The toString() hack checks for null.
+ super(msg.toString());
+ this.input = input.toString();
+ this.index = index;
+ if (index < -1)
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Returns the bad input string.
+ *
+ * @return the bad URI, guaranteed non-null
+ */
+ public String getInput()
+ {
+ return input;
+ }
+
+ /**
+ * Returns the reason for the failure.
+ *
+ * @return the message, guaranteed non-null
+ */
+ public String getReason()
+ {
+ return super.getMessage();
+ }
+
+ /**
+ * Returns the index of the failure, or -1.
+ *
+ * @return the index of failure
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * Returns a message describing the parse error, as if by
+ * <code>getReason() + (getIndex() &gt;= 0 ? " at index " + getIndex() : "")
+ * + ": " + getInput()</code>.
+ *
+ * @return the message string
+ */
+ public String getMessage()
+ {
+ return (super.getMessage() + (index >= 0 ? " at index " + index : "")
+ + ": " + input);
+ }
+}
diff --git a/libjava/classpath/java/net/URL.java b/libjava/classpath/java/net/URL.java
new file mode 100644
index 000000000..1b778b40a
--- /dev/null
+++ b/libjava/classpath/java/net/URL.java
@@ -0,0 +1,1010 @@
+/* URL.java -- Uniform Resource Locator Class
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.net.URLParseError;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * This final class represents an Internet Uniform Resource Locator (URL).
+ * For details on the syntax of URL's and what they can be used for,
+ * refer to RFC 1738, available from <a
+ * href="http://ds.internic.net/rfcs/rfc1738.txt">
+ * http://ds.internic.net/rfcs/rfc1738.txt</a>
+ * <p>
+ * There are a great many protocols supported by URL's such as "http",
+ * "ftp", and "file". This object can handle any arbitrary URL for which
+ * a URLStreamHandler object can be written. Default protocol handlers
+ * are provided for the "http" and "ftp" protocols. Additional protocols
+ * handler implementations may be provided in the future. In any case,
+ * an application or applet can install its own protocol handlers that
+ * can be "chained" with other protocol hanlders in the system to extend
+ * the base functionality provided with this class. (Note, however, that
+ * unsigned applets cannot access properties by default or install their
+ * own protocol handlers).
+ * <p>
+ * This chaining is done via the system property java.protocol.handler.pkgs
+ * If this property is set, it is assumed to be a "|" separated list of
+ * package names in which to attempt locating protocol handlers. The
+ * protocol handler is searched for by appending the string
+ * ".&lt;protocol&gt;.Handler" to each packed in the list until a hander is
+ * found. If a protocol handler is not found in this list of packages, or if
+ * the property does not exist, then the default protocol handler of
+ * "gnu.java.net.&lt;protocol&gt;.Handler" is tried. If this is
+ * unsuccessful, a MalformedURLException is thrown.
+ * <p>
+ * All of the constructor methods of URL attempt to load a protocol
+ * handler and so any needed protocol handlers must be installed when
+ * the URL is constructed.
+ * <p>
+ * Here is an example of how URL searches for protocol handlers. Assume
+ * the value of java.protocol.handler.pkgs is "com.foo|com.bar" and the
+ * URL is "news://comp.lang.java.programmer". URL would looking the
+ * following places for protocol handlers:
+ * <p><pre>
+ * com.foo.news.Handler
+ * com.bar.news.Handler
+ * gnu.java.net.news.Handler
+ * </pre><p>
+ * If the protocol handler is not found in any of those locations, a
+ * MalformedURLException would be thrown.
+ * <p>
+ * Please note that a protocol handler must be a subclass of
+ * URLStreamHandler.
+ * <p>
+ * Normally, this class caches protocol handlers. Once it finds a handler
+ * for a particular protocol, it never tries to look up a new handler
+ * again. However, if the system property
+ * gnu.java.net.nocache_protocol_handlers is set, then this
+ * caching behavior is disabled. This property is specific to this
+ * implementation. Sun's JDK may or may not do protocol caching, but it
+ * almost certainly does not examine this property.
+ * <p>
+ * Please also note that an application can install its own factory for
+ * loading protocol handlers (see setURLStreamHandlerFactory). If this is
+ * done, then the above information is superseded and the behavior of this
+ * class in loading protocol handlers is dependent on that factory.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ *
+ * @see URLStreamHandler
+ */
+public final class URL implements Serializable
+{
+ private static final String DEFAULT_SEARCH_PATH =
+ "gnu.java.net.protocol|gnu.inet";
+
+ // Cached System ClassLoader
+ private static ClassLoader systemClassLoader;
+
+ /**
+ * The name of the protocol for this URL.
+ * The protocol is always stored in lower case.
+ */
+ private String protocol;
+
+ /**
+ * The "authority" portion of the URL.
+ */
+ private String authority;
+
+ /**
+ * The hostname or IP address of this protocol.
+ * This includes a possible user. For example <code>joe@some.host.net</code>.
+ */
+ private String host;
+
+ /**
+ * The user information necessary to establish the connection.
+ */
+ private String userInfo;
+
+ /**
+ * The port number of this protocol or -1 if the port number used is
+ * the default for this protocol.
+ */
+ private int port = -1; // Initialize for constructor using context.
+
+ /**
+ * The "file" portion of the URL. It is defined as <code>path[?query]</code>.
+ */
+ private String file;
+
+ /**
+ * The anchor portion of the URL.
+ */
+ private String ref;
+
+ /**
+ * This is the hashCode for this URL
+ */
+ private int hashCode;
+
+ /**
+ * The protocol handler in use for this URL
+ */
+ transient URLStreamHandler ph;
+
+ /**
+ * If an application installs its own protocol handler factory, this is
+ * where we keep track of it.
+ */
+ private static URLStreamHandlerFactory factory;
+ private static final long serialVersionUID = -7627629688361524110L;
+
+ /**
+ * This a table where we cache protocol handlers to avoid the overhead
+ * of looking them up each time.
+ */
+ private static HashMap<String, URLStreamHandler> ph_cache
+ = new HashMap<String, URLStreamHandler>();
+
+ /**
+ * Whether or not to cache protocol handlers.
+ */
+ private static boolean cache_handlers;
+
+ static
+ {
+ String s = SystemProperties.getProperty("gnu.java.net.nocache_protocol_handlers");
+
+ if (s == null)
+ cache_handlers = true;
+ else
+ cache_handlers = false;
+ }
+
+ /**
+ * Constructs a URL and loads a protocol handler for the values passed as
+ * arguments.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address to connect to
+ * @param port The port number to use, or -1 to use the protocol's
+ * default port
+ * @param file The "file" portion of the URL.
+ *
+ * @exception MalformedURLException If a protocol handler cannot be loaded or
+ * a parse error occurs.
+ */
+ public URL(String protocol, String host, int port, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, port, file, null);
+ }
+
+ /**
+ * Constructs a URL and loads a protocol handler for the values passed in
+ * as arugments. Uses the default port for the protocol.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address for this URL
+ * @param file The "file" portion of this URL.
+ *
+ * @exception MalformedURLException If a protocol handler cannot be loaded or
+ * a parse error occurs.
+ */
+ public URL(String protocol, String host, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, -1, file, null);
+ }
+
+ /**
+ * This method initializes a new instance of <code>URL</code> with the
+ * specified protocol, host, port, and file. Additionally, this method
+ * allows the caller to specify a protocol handler to use instead of
+ * the default. If this handler is specified, the caller must have
+ * the "specifyStreamHandler" permission (see <code>NetPermission</code>)
+ * or a <code>SecurityException</code> will be thrown.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address to connect to
+ * @param port The port number to use, or -1 to use the protocol's default
+ * port
+ * @param file The "file" portion of the URL.
+ * @param ph The protocol handler to use with this URL.
+ *
+ * @exception MalformedURLException If no protocol handler can be loaded
+ * for the specified protocol.
+ * @exception SecurityException If the <code>SecurityManager</code> exists
+ * and does not allow the caller to specify its own protocol handler.
+ *
+ * @since 1.2
+ */
+ public URL(String protocol, String host, int port, String file,
+ URLStreamHandler ph) throws MalformedURLException
+ {
+ if (protocol == null)
+ throw new MalformedURLException("null protocol");
+ protocol = protocol.toLowerCase();
+ this.protocol = protocol;
+
+ if (ph != null)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new NetPermission("specifyStreamHandler"));
+
+ this.ph = ph;
+ }
+ else
+ this.ph = getURLStreamHandler(protocol);
+
+ if (this.ph == null)
+ throw new MalformedURLException("Protocol handler not found: "
+ + protocol);
+
+ this.host = host;
+ this.port = port;
+ this.authority = (host != null) ? host : "";
+ if (port >= 0 && host != null)
+ this.authority += ":" + 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);
+ }
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Initializes a URL from a complete string specification such as
+ * "http://www.urbanophile.com/arenn/". First the protocol name is parsed
+ * out of the string. Then a handler is located for that protocol and
+ * the parseURL() method of that protocol handler is used to parse the
+ * remaining fields.
+ *
+ * @param spec The complete String representation of a URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * or the URL cannot be parsed
+ */
+ public URL(String spec) throws MalformedURLException
+ {
+ this((URL) null, spec != null ? spec : "", (URLStreamHandler) null,
+ false);
+ }
+
+ /**
+ * This method parses a String representation of a URL within the
+ * context of an existing URL. Principally this means that any
+ * fields not present the URL are inheritied from the context URL.
+ * This allows relative URL's to be easily constructed. If the
+ * context argument is null, then a complete URL must be specified
+ * in the URL string. If the protocol parsed out of the URL is
+ * different from the context URL's protocol, then then URL String
+ * is also expected to be a complete URL.
+ *
+ * @param context The context on which to parse the specification
+ * @param spec The string to parse an URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * for the URL cannot be parsed
+ */
+ public URL(URL context, String spec) throws MalformedURLException
+ {
+ this(context, spec,
+ (context == null) ? (URLStreamHandler) null : context.ph,
+ false);
+ }
+
+ /**
+ * Creates an URL from given arguments
+ * This method parses a String representation of a URL within the
+ * context of an existing URL. Principally this means that any fields
+ * not present the URL are inheritied from the context URL. This allows
+ * relative URL's to be easily constructed. If the context argument is
+ * null, then a complete URL must be specified in the URL string.
+ * If the protocol parsed out of the URL is different
+ * from the context URL's protocol, then then URL String is also
+ * expected to be a complete URL.
+ * <p>
+ * Additionally, this method allows the caller to specify a protocol handler
+ * to use instead of the default. If this handler is specified, the caller
+ * must have the "specifyStreamHandler" permission
+ * (see <code>NetPermission</code>) or a <code>SecurityException</code>
+ * will be thrown.
+ *
+ * @param context The context in which to parse the specification
+ * @param spec The string to parse as an URL
+ * @param ph The stream handler for the URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * or the URL cannot be parsed
+ * @exception SecurityException If the <code>SecurityManager</code> exists
+ * and does not allow the caller to specify its own protocol handler.
+ *
+ * @since 1.2
+ */
+ public URL(URL context, String spec, URLStreamHandler ph)
+ throws MalformedURLException
+ {
+ this(context, spec, ph, true);
+ }
+
+ /**
+ * Private constructor called by all other constructors taking
+ * a context and spec.
+ *
+ * @param context The context in which to parse the specification
+ * @param spec The string to parse as an URL
+ * @param ph The stream handler for the URL
+ * @param phFromUser Whether or not the user supplied the URLStreamHandler
+ *
+ */
+ private URL(URL context, String spec, URLStreamHandler ph,
+ boolean phFromUser)
+ 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.
+ */
+
+ // If this is an absolute URL, then ignore context completely.
+ // An absolute URL must have chars prior to "://" but cannot have a colon
+ // right after the "://". The second colon is for an optional port value
+ // and implies that the host from the context is used if available.
+ int colon;
+ int slash = spec.indexOf('/');
+ if ((colon = spec.indexOf("://", 1)) > 0
+ && ((colon < slash || slash < 0))
+ && ! spec.regionMatches(colon, "://:", 0, 4))
+ {
+ context = null;
+ if (! phFromUser)
+ ph = null;
+ }
+
+ boolean protocolSpecified = false;
+
+ if ((colon = spec.indexOf(':')) > 0
+ && (colon < slash || slash < 0))
+ {
+ // Protocol may have been specified in spec string.
+ protocolSpecified = true;
+ protocol = spec.substring(0, colon).toLowerCase();
+ if (context != null)
+ {
+ if (context.protocol.equals(protocol))
+ {
+ // The 1.2 doc specifically says these are copied to the new URL.
+ host = context.host;
+ port = context.port;
+ userInfo = context.userInfo;
+ authority = context.authority;
+ }
+ else
+ {
+ // There was a colon in the spec. Check to see if
+ // what precedes it is a valid protocol. If it was
+ // not, assume that it is relative to the context.
+ URLStreamHandler specPh = getURLStreamHandler(protocol.trim());
+ if (null == specPh)
+ protocolSpecified = false;
+ }
+ }
+ }
+
+ if (!protocolSpecified)
+ {
+ 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;
+ userInfo = context.userInfo;
+ if (spec.indexOf(":/", 1) < 0)
+ {
+ file = context.file;
+ if (file == null || file.length() == 0)
+ file = "/";
+ }
+ authority = context.authority;
+ }
+ else // Protocol NOT specified in spec. and no context available.
+ throw new MalformedURLException("Absolute URL required with null"
+ + " context: " + spec);
+ }
+
+ protocol = protocol.trim();
+
+ if (ph != null)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && phFromUser)
+ s.checkPermission(new NetPermission("specifyStreamHandler"));
+
+ this.ph = ph;
+ }
+ else
+ this.ph = getURLStreamHandler(protocol);
+
+ if (this.ph == null)
+ throw new MalformedURLException("Protocol handler not found: "
+ + protocol);
+
+ // JDK 1.2 doc for parseURL specifically states that any '#' ref
+ // is to be excluded by passing the 'limit' as the indexOf the '#'
+ // if one exists, otherwise pass the end of the string.
+ int hashAt = spec.indexOf('#', colon + 1);
+
+ try
+ {
+ this.ph.parseURL(this, spec, colon + 1,
+ hashAt < 0 ? spec.length() : hashAt);
+ }
+ catch (URLParseError e)
+ {
+ MalformedURLException mue = new MalformedURLException(e.getMessage());
+ mue.initCause(e);
+ throw mue;
+ }
+ catch (RuntimeException e)
+ {
+ // This isn't documented, but the JDK also catches
+ // RuntimeExceptions here.
+ MalformedURLException mue = new MalformedURLException(e.getMessage());
+ mue.initCause(e);
+ throw mue;
+ }
+
+ if (hashAt >= 0)
+ ref = spec.substring(hashAt + 1);
+
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Test another URL for equality with this one. This will be true only if
+ * the argument is non-null and all of the fields in the URL's match
+ * exactly (ie, protocol, host, port, file, and ref). Overrides
+ * Object.equals(), implemented by calling the equals method of the handler.
+ *
+ * @param obj The URL to compare with
+ *
+ * @return true if the URL is equal, false otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof URL))
+ return false;
+
+ return ph.equals(this, (URL) obj);
+ }
+
+ /**
+ * Returns the contents of this URL as an object by first opening a
+ * connection, then calling the getContent() method against the connection
+ *
+ * @return A content object for this URL
+ * @exception IOException If opening the connection or getting the
+ * content fails.
+ *
+ * @since 1.3
+ */
+ public Object getContent() throws IOException
+ {
+ return openConnection().getContent();
+ }
+
+ /**
+ * Gets the contents of this URL
+ *
+ * @param classes The allow classes for the content object.
+ *
+ * @return a context object for this URL.
+ *
+ * @exception IOException If an error occurs
+ */
+ public Object getContent(Class[] classes) throws IOException
+ {
+ return openConnection().getContent(classes);
+ }
+
+ /**
+ * Returns the file portion of the URL.
+ * Defined as <code>path[?query]</code>.
+ * Returns the empty string if there is no file portion.
+ *
+ * @return The filename specified in this URL, or an empty string if empty.
+ */
+ public String getFile()
+ {
+ return file == null ? "" : file;
+ }
+
+ /**
+ * Returns the path of the URL. This is the part of the file before any '?'
+ * character.
+ *
+ * @return The path specified in this URL, or null if empty.
+ *
+ * @since 1.3
+ */
+ public String getPath()
+ {
+ // The spec says we need to return an empty string, but some
+ // applications depends on receiving null when the path is empty.
+ if (file == null)
+ return null;
+ int quest = file.indexOf('?');
+ return quest < 0 ? getFile() : file.substring(0, quest);
+ }
+
+ /**
+ * Returns the authority of the URL
+ *
+ * @return The authority specified in this URL.
+ *
+ * @since 1.3
+ */
+ public String getAuthority()
+ {
+ return authority;
+ }
+
+ /**
+ * Returns the host of the URL
+ *
+ * @return The host specified in this URL.
+ */
+ public String getHost()
+ {
+ int at = (host == null) ? -1 : host.indexOf('@');
+ return at < 0 ? host : host.substring(at + 1, host.length());
+ }
+
+ /**
+ * Returns the port number of this URL or -1 if the default port number is
+ * being used.
+ *
+ * @return The port number
+ *
+ * @see #getDefaultPort()
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the default port of the URL. If the StreamHandler for the URL
+ * protocol does not define a default port it returns -1.
+ *
+ * @return The default port of the current protocol.
+ */
+ public int getDefaultPort()
+ {
+ return ph.getDefaultPort();
+ }
+
+ /**
+ * Returns the protocol of the URL
+ *
+ * @return The specified protocol.
+ */
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ /**
+ * Returns the ref (sometimes called the "# reference" or "anchor") portion
+ * of the URL.
+ *
+ * @return The ref
+ */
+ public String getRef()
+ {
+ return ref;
+ }
+
+ /**
+ * Returns the user information of the URL. This is the part of the host
+ * name before the '@'.
+ *
+ * @return the user at a particular host or null when no user defined.
+ */
+ public String getUserInfo()
+ {
+ if (userInfo != null)
+ return userInfo;
+ int at = (host == null) ? -1 : host.indexOf('@');
+ return at < 0 ? null : host.substring(0, at);
+ }
+
+ /**
+ * Returns the query of the URL. This is the part of the file before the
+ * '?'.
+ *
+ * @return the query part of the file, or null when there is no query part.
+ */
+ public String getQuery()
+ {
+ int quest = (file == null) ? -1 : file.indexOf('?');
+ return quest < 0 ? null : file.substring(quest + 1, file.length());
+ }
+
+ /**
+ * Returns a hashcode computed by the URLStreamHandler of this URL
+ *
+ * @return The hashcode for this URL.
+ */
+ public int hashCode()
+ {
+ if (hashCode != 0)
+ return hashCode; // Use cached value if available.
+ else
+ return ph.hashCode(this);
+ }
+
+ /**
+ * Returns a URLConnection object that represents a connection to the remote
+ * object referred to by the URL. The URLConnection is created by calling the
+ * openConnection() method of the protocol handler
+ *
+ * @return A URLConnection for this URL
+ *
+ * @exception IOException If an error occurs
+ */
+ public URLConnection openConnection() throws IOException
+ {
+ return ph.openConnection(this);
+ }
+
+ /**
+ * Opens a connection to this URL and returns an InputStream for reading
+ * from that connection
+ *
+ * @return An <code>InputStream</code> for this URL.
+ *
+ * @exception IOException If an error occurs
+ */
+ public InputStream openStream() throws IOException
+ {
+ return openConnection().getInputStream();
+ }
+
+ /**
+ * Tests whether or not another URL refers to the same "file" as this one.
+ * This will be true if and only if the passed object is not null, is a
+ * URL, and matches all fields but the ref (ie, protocol, host, port,
+ * and file);
+ *
+ * @param url The URL object to test with
+ *
+ * @return true if URL matches this URL's file, false otherwise
+ */
+ public boolean sameFile(URL url)
+ {
+ return ph.sameFile(this, url);
+ }
+
+ /**
+ * Sets the specified fields of the URL. This is not a public method so
+ * that only URLStreamHandlers can modify URL fields. This might be called
+ * by the <code>parseURL()</code> method in that class. URLs are otherwise
+ * constant. If the given protocol does not exist, it will keep the previously
+ * set protocol.
+ *
+ * @param protocol The protocol name for this URL
+ * @param host The hostname or IP address for this URL
+ * @param port The port number of this URL
+ * @param file The "file" portion of this URL.
+ * @param ref The anchor portion of this URL.
+ */
+ protected void set(String protocol, String host, int port, String file,
+ String ref)
+ {
+ URLStreamHandler protocolHandler = null;
+ protocol = protocol.toLowerCase();
+ if (! this.protocol.equals(protocol))
+ protocolHandler = getURLStreamHandler(protocol);
+
+ // It is an hidden feature of the JDK. If the protocol does not exist,
+ // we keep the previously initialized protocol.
+ if (protocolHandler != null)
+ {
+ this.ph = protocolHandler;
+ this.protocol = protocol;
+ }
+ this.authority = "";
+ this.port = port;
+ this.host = host;
+ this.file = file;
+ this.ref = ref;
+
+ if (host != null)
+ this.authority += host;
+ if (port >= 0)
+ this.authority += ":" + port;
+
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Sets the specified fields of the URL. This is not a public method so
+ * that only URLStreamHandlers can modify URL fields. URLs are otherwise
+ * constant. If the given protocol does not exist, it will keep the previously
+ * set protocol.
+ *
+ * @param protocol The protocol name for this URL.
+ * @param host The hostname or IP address for this URL.
+ * @param port The port number of this URL.
+ * @param authority The authority of this URL.
+ * @param userInfo The user and password (if needed) of this URL.
+ * @param path The "path" portion of this URL.
+ * @param query The query of this URL.
+ * @param ref The anchor portion of this URL.
+ *
+ * @since 1.3
+ */
+ protected void set(String protocol, String host, int port, String authority,
+ String userInfo, String path, String query, String ref)
+ {
+ URLStreamHandler protocolHandler = null;
+ protocol = protocol.toLowerCase();
+ if (! this.protocol.equals(protocol))
+ protocolHandler = getURLStreamHandler(protocol);
+
+ // It is an hidden feature of the JDK. If the protocol does not exist,
+ // we keep the previously initialized protocol.
+ if (protocolHandler != null)
+ {
+ this.ph = protocolHandler;
+ this.protocol = protocol;
+ }
+ this.host = host;
+ this.userInfo = userInfo;
+ this.port = port;
+ this.authority = authority;
+ if (query == null)
+ this.file = path;
+ else
+ this.file = path + "?" + query;
+ this.ref = ref;
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Sets the URLStreamHandlerFactory for this class. This factory is
+ * responsible for returning the appropriate protocol handler for
+ * a given URL.
+ *
+ * @param fac The URLStreamHandlerFactory class to use
+ *
+ * @exception Error If the factory is alread set.
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ 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;
+ }
+
+ /**
+ * Returns a String representing this URL. The String returned is
+ * created by calling the protocol handler's toExternalForm() method.
+ *
+ * @return A string for this URL
+ */
+ public String toExternalForm()
+ {
+ // Identical to toString().
+ return ph.toExternalForm(this);
+ }
+
+ /**
+ * Returns a String representing this URL. Identical to toExternalForm().
+ * The value returned is created by the protocol handler's
+ * toExternalForm method. Overrides Object.toString()
+ *
+ * @return A string for this URL
+ */
+ public String toString()
+ {
+ // Identical to toExternalForm().
+ return ph.toExternalForm(this);
+ }
+
+ /**
+ * This internal method is used in two different constructors to load
+ * a protocol handler for this URL.
+ *
+ * @param protocol The protocol to load a handler for
+ *
+ * @return A URLStreamHandler for this protocol, or null when not found.
+ */
+ private static synchronized URLStreamHandler getURLStreamHandler(String protocol)
+ {
+ URLStreamHandler ph = null;
+
+ // First, see if a protocol handler is in our cache.
+ if (cache_handlers)
+ {
+ if ((ph = ph_cache.get(protocol)) != null)
+ return ph;
+ }
+
+ // If a non-default factory has been set, use it to find the protocol.
+ if (factory != null)
+ {
+ ph = 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 (ph == 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 ph_search_path =
+ SystemProperties.getProperty("java.protocol.handler.pkgs");
+
+ // Tack our default package on at the ends.
+ if (ph_search_path != null)
+ ph_search_path += "|" + DEFAULT_SEARCH_PATH;
+ else
+ ph_search_path = DEFAULT_SEARCH_PATH;
+
+ // Finally loop through our search path looking for a match.
+ StringTokenizer pkgPrefix = new StringTokenizer(ph_search_path, "|");
+
+ // Cache the systemClassLoader
+ if (systemClassLoader == null)
+ {
+ systemClassLoader = AccessController.doPrivileged
+ (new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run()
+ {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ }
+
+ do
+ {
+ try
+ {
+ // Try to get a class from the system/application
+ // classloader, initialize it, make an instance
+ // and try to cast it to a URLStreamHandler.
+ String clsName =
+ (pkgPrefix.nextToken() + "." + protocol + ".Handler");
+ Class c = Class.forName(clsName, true, systemClassLoader);
+ ph = (URLStreamHandler) c.newInstance();
+ }
+ catch (ThreadDeath death)
+ {
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ // Ignored.
+ }
+ }
+ while (ph == null && pkgPrefix.hasMoreTokens());
+ }
+
+ // Update the hashtable with the new protocol handler.
+ if (ph != null && cache_handlers)
+ ph_cache.put(protocol, ph);
+ else
+ ph = null;
+
+ return ph;
+ }
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+ this.ph = getURLStreamHandler(protocol);
+ if (this.ph == null)
+ throw new IOException("Handler for protocol " + protocol + " not found");
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException
+ {
+ oos.defaultWriteObject();
+ }
+
+ /**
+ * Returns the equivalent <code>URI</code> object for this <code>URL</code>.
+ * This is the same as calling <code>new URI(this.toString())</code>.
+ * RFC2396-compliant URLs are guaranteed a successful conversion to
+ * a <code>URI</code> instance. However, there are some values which
+ * form valid URLs, but which do not also form RFC2396-compliant URIs.
+ *
+ * @throws URISyntaxException if this URL is not RFC2396-compliant,
+ * and thus can not be successfully converted to a URI.
+ */
+ public URI toURI()
+ throws URISyntaxException
+ {
+ return new URI(toString());
+ }
+
+}
diff --git a/libjava/classpath/java/net/URLClassLoader.java b/libjava/classpath/java/net/URLClassLoader.java
new file mode 100644
index 000000000..418ee77f3
--- /dev/null
+++ b/libjava/classpath/java/net/URLClassLoader.java
@@ -0,0 +1,860 @@
+/* URLClassLoader.java -- ClassLoader that loads classes from one or more URLs
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.net.loader.FileURLLoader;
+import gnu.java.net.loader.JarURLLoader;
+import gnu.java.net.loader.RemoteURLLoader;
+import gnu.java.net.loader.Resource;
+import gnu.java.net.loader.URLLoader;
+import gnu.java.net.loader.URLStreamHandlerCache;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+
+/**
+ * A secure class loader that can load classes and resources from
+ * multiple locations. Given an array of <code>URL</code>s this class
+ * loader will retrieve classes and resources by fetching them from
+ * possible remote locations. Each <code>URL</code> is searched in
+ * order in which it was added. If the file portion of the
+ * <code>URL</code> ends with a '/' character then it is interpreted
+ * as a base directory, otherwise it is interpreted as a jar file from
+ * which the classes/resources are resolved.
+ *
+ * <p>New instances can be created by two static
+ * <code>newInstance()</code> methods or by three public
+ * contructors. Both ways give the option to supply an initial array
+ * of <code>URL</code>s and (optionally) a parent classloader (that is
+ * different from the standard system class loader).</p>
+ *
+ * <p>Normally creating a <code>URLClassLoader</code> throws a
+ * <code>SecurityException</code> if a <code>SecurityManager</code> is
+ * installed and the <code>checkCreateClassLoader()</code> method does
+ * not return true. But the <code>newInstance()</code> methods may be
+ * used by any code as long as it has permission to acces the given
+ * <code>URL</code>s. <code>URLClassLoaders</code> created by the
+ * <code>newInstance()</code> methods also explicitly call the
+ * <code>checkPackageAccess()</code> method of
+ * <code>SecurityManager</code> if one is installed before trying to
+ * load a class. Note that only subclasses of
+ * <code>URLClassLoader</code> can add new URLs after the
+ * URLClassLoader had been created. But it is always possible to get
+ * an array of all URLs that the class loader uses to resolve classes
+ * and resources by way of the <code>getURLs()</code> method.</p>
+ *
+ * <p>Open issues:
+ * <ul>
+ *
+ * <li>Should the URLClassLoader actually add the locations found in
+ * the manifest or is this the responsibility of some other
+ * loader/(sub)class? (see <a
+ * href="http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html">
+ * Extension Mechanism Architecture - Bundles Extensions</a>)</li>
+ *
+ * <li>How does <code>definePackage()</code> and sealing work
+ * precisely?</li>
+ *
+ * <li>We save and use the security context (when a created by
+ * <code>newInstance()</code> but do we have to use it in more
+ * places?</li>
+ *
+ * <li>The use of <code>URLStreamHandler</code>s has not been tested.</li>
+ *
+ * </ul>
+ * </p>
+ *
+ * @since 1.2
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Wu Gansha (gansha.wu@intel.com)
+ */
+public class URLClassLoader extends SecureClassLoader
+{
+ // Class Variables
+
+ /**
+ * A cache to store mappings between handler factory and its
+ * private protocol handler cache (also a HashMap), so we can avoid
+ * creating handlers each time the same protocol comes.
+ */
+ private static URLStreamHandlerCache factoryCache
+ = new URLStreamHandlerCache();
+
+ /**
+ * The prefix for URL loaders.
+ */
+ private static final String URL_LOADER_PREFIX = "gnu.java.net.loader.Load_";
+
+ // Instance variables
+
+ /** Locations to load classes from */
+ private final Vector<URL> urls = new Vector<URL>();
+
+ /**
+ * Store pre-parsed information for each url into this vector: each
+ * element is a URL loader. A jar file has its own class-path
+ * attribute which adds to the URLs that will be searched, but this
+ * does not add to the list of urls.
+ */
+ private final Vector<URLLoader> urlinfos = new Vector<URLLoader>();
+
+ /** Factory used to get the protocol handlers of the URLs */
+ private final URLStreamHandlerFactory factory;
+
+ /**
+ * The security context when created from <code>newInstance()</code>
+ * or null when created through a normal constructor or when no
+ * <code>SecurityManager</code> was installed.
+ */
+ private final AccessControlContext securityContext;
+
+ // Helper classes
+
+ /**
+ * Creates a URLClassLoader that gets classes from the supplied URLs.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<code>SecureClassLoader</code>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the default parent ClassLoader).
+ *
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls) throws SecurityException
+ {
+ super();
+ this.factory = null;
+ this.securityContext = null;
+ addURLs(urls);
+ }
+
+ /**
+ * Creates a <code>URLClassLoader</code> that gets classes from the supplied
+ * <code>URL</code>s.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<code>SecureClassLoader</code>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the supplied parent ClassLoader).
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @param parent The parent class loader used before trying this class
+ * loader.
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @exception SecurityException
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls, ClassLoader parent)
+ throws SecurityException
+ {
+ super(parent);
+ this.factory = null;
+ this.securityContext = null;
+ addURLs(urls);
+ }
+
+ // Package-private to avoid a trampoline constructor.
+ /**
+ * Package-private constructor used by the static
+ * <code>newInstance(URL[])</code> method. Creates an
+ * <code>URLClassLoader</code> with the given parent but without any
+ * <code>URL</code>s yet. This is used to bypass the normal security
+ * check for creating classloaders, but remembers the security
+ * context which will be used when defining classes. The
+ * <code>URL</code>s to load from must be added by the
+ * <code>newInstance()</code> method in the security context of the
+ * caller.
+ *
+ * @param securityContext the security context of the unprivileged code.
+ */
+ URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
+ {
+ super(parent);
+ this.factory = null;
+ this.securityContext = securityContext;
+ }
+
+ /**
+ * Creates a URLClassLoader that gets classes from the supplied URLs.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the supplied parent ClassLoader).
+ * It will use the supplied <CODE>URLStreamHandlerFactory</CODE> to get the
+ * protocol handlers of the supplied URLs.
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @param parent The parent class loader used before trying this class
+ * loader.
+ * @param factory Used to get the protocol handler for the URLs.
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @exception SecurityException
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls, ClassLoader parent,
+ URLStreamHandlerFactory factory)
+ throws SecurityException
+ {
+ super(parent);
+ this.securityContext = null;
+ this.factory = factory;
+ // If this factory is not yet in factoryCache, add it.
+ factoryCache.add(factory);
+ addURLs(urls);
+ }
+
+ // Methods
+
+ /**
+ * Adds a new location to the end of the internal URL store.
+ * @param newUrl the location to add
+ */
+ protected void addURL(URL newUrl)
+ {
+ urls.add(newUrl);
+ addURLImpl(newUrl);
+ }
+
+ private void addURLImpl(URL newUrl)
+ {
+ synchronized (this)
+ {
+ if (newUrl == null)
+ return; // Silently ignore...
+
+ // Reset the toString() value.
+ thisString = null;
+
+ // Create a loader for this URL.
+ URLLoader loader = null;
+ String file = newUrl.getFile();
+ String protocol = newUrl.getProtocol();
+
+ // If we have a file: URL, we want to make it absolute
+ // here, before we decide whether it is really a jar.
+ URL absoluteURL;
+ if ("file".equals (protocol))
+ {
+ File dir = new File(file);
+ try
+ {
+ absoluteURL = dir.getCanonicalFile().toURL();
+ }
+ catch (IOException ignore)
+ {
+ try
+ {
+ absoluteURL = dir.getAbsoluteFile().toURL();
+ }
+ catch (MalformedURLException _)
+ {
+ // This really should not happen.
+ absoluteURL = newUrl;
+ }
+ }
+ }
+ else
+ {
+ // This doesn't hurt, and it simplifies the logic a
+ // little.
+ absoluteURL = newUrl;
+ }
+
+ // First see if we can find a handler with the correct name.
+ try
+ {
+ Class<?> handler = Class.forName(URL_LOADER_PREFIX + protocol);
+ Class<?>[] argTypes = new Class<?>[] { URLClassLoader.class,
+ URLStreamHandlerCache.class,
+ URLStreamHandlerFactory.class,
+ URL.class,
+ URL.class };
+ Constructor k = handler.getDeclaredConstructor(argTypes);
+ loader
+ = (URLLoader) k.newInstance(new Object[] { this,
+ factoryCache,
+ factory,
+ newUrl,
+ absoluteURL });
+ }
+ catch (ClassNotFoundException ignore)
+ {
+ // Fall through.
+ }
+ catch (NoSuchMethodException nsme)
+ {
+ // Programming error in the class library.
+ InternalError vme
+ = new InternalError("couldn't find URLLoader constructor");
+ vme.initCause(nsme);
+ throw vme;
+ }
+ catch (InstantiationException inste)
+ {
+ // Programming error in the class library.
+ InternalError vme
+ = new InternalError("couldn't instantiate URLLoader");
+ vme.initCause(inste);
+ throw vme;
+ }
+ catch (InvocationTargetException ite)
+ {
+ // Programming error in the class library.
+ InternalError vme
+ = new InternalError("error instantiating URLLoader");
+ vme.initCause(ite);
+ throw vme;
+ }
+ catch (IllegalAccessException illae)
+ {
+ // Programming error in the class library.
+ InternalError vme
+ = new InternalError("invalid access to URLLoader");
+ vme.initCause(illae);
+ throw vme;
+ }
+
+ if (loader == null)
+ {
+ // If it is not a directory, use the jar loader.
+ if (! (file.endsWith("/") || file.endsWith(File.separator)))
+ loader = new JarURLLoader(this, factoryCache, factory,
+ newUrl, absoluteURL);
+ else if ("file".equals(protocol))
+ loader = new FileURLLoader(this, factoryCache, factory,
+ newUrl, absoluteURL);
+ else
+ loader = new RemoteURLLoader(this, factoryCache, factory,
+ newUrl);
+ }
+
+ urlinfos.add(loader);
+ ArrayList<URLLoader> extra = loader.getClassPath();
+ if (extra != null)
+ urlinfos.addAll(extra);
+ }
+ }
+
+ /**
+ * Adds an array of new locations to the end of the internal URL
+ * store. Called from the the constructors. Should not call to the
+ * protected addURL() method since that can be overridden and
+ * subclasses are not yet in a good state at this point.
+ * jboss 4.0.3 for example depends on this.
+ *
+ * @param newUrls the locations to add
+ */
+ private void addURLs(URL[] newUrls)
+ {
+ for (int i = 0; i < newUrls.length; i++)
+ {
+ urls.add(newUrls[i]);
+ addURLImpl(newUrls[i]);
+ }
+ }
+
+ /**
+ * Look in both Attributes for a given value. The first Attributes
+ * object, if not null, has precedence.
+ */
+ private String getAttributeValue(Attributes.Name name, Attributes first,
+ Attributes second)
+ {
+ String result = null;
+ if (first != null)
+ result = first.getValue(name);
+ if (result == null)
+ result = second.getValue(name);
+ return result;
+ }
+
+ /**
+ * Defines a Package based on the given name and the supplied manifest
+ * information. The manifest indicates the title, version and
+ * vendor information of the specification and implementation and whether the
+ * package is sealed. If the Manifest indicates that the package is sealed
+ * then the Package will be sealed with respect to the supplied URL.
+ *
+ * @param name The name of the package
+ * @param manifest The manifest describing the specification,
+ * implementation and sealing details of the package
+ * @param url the code source url to seal the package
+ * @return the defined Package
+ * @throws IllegalArgumentException If this package name already exists
+ * in this class loader
+ */
+ protected Package definePackage(String name, Manifest manifest, URL url)
+ throws IllegalArgumentException
+ {
+ // Compute the name of the package as it may appear in the
+ // Manifest.
+ CPStringBuilder xform = new CPStringBuilder(name);
+ for (int i = xform.length () - 1; i >= 0; --i)
+ if (xform.charAt(i) == '.')
+ xform.setCharAt(i, '/');
+ xform.append('/');
+ String xformName = xform.toString();
+
+ Attributes entryAttr = manifest.getAttributes(xformName);
+ Attributes attr = manifest.getMainAttributes();
+
+ String specTitle
+ = getAttributeValue(Attributes.Name.SPECIFICATION_TITLE,
+ entryAttr, attr);
+ String specVersion
+ = getAttributeValue(Attributes.Name.SPECIFICATION_VERSION,
+ entryAttr, attr);
+ String specVendor
+ = getAttributeValue(Attributes.Name.SPECIFICATION_VENDOR,
+ entryAttr, attr);
+ String implTitle
+ = getAttributeValue(Attributes.Name.IMPLEMENTATION_TITLE,
+ entryAttr, attr);
+ String implVersion
+ = getAttributeValue(Attributes.Name.IMPLEMENTATION_VERSION,
+ entryAttr, attr);
+ String implVendor
+ = getAttributeValue(Attributes.Name.IMPLEMENTATION_VENDOR,
+ entryAttr, attr);
+
+ // Look if the Manifest indicates that this package is sealed
+ // XXX - most likely not completely correct!
+ // Shouldn't we also check the sealed attribute of the complete jar?
+ // http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled
+ // But how do we get that jar manifest here?
+ String sealed = attr.getValue(Attributes.Name.SEALED);
+ if ("false".equals(sealed))
+ // make sure that the URL is null so the package is not sealed
+ url = null;
+
+ return definePackage(name,
+ specTitle, specVendor, specVersion,
+ implTitle, implVendor, implVersion,
+ url);
+ }
+
+ /**
+ * Finds (the first) class by name from one of the locations. The locations
+ * are searched in the order they were added to the URLClassLoader.
+ *
+ * @param className the classname to find
+ * @exception ClassNotFoundException when the class could not be found or
+ * loaded
+ * @return a Class object representing the found class
+ */
+ protected Class<?> findClass(final String className)
+ throws ClassNotFoundException
+ {
+ // Just try to find the resource by the (almost) same name
+ String resourceName = className.replace('.', '/') + ".class";
+ int max = urlinfos.size();
+ Resource resource = null;
+ for (int i = 0; i < max && resource == null; i++)
+ {
+ URLLoader loader = (URLLoader)urlinfos.elementAt(i);
+ if (loader == null)
+ continue;
+
+ Class k = loader.getClass(className);
+ if (k != null)
+ return k;
+
+ resource = loader.getResource(resourceName);
+ }
+ if (resource == null)
+ throw new ClassNotFoundException(className + " not found in " + this);
+
+ // Try to read the class data, create the CodeSource, Package and
+ // construct the class (and watch out for those nasty IOExceptions)
+ try
+ {
+ byte[] data;
+ InputStream in = resource.getInputStream();
+ try
+ {
+ int length = resource.getLength();
+ if (length != -1)
+ {
+ // We know the length of the data.
+ // Just try to read it in all at once
+ data = new byte[length];
+ int pos = 0;
+ while (length - pos > 0)
+ {
+ int len = in.read(data, pos, length - pos);
+ if (len == -1)
+ throw new EOFException("Not enough data reading from: "
+ + in);
+ pos += len;
+ }
+ }
+ else
+ {
+ // We don't know the data length.
+ // Have to read it in chunks.
+ ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+ byte[] b = new byte[4096];
+ int l = 0;
+ while (l != -1)
+ {
+ l = in.read(b);
+ if (l != -1)
+ out.write(b, 0, l);
+ }
+ data = out.toByteArray();
+ }
+ }
+ finally
+ {
+ in.close();
+ }
+ final byte[] classData = data;
+
+ // Now get the CodeSource
+ final CodeSource source = resource.getCodeSource();
+
+ // Find out package name
+ String packageName = null;
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot != -1)
+ packageName = className.substring(0, lastDot);
+
+ if (packageName != null && getPackage(packageName) == null)
+ {
+ // define the package
+ Manifest manifest = resource.getLoader().getManifest();
+ if (manifest == null)
+ definePackage(packageName, null, null, null, null, null, null,
+ null);
+ else
+ definePackage(packageName, manifest,
+ resource.getLoader().getBaseURL());
+ }
+
+ // And finally construct the class!
+ SecurityManager sm = System.getSecurityManager();
+ Class result = null;
+ if (sm != null && securityContext != null)
+ {
+ result = AccessController.doPrivileged
+ (new PrivilegedAction<Class>()
+ {
+ public Class run()
+ {
+ return defineClass(className, classData,
+ 0, classData.length,
+ source);
+ }
+ }, securityContext);
+ }
+ else
+ result = defineClass(className, classData, 0, classData.length, source);
+
+ // Avoid NullPointerExceptions.
+ Certificate[] resourceCertificates = resource.getCertificates();
+ if(resourceCertificates != null)
+ super.setSigners(result, resourceCertificates);
+
+ return result;
+ }
+ catch (IOException ioe)
+ {
+ throw new ClassNotFoundException(className + " not found in " + this, ioe);
+ }
+ }
+
+ // Cached String representation of this URLClassLoader
+ private String thisString;
+
+ /**
+ * Returns a String representation of this URLClassLoader giving the
+ * actual Class name, the URLs that are searched and the parent
+ * ClassLoader.
+ */
+ public String toString()
+ {
+ synchronized (this)
+ {
+ if (thisString == null)
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ sb.append(this.getClass().getName());
+ sb.append("{urls=[" );
+ URL[] thisURLs = getURLs();
+ for (int i = 0; i < thisURLs.length; i++)
+ {
+ sb.append(thisURLs[i]);
+ if (i < thisURLs.length - 1)
+ sb.append(',');
+ }
+ sb.append(']');
+ sb.append(", parent=");
+ sb.append(getParent());
+ sb.append('}');
+ thisString = sb.toString();
+ }
+ return thisString;
+ }
+ }
+
+ /**
+ * Finds the first occurrence of a resource that can be found. The locations
+ * are searched in the order they were added to the URLClassLoader.
+ *
+ * @param resourceName the resource name to look for
+ * @return the URLResource for the resource if found, null otherwise
+ */
+ private Resource findURLResource(String resourceName)
+ {
+ int max = urlinfos.size();
+ for (int i = 0; i < max; i++)
+ {
+ URLLoader loader = (URLLoader) urlinfos.elementAt(i);
+ if (loader == null)
+ continue;
+
+ Resource resource = loader.getResource(resourceName);
+ if (resource != null)
+ return resource;
+ }
+ return null;
+ }
+
+ /**
+ * Finds the first occurrence of a resource that can be found.
+ *
+ * @param resourceName the resource name to look for
+ * @return the URL if found, null otherwise
+ */
+ public URL findResource(String resourceName)
+ {
+ Resource resource = findURLResource(resourceName);
+ if (resource != null)
+ return resource.getURL();
+
+ // Resource not found
+ return null;
+ }
+
+ /**
+ * Finds all the resources with a particular name from all the locations.
+ *
+ * @param resourceName the name of the resource to lookup
+ * @return a (possible empty) enumeration of URLs where the resource can be
+ * found
+ * @exception IOException when an error occurs accessing one of the
+ * locations
+ */
+ public Enumeration<URL> findResources(String resourceName)
+ throws IOException
+ {
+ Vector<URL> resources = new Vector<URL>();
+ int max = urlinfos.size();
+ for (int i = 0; i < max; i++)
+ {
+ URLLoader loader = (URLLoader) urlinfos.elementAt(i);
+ Resource resource = loader.getResource(resourceName);
+ if (resource != null)
+ resources.add(resource.getURL());
+ }
+ return resources.elements();
+ }
+
+ /**
+ * Returns the permissions needed to access a particular code
+ * source. These permissions includes those returned by
+ * <code>SecureClassLoader.getPermissions()</code> and the actual
+ * permissions to access the objects referenced by the URL of the
+ * code source. The extra permissions added depend on the protocol
+ * and file portion of the URL in the code source. If the URL has
+ * the "file" protocol ends with a '/' character then it must be a
+ * directory and a file Permission to read everything in that
+ * directory and all subdirectories is added. If the URL had the
+ * "file" protocol and doesn't end with a '/' character then it must
+ * be a normal file and a file permission to read that file is
+ * added. If the <code>URL</code> has any other protocol then a
+ * socket permission to connect and accept connections from the host
+ * portion of the URL is added.
+ *
+ * @param source The codesource that needs the permissions to be accessed
+ * @return the collection of permissions needed to access the code resource
+ * @see java.security.SecureClassLoader#getPermissions(CodeSource)
+ */
+ protected PermissionCollection getPermissions(CodeSource source)
+ {
+ // XXX - This implementation does exactly as the Javadoc describes.
+ // But maybe we should/could use URLConnection.getPermissions()?
+ // First get the permissions that would normally be granted
+ PermissionCollection permissions = super.getPermissions(source);
+
+ // Now add any extra permissions depending on the URL location.
+ URL url = source.getLocation();
+ String protocol = url.getProtocol();
+ if (protocol.equals("file"))
+ {
+ String file = url.getFile();
+
+ // If the file end in / it must be an directory.
+ if (file.endsWith("/") || file.endsWith(File.separator))
+ {
+ // Grant permission to read everything in that directory and
+ // all subdirectories.
+ permissions.add(new FilePermission(file + "-", "read"));
+ }
+ else
+ {
+ // It is a 'normal' file.
+ // Grant permission to access that file.
+ permissions.add(new FilePermission(file, "read"));
+ }
+ }
+ else
+ {
+ // Grant permission to connect to and accept connections from host
+ String host = url.getHost();
+ if (host != null)
+ permissions.add(new SocketPermission(host, "connect,accept"));
+ }
+
+ return permissions;
+ }
+
+ /**
+ * Returns all the locations that this class loader currently uses the
+ * resolve classes and resource. This includes both the initially supplied
+ * URLs as any URLs added later by the loader.
+ * @return All the currently used URLs
+ */
+ public URL[] getURLs()
+ {
+ return (URL[]) urls.toArray(new URL[urls.size()]);
+ }
+
+ /**
+ * Creates a new instance of a <code>URLClassLoader</code> that gets
+ * classes from the supplied <code>URL</code>s. This class loader
+ * will have as parent the standard system class loader.
+ *
+ * @param urls the initial URLs used to resolve classes and
+ * resources
+ *
+ * @return the class loader
+ *
+ * @exception SecurityException when the calling code does not have
+ * permission to access the given <code>URL</code>s
+ */
+ public static URLClassLoader newInstance(URL[] urls)
+ throws SecurityException
+ {
+ return newInstance(urls, null);
+ }
+
+ /**
+ * Creates a new instance of a <code>URLClassLoader</code> that gets
+ * classes from the supplied <code>URL</code>s and with the supplied
+ * loader as parent class loader.
+ *
+ * @param urls the initial URLs used to resolve classes and
+ * resources
+ * @param parent the parent class loader
+ *
+ * @return the class loader
+ *
+ * @exception SecurityException when the calling code does not have
+ * permission to access the given <code>URL</code>s
+ */
+ public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
+ throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null)
+ return new URLClassLoader(urls, parent);
+ else
+ {
+ final Object securityContext = sm.getSecurityContext();
+
+ // XXX - What to do with anything else then an AccessControlContext?
+ if (! (securityContext instanceof AccessControlContext))
+ throw new SecurityException("securityContext must be AccessControlContext: "
+ + securityContext);
+
+ URLClassLoader loader =
+ AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>()
+ {
+ public URLClassLoader run()
+ {
+ return new URLClassLoader(parent,
+ (AccessControlContext) securityContext);
+ }
+ });
+ loader.addURLs(urls);
+ return loader;
+ }
+ }
+}
diff --git a/libjava/classpath/java/net/URLConnection.java b/libjava/classpath/java/net/URLConnection.java
new file mode 100644
index 000000000..e9365a3e0
--- /dev/null
+++ b/libjava/classpath/java/net/URLConnection.java
@@ -0,0 +1,1150 @@
+/* URLConnection.java -- Abstract superclass for reading from URL's
+ Copyright (C) 1998, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AllPermission;
+import java.security.Permission;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: One guessContentTypeFrom... methods not implemented.
+ * getContent method assumes content type from response; see comment there.
+ */
+/**
+ * This class models a connection that retrieves the information pointed
+ * to by a URL object. This is typically a connection to a remote node
+ * on the network, but could be a simple disk read.
+ * <p>
+ * A URLConnection object is normally created by calling the openConnection()
+ * method of a URL object. This method is somewhat misnamed because it does
+ * not actually open the connection. Instead, it return an unconnected
+ * instance of this object. The caller then has the opportunity to set
+ * various connection options prior to calling the actual connect() method.
+ * <p>
+ * After the connection has been opened, there are a number of methods in
+ * this class that access various attributes of the data, typically
+ * represented by headers sent in advance of the actual data itself.
+ * <p>
+ * Also of note are the getInputStream and getContent() methods which allow
+ * the caller to retrieve the actual data from the connection. Note that
+ * for some types of connections, writing is also allowed. The setDoOutput()
+ * method must be called prior to connecing in order to enable this, then
+ * the getOutputStream method called after the connection in order to
+ * obtain a stream to write the output to.
+ * <p>
+ * The getContent() method is of particular note. This method returns an
+ * Object that encapsulates the data returned. There is no way do determine
+ * the type of object that will be returned in advance. This is determined
+ * by the actual content handlers as described in the description of that
+ * method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class URLConnection
+{
+ /**
+ * This is an object that maps filenames to MIME types. The interface
+ * to do this is implemented by this class, so just create an empty
+ * instance and store it here.
+ */
+ private static FileNameMap fileNameMap;
+
+ /**
+ * This is the ContentHandlerFactory set by the caller, if any
+ */
+ private static ContentHandlerFactory factory;
+
+ /**
+ * This is the default value that will be used to determine whether or
+ * not user interaction should be allowed.
+ */
+ private static boolean defaultAllowUserInteraction;
+
+ /**
+ * This is the default flag indicating whether or not to use caches to
+ * store the data returned from a server
+ */
+ private static boolean defaultUseCaches = true;
+
+ /**
+ * Default internal content handler factory.
+ */
+ private static ContentHandlerFactory defaultFactory
+ = new gnu.java.net.DefaultContentHandlerFactory();
+
+ /**
+ * This variable determines whether or not interaction is allowed with
+ * the user. For example, to prompt for a username and password.
+ */
+ protected boolean allowUserInteraction;
+
+ /**
+ * Indicates whether or not a connection has been established to the
+ * destination specified in the URL
+ */
+ protected boolean connected;
+
+ /**
+ * Indicates whether or not input can be read from this URL
+ */
+ protected boolean doInput = true;
+
+ /**
+ * Indicates whether or not output can be sent to this URL
+ */
+ protected boolean doOutput;
+
+ /**
+ * If this flag is set, the protocol is allowed to cache data whenever
+ * it can (caching is not guaranteed). If it is not set, the protocol
+ * must a get a fresh copy of the data.
+ * <p>
+ * This field is set by the setUseCaches method and returned by the
+ * getUseCaches method.
+ *
+ * Its default value is that determined by the last invocation of
+ * setDefaultUseCaches
+ */
+ protected boolean useCaches;
+
+ /**
+ * If this value is non-zero, then the connection will only attempt to
+ * fetch the document pointed to by the URL if the document has been
+ * modified more recently than the date set in this variable. That date
+ * should be specified as the number of seconds since 1/1/1970 GMT.
+ */
+ protected long ifModifiedSince;
+
+ /**
+ * This is the URL associated with this connection
+ */
+ protected URL url;
+
+ private static SimpleDateFormat[] dateFormats;
+ private static boolean dateformats_initialized;
+
+ /**
+ * The connection timeout period.
+ */
+ private int connectTimeout;
+
+ /**
+ * The read timeout period.
+ */
+ private int readTimeout;
+
+ /* Cached ParsePosition, used when parsing dates. */
+ private ParsePosition position;
+
+ /**
+ * Creates a URL connection to a given URL. A real connection is not made.
+ * Use <code>connect()</code> to do this.
+ *
+ * @param url The Object to create the URL connection to
+ *
+ * @see URLConnection#connect()
+ */
+ protected URLConnection(URL url)
+ {
+ // Set up all our instance variables
+ this.url = url;
+ allowUserInteraction = defaultAllowUserInteraction;
+ useCaches = defaultUseCaches;
+ }
+
+ /**
+ * Establishes the actual connection to the URL associated with this
+ * connection object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract void connect() throws IOException;
+
+ /**
+ * Returns the URL object associated with this connection
+ *
+ * @return The URL for this connection.
+ */
+ public URL getURL()
+ {
+ return url;
+ }
+
+ /**
+ * Returns the connection timeout speed, in milliseconds, or zero if
+ * the timeout is infinite or not set.
+ *
+ * @return The timeout.
+ *
+ * @since 1.5
+ */
+ public int getConnectTimeout()
+ {
+ return connectTimeout;
+ }
+
+ /**
+ * Set the connection timeout speed, in milliseconds, or zero if the timeout
+ * is to be considered infinite. Note that in certain socket
+ * implementations/platforms this method may not have any effect.
+ *
+ * Throws an <code>IllegalArgumentException</code> if timeout < 0.
+ *
+ * @param timeout the timeout, in milliseconds.
+ *
+ * @since 1.5
+ */
+ public void setConnectTimeout(int timeout)
+ throws IllegalArgumentException
+ {
+ if( timeout < 0 )
+ throw new IllegalArgumentException("Timeout must be 0 or positive.");
+ connectTimeout = timeout;
+ }
+
+ /**
+ * Returns the read timeout, in milliseconds, or zero if the timeout
+ * is infinite or not set.
+ *
+ * @return The timeout.
+ *
+ * @see #setReadTimeout
+ *
+ * @since 1.5
+ */
+ public int getReadTimeout()
+ {
+ return readTimeout;
+ }
+
+ /**
+ * Set the read timeout, in milliseconds, or zero if the timeout
+ * is to be considered infinite. Note that in certain socket
+ * implementations/platforms this method may not have any effect.
+ *
+ * Throws an <code>IllegalArgumentException</code> if timeout < 0.
+ *
+ * @param timeout - The timeout, in milliseconds.
+ *
+ * @throws IllegalArgumentException if timeout is negative.
+ *
+ * @see #getReadTimeout
+ *
+ * @since 1.5
+ */
+ public void setReadTimeout(int timeout)
+ throws IllegalArgumentException
+ {
+ if( timeout < 0 )
+ throw new IllegalArgumentException("Timeout must be 0 or positive.");
+ readTimeout = timeout;
+ }
+
+ /**
+ * Returns the value of the content-length header field or -1 if the value
+ * is not known or not present.
+ *
+ * @return The content-length field
+ */
+ public int getContentLength()
+ {
+ return getHeaderFieldInt("content-length", -1);
+ }
+
+ /**
+ * Returns the the content-type of the data pointed to by the URL. This
+ * method first tries looking for a content-type header. If that is not
+ * present, it attempts to use the file name to determine the content's
+ * MIME type. If that is unsuccessful, the method returns null. The caller
+ * may then still attempt to determine the MIME type by a call to
+ * guessContentTypeFromStream()
+ *
+ * @return The content MIME type
+ */
+ public String getContentType()
+ {
+ return getHeaderField("content-type");
+ }
+
+ /**
+ * Returns the value of the content-encoding field or null if it is not
+ * known or not present.
+ *
+ * @return The content-encoding field
+ */
+ public String getContentEncoding()
+ {
+ return getHeaderField("content-encoding");
+ }
+
+ /**
+ * Returns the value of the expires header or 0 if not known or present.
+ * If populated, the return value is number of seconds since midnight
+ * on 1/1/1970 GMT.
+ *
+ * @return The expiration time.
+ */
+ public long getExpiration()
+ {
+ return getHeaderFieldDate("expires", 0L);
+ }
+
+ /**
+ * Returns the date of the document pointed to by the URL as reported in
+ * the date field of the header or 0 if the value is not present or not
+ * known. If populated, the return value is number of seconds since
+ * midnight on 1/1/1970 GMT.
+ *
+ * @return The document date
+ */
+ public long getDate()
+ {
+ return getHeaderFieldDate("date", 0L);
+ }
+
+ /**
+ * Returns the value of the last-modified header field or 0 if not known known
+ * or not present. If populated, the return value is the number of seconds
+ * since midnight on 1/1/1970.
+ *
+ * @return The last modified time
+ */
+ public long getLastModified()
+ {
+ return getHeaderFieldDate("last-modified", 0L);
+ }
+
+ /**
+ * Return a String representing the header value at the specified index.
+ * This allows the caller to walk the list of header fields. The analogous
+ * {@link #getHeaderField(int)} method allows access to the corresponding
+ * key for this header field
+ *
+ * @param index The index into the header field list to retrieve the value for
+ *
+ * @return The header value or null if index is past the end of the headers
+ */
+ public String getHeaderField(int index)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * Returns a String representing the value of the header field having
+ * the named key. Returns null if the header field does not exist.
+ *
+ * @param name The key of the header field
+ *
+ * @return The value of the header field as a String
+ */
+ public String getHeaderField(String name)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * Returns an unmodifiable Map containing all sent header fields.
+ *
+ * @return The map of header fields. The map consists of String keys with
+ * an unmodifiable List of String objects as value.
+ *
+ * @since 1.4
+ */
+ public Map<String,List<String>> getHeaderFields()
+ {
+ // Subclasses for specific protocols override this.
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Returns the value of the named header field as an int. If the field
+ * is not present or cannot be parsed as an integer, the default value
+ * will be returned.
+ *
+ * @param name The header field key to lookup
+ * @param defaultValue The defaule value if the header field is not found
+ * or can't be parsed.
+ *
+ * @return The value of the header field or the default value if the field
+ * is missing or malformed
+ */
+ public int getHeaderFieldInt(String name, int defaultValue)
+ {
+ String value = getHeaderField(name);
+
+ if (value == null)
+ return defaultValue;
+
+ try
+ {
+ return Integer.parseInt(value);
+ }
+ catch (NumberFormatException e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of the named header field as a date. This date will
+ * be the number of seconds since midnight 1/1/1970 GMT or the default
+ * value if the field is not present or cannot be converted to a date.
+ *
+ * @param name The name of the header field
+ * @param defaultValue The default date if the header field is not found
+ * or can't be converted.
+ *
+ * @return The date value of the header filed or the default value
+ * if the field is missing or malformed
+ */
+ public long getHeaderFieldDate(String name, long defaultValue)
+ {
+ if (! dateformats_initialized)
+ initializeDateFormats();
+
+ if (position == null)
+ position = new ParsePosition(0);
+
+ long result = defaultValue;
+ String str = getHeaderField(name);
+
+ if (str != null)
+ {
+ for (int i = 0; i < dateFormats.length; i++)
+ {
+ SimpleDateFormat df = dateFormats[i];
+ position.setIndex(0);
+ position.setErrorIndex(0);
+ Date date = df.parse(str, position);
+ if (date != null)
+ return date.getTime();
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a String representing the header key at the specified index.
+ * This allows the caller to walk the list of header fields. The analogous
+ * {@link #getHeaderField(int)} method allows access to the corresponding
+ * value for this tag.
+ *
+ * @param index The index into the header field list to retrieve the key for.
+ *
+ * @return The header field key or null if index is past the end
+ * of the headers.
+ */
+ public String getHeaderFieldKey(int index)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * This method returns the content of the document pointed to by the
+ * URL as an Object. The type of object depends on the MIME type of
+ * the object and particular content hander loaded. Most text type
+ * content handlers will return a subclass of
+ * <code>InputStream</code>. Images usually return a class that
+ * implements <code>ImageProducer</code>. There is not guarantee
+ * what type of object will be returned, however.
+ *
+ * <p>This class first determines the MIME type of the content, then
+ * creates a ContentHandler object to process the input. If the
+ * <code>ContentHandlerFactory</code> is set, then that object is
+ * called to load a content handler, otherwise a class called
+ * gnu.java.net.content.&lt;content_type&gt; is tried. If this
+ * handler does not exist, the method will simple return the
+ * <code>InputStream</code> returned by
+ * <code>getInputStream()</code>. Note that the default
+ * implementation of <code>getInputStream()</code> throws a
+ * <code>UnknownServiceException</code> so subclasses are encouraged
+ * to override this method.</p>
+ *
+ * @return the content
+ *
+ * @exception IOException If an error with the connection occurs.
+ * @exception UnknownServiceException If the protocol does not support the
+ * content type at all.
+ */
+ public Object getContent() throws IOException
+ {
+ if (!connected)
+ connect();
+
+ // 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 type = getContentType();
+ ContentHandler ch = getContentHandler(type);
+
+ if (ch != null)
+ return ch.getContent(this);
+
+ return getInputStream();
+ }
+
+ /**
+ * Retrieves the content of this URLConnection
+ *
+ * @param classes The allowed classes for the content
+ *
+ * @return the content
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support the
+ * content type
+ */
+ public Object getContent(Class[] classes)
+ throws IOException
+ {
+ if (! connected)
+ connect();
+ String type = getContentType();
+ ContentHandler ch = getContentHandler(type);
+ if (ch != null)
+ return ch.getContent(this, classes);
+ throw new UnknownServiceException("protocol does not support the content type");
+ }
+
+ /**
+ * This method returns a <code>Permission</code> object representing the
+ * permissions required to access this URL. This method returns
+ * <code>java.security.AllPermission</code> by default. Subclasses should
+ * override it to return a more specific permission. For example, an
+ * HTTP URL should return an instance of <code>SocketPermission</code>
+ * for the appropriate host and port.
+ * <p>
+ * Note that because of items such as HTTP redirects, the permission
+ * object returned might be different before and after connecting.
+ *
+ * @return A Permission object
+ *
+ * @exception IOException If the computation of the permission requires
+ * network or file I/O and an exception occurs while computing it
+ */
+ public Permission getPermission() throws IOException
+ {
+ // Subclasses may override this.
+ return new AllPermission();
+ }
+
+ /**
+ * Returns an InputStream for this connection. As this default
+ * implementation returns null, subclasses should override this method
+ *
+ * @return An InputStream for this connection
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support input
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol()
+ + " does not support input.");
+ }
+
+ /**
+ * Returns an OutputStream for this connection. As this default
+ * implementation returns null, subclasses should override this method
+ *
+ * @return An OutputStream for this connection
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support output
+ */
+ public OutputStream getOutputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol()
+ + " does not support output.");
+ }
+
+ /**
+ * The methods prints the value of this object as a String by calling the
+ * toString() method of its associated URL. Overrides Object.toString()
+ *
+ * @return A String representation of this object
+ */
+ public String toString()
+ {
+ return this.getClass().getName() + ":" + url.toString();
+ }
+
+ /**
+ * Sets the value of a flag indicating whether or not input is going
+ * to be done for this connection. This default to true unless the
+ * doOutput flag is set to false, in which case this defaults to false.
+ *
+ * @param input <code>true</code> if input is to be done,
+ * <code>false</code> otherwise
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setDoInput(boolean input)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ doInput = input;
+ }
+
+ /**
+ * Returns the value of a flag indicating whether or not input is going
+ * to be done for this connection. This default to true unless the
+ * doOutput flag is set to false, in which case this defaults to false.
+ *
+ * @return true if input is to be done, false otherwise
+ */
+ public boolean getDoInput()
+ {
+ return doInput;
+ }
+
+ /**
+ * Sets a boolean flag indicating whether or not output will be done
+ * on this connection. The default value is false, so this method can
+ * be used to override the default
+ *
+ * @param output ture if output is to be done, false otherwise
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setDoOutput(boolean output)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ doOutput = output;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not output will be done
+ * on this connection. This defaults to false.
+ *
+ * @return true if output is to be done, false otherwise
+ */
+ public boolean getDoOutput()
+ {
+ return doOutput;
+ }
+
+ /**
+ * Sets a boolean flag indicating whether or not user interaction is
+ * allowed for this connection. (For example, in order to prompt for
+ * username and password info.
+ *
+ * @param allow true if user interaction should be allowed, false otherwise.
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setAllowUserInteraction(boolean allow)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ allowUserInteraction = allow;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not user interaction is
+ * allowed for this connection. (For example, in order to prompt for
+ * username and password info.
+ *
+ * @return true if user interaction is allowed, false otherwise
+ */
+ public boolean getAllowUserInteraction()
+ {
+ return allowUserInteraction;
+ }
+
+ /**
+ * Sets the default flag for whether or not interaction with a user
+ * is allowed. This will be used for all connections unless overridden
+ *
+ * @param allow true to allow user interaction, false otherwise
+ */
+ public static void setDefaultAllowUserInteraction(boolean allow)
+ {
+ defaultAllowUserInteraction = allow;
+ }
+
+ /**
+ * Returns the default flag for whether or not interaction with a user
+ * is allowed. This will be used for all connections unless overridden
+ *
+ * @return true if user interaction is allowed, false otherwise
+ */
+ public static boolean getDefaultAllowUserInteraction()
+ {
+ return defaultAllowUserInteraction;
+ }
+
+ /**
+ * Sets a boolean flag indicating whether or not caching will be used
+ * (if possible) to store data downloaded via the connection.
+ *
+ * @param usecaches The new value
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setUseCaches(boolean usecaches)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ useCaches = usecaches;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not caching will be used
+ * (if possible) to store data downloaded via the connection.
+ *
+ * @return true if caching should be used if possible, false otherwise
+ */
+ public boolean getUseCaches()
+ {
+ return useCaches;
+ }
+
+ /**
+ * Sets the ifModified since instance variable. If this value is non
+ * zero and the underlying protocol supports it, the actual document will
+ * not be fetched unless it has been modified since this time. The value
+ * passed should be 0 if this feature is to be disabled or the time expressed
+ * as the number of seconds since midnight 1/1/1970 GMT otherwise.
+ *
+ * @param ifmodifiedsince The new value in milliseconds
+ * since January 1, 1970 GMT
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setIfModifiedSince(long ifmodifiedsince)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ ifModifiedSince = ifmodifiedsince;
+ }
+
+ /**
+ * Returns the ifModified since instance variable. If this value is non
+ * zero and the underlying protocol supports it, the actual document will
+ * not be fetched unless it has been modified since this time. The value
+ * returned will be 0 if this feature is disabled or the time expressed
+ * as the number of seconds since midnight 1/1/1970 GMT otherwise
+ *
+ * @return The ifModifiedSince value
+ */
+ public long getIfModifiedSince()
+ {
+ return ifModifiedSince;
+ }
+
+ /**
+ * Returns the default value used to determine whether or not caching
+ * of documents will be done when possible.
+ *
+ * @return true if caches will be used, false otherwise
+ */
+ public boolean getDefaultUseCaches()
+ {
+ return defaultUseCaches;
+ }
+
+ /**
+ * Sets the default value used to determine whether or not caching
+ * of documents will be done when possible.
+ *
+ * @param use true to use caches if possible by default, false otherwise
+ */
+ public void setDefaultUseCaches(boolean use)
+ {
+ defaultUseCaches = use;
+ }
+
+ /**
+ * Sets the value of the named request property.
+ * This method does overwrite the value of existing properties with
+ * the new value.
+ *
+ * @param key The name of the property
+ * @param value The value of the property
+ *
+ * @exception IllegalStateException If already connected
+ * @exception NullPointerException If key is null
+ *
+ * @see URLConnection#getRequestProperty(String key)
+ * @see URLConnection#addRequestProperty(String key, String value)
+ *
+ * @since 1.4
+ */
+ public void setRequestProperty(String key, String value)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ if (key == null)
+ throw new NullPointerException("key is null");
+
+ // Do nothing unless overridden by subclasses that support setting
+ // header fields in the request.
+ }
+
+ /**
+ * Adds a new request property by a key/value pair.
+ * This method does not overwrite existing properties with the same key.
+ *
+ * @param key Key of the property to add
+ * @param value Value of the Property to add
+ *
+ * @exception IllegalStateException If already connected
+ * @exception NullPointerException If key is null
+ *
+ * @see URLConnection#getRequestProperty(String)
+ * @see URLConnection#setRequestProperty(String, String)
+ *
+ * @since 1.4
+ */
+ public void addRequestProperty(String key, String value)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ if (key == null)
+ throw new NullPointerException("key is null");
+
+ // Do nothing unless overridden by subclasses that support adding
+ // header fields in the request.
+ }
+
+ /**
+ * Returns the value of the named request property.
+ *
+ * @param key The name of the property
+ *
+ * @return Value of the property, or <code>null</code> if key is null.
+ *
+ * @exception IllegalStateException If already connected
+ *
+ * @see URLConnection#setRequestProperty(String, String)
+ * @see URLConnection#addRequestProperty(String, String)
+ */
+ public String getRequestProperty(String key)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ // Overridden by subclasses that support reading header fields from the
+ // request.
+ return null;
+ }
+
+ /**
+ * Returns an unmodifiable Map containing the request properties.
+ *
+ * @return The map of properties. The map consists of String keys with an
+ * unmodifiable List of String objects as value.
+ *
+ * @exception IllegalStateException If already connected
+ *
+ * @since 1.4
+ */
+ public Map<String,List<String>> getRequestProperties()
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ // Overridden by subclasses that support reading header fields from the
+ // request.
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Sets the default value of a request property. This will be used
+ * for all connections unless the value of the property is manually
+ * overridden.
+ *
+ * @param key The request property name the default is being set for
+ * @param value The value to set the default to
+ *
+ * @deprecated 1.3 The method setRequestProperty should be used instead.
+ * This method does nothing now.
+ *
+ * @see URLConnection#setRequestProperty(String, String)
+ */
+ public static void setDefaultRequestProperty(String key, String value)
+ {
+ // This method does nothing since JDK 1.3.
+ }
+
+ /**
+ * Returns the default value of a request property. This will be used
+ * for all connections unless the value of the property is manually
+ * overridden.
+ *
+ * @param key The request property to return the default value of
+ *
+ * @return The value of the default property or null if not available
+ *
+ * @deprecated 1.3 The method getRequestProperty should be used instead.
+ * This method does nothing now.
+ *
+ * @see URLConnection#getRequestProperty(String)
+ */
+ public static String getDefaultRequestProperty(String key)
+ {
+ // This method does nothing since JDK 1.3.
+ return null;
+ }
+
+ /**
+ * Sets the ContentHandlerFactory for an application. This can be called
+ * once and only once. If it is called again, then an Error is thrown.
+ * Unlike for other set factory methods, this one does not do a security
+ * check prior to setting the factory.
+ *
+ * @param factory The ContentHandlerFactory for this application
+ *
+ * @exception Error If the factory has already been defined
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static synchronized void setContentHandlerFactory(ContentHandlerFactory factory)
+ {
+ if (URLConnection.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();
+
+ URLConnection.factory = factory;
+ }
+
+ /**
+ * Returns the MIME type of a file based on the name of the file. This
+ * works by searching for the file's extension in a list of file extensions
+ * and returning the MIME type associated with it. If no type is found,
+ * then a MIME type of "application/octet-stream" will be returned.
+ *
+ * @param filename The filename to determine the MIME type for
+ *
+ * @return The MIME type String
+ *
+ * @specnote public since JDK 1.4
+ */
+ public static String guessContentTypeFromName(String filename)
+ {
+ return getFileNameMap().getContentTypeFor(filename.toLowerCase());
+ }
+
+ /**
+ * Returns the MIME type of a stream based on the first few characters
+ * at the beginning of the stream. This routine can be used to determine
+ * the MIME type if a server is believed to be returning an incorrect
+ * MIME type. This method returns "application/octet-stream" if it
+ * cannot determine the MIME type.
+ * <p>
+ * NOTE: Overriding MIME types sent from the server can be obnoxious
+ * to user's. See Internet Exploder 4 if you don't believe me.
+ *
+ * @param is The InputStream to determine the MIME type from
+ *
+ * @return The MIME type
+ *
+ * @exception IOException If an error occurs
+ */
+ public static String guessContentTypeFromStream(InputStream is)
+ throws IOException
+ {
+ String result = VMURLConnection.guessContentTypeFromStream(is);
+ if (result == null)
+ return "application/octet-stream";
+ return result;
+ }
+
+ /**
+ * This method returns the <code>FileNameMap</code> object being used
+ * to decode MIME types by file extension.
+ *
+ * @return The <code>FileNameMap</code>.
+ *
+ * @since 1.2
+ */
+ public static synchronized FileNameMap getFileNameMap()
+ {
+ // Delayed initialization.
+ if (fileNameMap == null)
+ fileNameMap = new MimeTypeMapper();
+
+ return fileNameMap;
+ }
+
+ /**
+ * This method sets the <code>FileNameMap</code> object being used
+ * to decode MIME types by file extension.
+ *
+ * @param map The <code>FileNameMap</code>.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ *
+ * @since 1.2
+ */
+ public static synchronized void setFileNameMap(FileNameMap map)
+ {
+ // Throw an exception if an extant security manager precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ fileNameMap = map;
+ }
+
+ private ContentHandler getContentHandler(String contentType)
+ {
+ // No content type so just handle it as the default.
+ if (contentType == null || contentType.equals(""))
+ return null;
+
+ ContentHandler handler = null;
+
+ // If a non-default factory has been set, use it.
+ if (factory != null)
+ handler = factory.createContentHandler(contentType);
+
+ // Now try default factory. Using this factory to instantiate built-in
+ // content handlers is preferable
+ if (handler == null)
+ handler = defaultFactory.createContentHandler(contentType);
+
+ // User-set factory has not returned a handler. Use the default search
+ // algorithm.
+ 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 = SystemProperties.getProperty("java.content.handler.pkgs");
+ propVal = (((propVal == null) ? "" : (propVal + "|"))
+ + "gnu.java.net.content|sun.net.www.content");
+
+ // Deal with "Content-Type: text/html; charset=ISO-8859-1".
+ int parameterBegin = contentType.indexOf(';');
+ if (parameterBegin >= 1)
+ contentType = contentType.substring(0, parameterBegin);
+ contentType = contentType.trim();
+
+ // Replace the '/' character in the content type with '.' and
+ // all other non-alphabetic, non-numeric characters with '_'.
+ 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.
+ StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
+ 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 && pkgPrefix.hasMoreTokens());
+ }
+
+ return handler;
+ }
+
+ // We don't put these in a static initializer, because it creates problems
+ // with initializer co-dependency: SimpleDateFormat's constructors
+ // eventually depend on URLConnection (via the java.text.*Symbols classes).
+ private static synchronized void initializeDateFormats()
+ {
+ if (dateformats_initialized)
+ return;
+
+ Locale locale = new Locale("En", "Us", "Unix");
+ dateFormats = new SimpleDateFormat[3];
+ dateFormats[0] =
+ new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale);
+ dateFormats[1] =
+ new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale);
+ dateFormats[2] = new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale);
+ dateformats_initialized = true;
+ }
+}
diff --git a/libjava/classpath/java/net/URLDecoder.java b/libjava/classpath/java/net/URLDecoder.java
new file mode 100644
index 000000000..73cedea5c
--- /dev/null
+++ b/libjava/classpath/java/net/URLDecoder.java
@@ -0,0 +1,182 @@
+/* URLDecoder.java -- Class to decode URL's from encoded form.
+ Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * This utility class contains static methods that converts a
+ * string encoded in the x-www-form-urlencoded format to the original
+ * text. The x-www-form-urlencoded format replaces certain disallowed
+ * characters with encoded equivalents. All upper case and lower case
+ * letters in the US alphabet remain as is, the space character (' ')
+ * is replaced with '+' sign, and all other characters are converted to a
+ * "%XX" format where XX is the hexadecimal representation of that character
+ * in a given character encoding (default is "UTF-8").
+ * <p>
+ * This method is very useful for decoding strings sent to CGI scripts
+ *
+ * Written using on-line Java Platform 1.2/1.4 API Specification.
+ * Status: Believed complete and correct.
+ *
+ * @since 1.2
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com) (documentation comments)
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class URLDecoder
+{
+ /**
+ * Public contructor. Note that this class has only static methods.
+ */
+ public URLDecoder()
+ {
+ }
+
+ /**
+ * This method translates the passed in string from x-www-form-urlencoded
+ * format using the default encoding "UTF-8" to decode the hex encoded
+ * unsafe characters.
+ *
+ * @param s the String to convert
+ *
+ * @return the converted String
+ *
+ * @deprecated
+ */
+ public static String decode(String s)
+ {
+ try
+ {
+ return decode(s, "UTF-8");
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ // Should never happen since UTF-8 encoding should always be supported
+ return s;
+ }
+ }
+
+ /**
+ * This method translates the passed in string from x-www-form-urlencoded
+ * format using the given character encoding to decode the hex encoded
+ * unsafe characters.
+ *
+ * This implementation will decode the string even if it contains
+ * unsafe characters (characters that should have been encoded) or if the
+ * two characters following a % do not represent a hex encoded byte.
+ * In those cases the unsafe character or the % character will be added
+ * verbatim to the decoded result.
+ *
+ * @param s the String to convert
+ * @param encoding the character encoding to use the decode the hex encoded
+ * unsafe characters
+ *
+ * @return the converted String
+ *
+ * @exception UnsupportedEncodingException If the named encoding is not
+ * supported
+ *
+ * @since 1.4
+ */
+ public static String decode(String s, String encoding)
+ throws UnsupportedEncodingException
+ {
+ // First convert all '+' characters to spaces.
+ String str = s.replace('+', ' ');
+
+ // Then go through the whole string looking for byte encoded characters
+ int i;
+ int start = 0;
+ byte[] bytes = null;
+ int length = str.length();
+ CPStringBuilder result = new CPStringBuilder(length);
+ while ((i = str.indexOf('%', start)) >= 0)
+ {
+ // Add all non-encoded characters to the result buffer
+ result.append(str.substring(start, i));
+ start = i;
+
+ // Get all consecutive encoded bytes
+ while ((i + 2 < length) && (str.charAt(i) == '%'))
+ i += 3;
+
+ // Decode all these bytes
+ if ((bytes == null) || (bytes.length < ((i - start) / 3)))
+ bytes = new byte[((i - start) / 3)];
+
+ int index = 0;
+ try
+ {
+ while (start < i)
+ {
+ String sub = str.substring(start + 1, start + 3);
+ bytes[index] = (byte) Integer.parseInt(sub, 16);
+ index++;
+ start += 3;
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ // One of the hex encoded strings was bad
+ }
+
+ // Add the bytes as characters according to the given encoding
+ result.append(new String(bytes, 0, index, encoding));
+
+ // Make sure we skip to just after a % sign
+ // There might not have been enough encoded characters after the %
+ // or the hex chars were not actually hex chars (NumberFormatException)
+ if (start < length && s.charAt(start) == '%')
+ {
+ result.append('%');
+ start++;
+ }
+ }
+
+ // Add any characters left
+ if (start < str.length())
+ result.append(str.substring(start));
+
+ return result.toString();
+ }
+} // class URLDecoder
diff --git a/libjava/classpath/java/net/URLEncoder.java b/libjava/classpath/java/net/URLEncoder.java
new file mode 100644
index 000000000..09c0f3de0
--- /dev/null
+++ b/libjava/classpath/java/net/URLEncoder.java
@@ -0,0 +1,186 @@
+/* URLEncoder.java -- Class to convert strings to a properly encoded URL
+ Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.UnsupportedEncodingException;
+
+
+/*
+ * Written using on-line Java Platform 1.2/1.4 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This utility class contains static methods that converts a
+ * string into a fully encoded URL string in x-www-form-urlencoded
+ * format. This format replaces certain disallowed characters with
+ * encoded equivalents. All upper case and lower case letters in the
+ * US alphabet remain as is, the space character (' ') is replaced with
+ * '+' sign, and all other characters are converted to a "%XX" format
+ * where XX is the hexadecimal representation of that character in a
+ * certain encoding (by default, the platform encoding, though the
+ * standard is "UTF-8").
+ * <p>
+ * This method is very useful for encoding strings to be sent to CGI scripts
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class URLEncoder
+{
+ /**
+ * This method translates the passed in string into x-www-form-urlencoded
+ * format using the default encoding. The standard encoding is
+ * "UTF-8", and the two-argument form of this method should be used
+ * instead.
+ *
+ * @param s The String to convert
+ *
+ * @return The converted String
+ *
+ * @deprecated
+ */
+ public static String encode(String s)
+ {
+ try
+ {
+ // We default to 8859_1 for compatibility with the same
+ // default elsewhere in the library.
+ return encode(s, System.getProperty("file.encoding", "8859_1"));
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ // Should never happen since default should always be supported
+ return s;
+ }
+ }
+
+ /**
+ * This method translates the passed in string into x-www-form-urlencoded
+ * format using the character encoding to hex-encode the unsafe characters.
+ *
+ * @param s The String to convert
+ * @param encoding The encoding to use for unsafe characters
+ *
+ * @return The converted String
+ *
+ * @exception UnsupportedEncodingException If the named encoding is not
+ * supported
+ *
+ * @since 1.4
+ */
+ public static String encode(String s, String encoding)
+ throws UnsupportedEncodingException
+ {
+ int length = s.length();
+ int start = 0;
+ int i = 0;
+
+ CPStringBuilder result = new CPStringBuilder(length);
+ while (true)
+ {
+ while (i < length && isSafe(s.charAt(i)))
+ i++;
+
+ // Safe character can just be added
+ result.append(s.substring(start, i));
+
+ // Are we done?
+ if (i >= length)
+ return result.toString();
+ else if (s.charAt(i) == ' ')
+ {
+ result.append('+'); // Replace space char with plus symbol.
+ i++;
+ }
+ else
+ {
+ // Get all unsafe characters
+ start = i;
+ char c;
+ while (i < length && (c = s.charAt(i)) != ' ' && ! isSafe(c))
+ i++;
+
+ // Convert them to %XY encoded strings
+ String unsafe = s.substring(start, i);
+ byte[] bytes = unsafe.getBytes(encoding);
+ for (int j = 0; j < bytes.length; j++)
+ {
+ result.append('%');
+ int val = bytes[j];
+ result.append(hex.charAt((val & 0xf0) >> 4));
+ result.append(hex.charAt(val & 0x0f));
+ }
+ }
+ start = i;
+ }
+ }
+
+ /**
+ * Private static method that returns true if the given char is either
+ * a uppercase or lowercase letter from 'a' till 'z', or a digit froim
+ * '0' till '9', or one of the characters '-', '_', '.' or '*'. Such
+ * 'safe' character don't have to be url encoded.
+ */
+ private static boolean isSafe(char c)
+ {
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.'
+ || c == '*');
+ }
+
+ /**
+ * Private constructor that does nothing. Included to avoid a default
+ * public constructor being created by the compiler.
+ */
+ private URLEncoder()
+ {
+ }
+
+ /**
+ * Used to convert to hex. We don't use Integer.toHexString, since
+ * it converts to lower case (and the Sun docs pretty clearly
+ * specify upper case here), and because it doesn't provide a
+ * leading 0.
+ */
+ private static final String hex = "0123456789ABCDEF";
+}
diff --git a/libjava/classpath/java/net/URLStreamHandler.java b/libjava/classpath/java/net/URLStreamHandler.java
new file mode 100644
index 000000000..5433aedd9
--- /dev/null
+++ b/libjava/classpath/java/net/URLStreamHandler.java
@@ -0,0 +1,541 @@
+/* URLStreamHandler.java -- Abstract superclass for all protocol handlers
+ Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * This class is the superclass of all URL protocol handlers. The URL
+ * class loads the appropriate protocol handler to establish a connection
+ * to a (possibly) remote service (eg, "http", "ftp") and to do protocol
+ * specific parsing of URL's. Refer to the URL class documentation for
+ * details on how that class locates and loads protocol handlers.
+ * <p>
+ * A protocol handler implementation should override the openConnection()
+ * method, and optionally override the parseURL() and toExternalForm()
+ * methods if necessary. (The default implementations will parse/write all
+ * URL's in the same form as http URL's). A protocol specific subclass
+ * of URLConnection will most likely need to be created as well.
+ * <p>
+ * Note that the instance methods in this class are called as if they
+ * were static methods. That is, a URL object to act on is passed with
+ * every call rather than the caller assuming the URL is stored in an
+ * instance variable of the "this" object.
+ * <p>
+ * The methods in this class are protected and accessible only to subclasses.
+ * URLStreamConnection objects are intended for use by the URL class only,
+ * not by other classes (unless those classes are implementing protocols).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ *
+ * @see URL
+ */
+public abstract class URLStreamHandler
+{
+ /**
+ * Creates a URLStreamHander
+ */
+ public URLStreamHandler()
+ {
+ }
+
+ /**
+ * Returns a URLConnection for the passed in URL. Note that this should
+ * not actually create the connection to the (possibly) remote host, but
+ * rather simply return a URLConnection object. The connect() method of
+ * URL connection is used to establish the actual connection, possibly
+ * after the caller sets up various connection options.
+ *
+ * @param url The URL to get a connection object for
+ *
+ * @return A URLConnection object for the given URL
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract URLConnection openConnection(URL url)
+ throws IOException;
+
+ /**
+ * This method parses the string passed in as a URL and set's the
+ * instance data fields in the URL object passed in to the various values
+ * parsed out of the string. The start parameter is the position to start
+ * scanning the string. This is usually the position after the ":" which
+ * terminates the protocol name. The end parameter is the position to
+ * stop scanning. This will be either the end of the String, or the
+ * position of the "#" character, which separates the "file" portion of
+ * the URL from the "anchor" portion.
+ * <p>
+ * This method assumes URL's are formatted like http protocol URL's, so
+ * subclasses that implement protocols with URL's the follow a different
+ * syntax should override this method. The lone exception is that if
+ * the protocol name set in the URL is "file", this method will accept
+ * an empty hostname (i.e., "file:///"), which is legal for that protocol
+ *
+ * @param url The URL object in which to store the results
+ * @param spec The String-ized URL to parse
+ * @param start The position in the string to start scanning from
+ * @param end The position in the string to stop scanning
+ */
+ protected void parseURL(URL url, String spec, int start, int end)
+ {
+ String host = url.getHost();
+ int port = url.getPort();
+ String file = url.getFile();
+ String ref = url.getRef();
+ String userInfo = url.getUserInfo();
+ String authority = url.getAuthority();
+ String query = null;
+
+ // On Windows we need to change \ to / for file URLs
+ char separator = File.separatorChar;
+ if (url.getProtocol().equals("file") && separator != '/')
+ {
+ file = file.replace(separator, '/');
+ spec = spec.replace(separator, '/');
+ }
+
+ if (spec.regionMatches(start, "//", 0, 2))
+ {
+ String genuineHost;
+ int hostEnd;
+ int colon;
+ int at_host;
+
+ start += 2;
+ int slash = spec.indexOf('/', start);
+ if (slash >= 0)
+ hostEnd = slash;
+ else
+ hostEnd = end;
+
+ authority = host = spec.substring(start, hostEnd);
+
+ // We first need a genuine host name (with userinfo).
+ // So we check for '@': if it's present check the port in the
+ // section after '@' in the other case check it in the full string.
+ // P.S.: We don't care having '@' at the beginning of the string.
+ if ((at_host = host.indexOf('@')) >= 0)
+ {
+ genuineHost = host.substring(at_host);
+ userInfo = host.substring(0, at_host);
+ }
+ else
+ genuineHost = host;
+
+ // Look for optional port number. It is valid for the non-port
+ // part of the host name to be null (e.g. a URL "http://:80").
+ // TBD: JDK 1.2 in this case sets host to null rather than "";
+ // this is undocumented and likely an unintended side effect in 1.2
+ // so we'll be simple here and stick with "". Note that
+ // "http://" or "http:///" produce a "" host in JDK 1.2.
+ if ((colon = genuineHost.indexOf(':')) >= 0)
+ {
+ try
+ {
+ port = Integer.parseInt(genuineHost.substring(colon + 1));
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignore invalid port values; port is already set to u's
+ // port.
+ }
+
+ // Now we must cut the port number in the original string.
+ if (at_host >= 0)
+ host = host.substring(0, at_host + colon);
+ else
+ host = host.substring(0, colon);
+ }
+ file = null;
+ start = hostEnd;
+ }
+ else if (host == null)
+ host = "";
+
+ if (file == null || file.length() == 0
+ || (start < end && spec.charAt(start) == '/'))
+ {
+ // No file context available; just spec for file.
+ // Or this is an absolute path name; ignore any file context.
+ file = spec.substring(start, end);
+ ref = null;
+ }
+ else if (start < end)
+ {
+ // Context is available, but only override it if there is a new file.
+ int lastSlash = file.lastIndexOf('/');
+ if (lastSlash < 0)
+ file = spec.substring(start, end);
+ else
+ file = (file.substring(0, lastSlash)
+ + '/' + spec.substring(start, end));
+
+ // For URLs constructed relative to a context, we
+ // need to canonicalise the file path.
+ file = canonicalizeFilename(file);
+
+ ref = null;
+ }
+
+ if (ref == null)
+ {
+ // Normally there should be no '#' in the file part,
+ // but we are nice.
+ int hash = file.indexOf('#');
+ if (hash != -1)
+ {
+ ref = file.substring(hash + 1, file.length());
+ file = file.substring(0, hash);
+ }
+ }
+
+ // We care about the query tag only if there is no reference at all.
+ if (ref == null)
+ {
+ int queryTag = file.indexOf('?');
+ if (queryTag != -1)
+ {
+ query = file.substring(queryTag + 1);
+ file = file.substring(0, queryTag);
+ }
+ }
+
+ // XXX - Classpath used to call PlatformHelper.toCanonicalForm() on
+ // the file part. It seems like overhead, but supposedly there is some
+ // benefit in windows based systems (it also lowercased the string).
+ setURL(url, url.getProtocol(), host, port, authority, userInfo, file, query, ref);
+ }
+
+ /*
+ * Canonicalize a filename.
+ */
+ private static String canonicalizeFilename(String file)
+ {
+ // XXX - GNU Classpath has an implementation that might be more appropriate
+ // for Windows based systems (gnu.java.io.PlatformHelper.toCanonicalForm)
+ int index;
+
+ // Replace "/./" with "/". This probably isn't very efficient in
+ // the general case, but it's probably not bad most of the time.
+ while ((index = file.indexOf("/./")) >= 0)
+ file = file.substring(0, index) + file.substring(index + 2);
+
+ // Process "/../" correctly. This probably isn't very efficient in
+ // the general case, but it's probably not bad most of the time.
+ while ((index = file.indexOf("/../")) >= 0)
+ {
+ // Strip of the previous directory - if it exists.
+ int previous = file.lastIndexOf('/', index - 1);
+ if (previous >= 0)
+ file = file.substring(0, previous) + file.substring(index + 3);
+ else
+ break;
+ }
+ return file;
+ }
+
+ /**
+ * Compares two URLs, excluding the fragment component
+ *
+ * @param url1 The first url
+ * @param url2 The second url to compare with the first
+ *
+ * @return True if both URLs point to the same file, false otherwise.
+ *
+ * @specnote Now protected
+ */
+ protected boolean sameFile(URL url1, URL url2)
+ {
+ if (url1 == url2)
+ return true;
+
+ // This comparison is very conservative. It assumes that any
+ // field can be null.
+ if (url1 == null || url2 == null)
+ return false;
+ int p1 = url1.getPort();
+ if (p1 == -1)
+ p1 = url1.ph.getDefaultPort();
+ int p2 = url2.getPort();
+ if (p2 == -1)
+ p2 = url2.ph.getDefaultPort();
+ if (p1 != p2)
+ return false;
+ String s1;
+ String s2;
+ s1 = url1.getProtocol();
+ s2 = url2.getProtocol();
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ s1 = url1.getHost();
+ s2 = url2.getHost();
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ s1 = canonicalizeFilename(url1.getFile());
+ s2 = canonicalizeFilename(url2.getFile());
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ return true;
+ }
+
+ /**
+ * This methods sets the instance variables representing the various fields
+ * of the URL to the values passed in.
+ *
+ * @param u The URL to modify
+ * @param protocol The protocol to set
+ * @param host The host name to et
+ * @param port The port number to set
+ * @param file The filename to set
+ * @param ref The reference
+ *
+ * @exception SecurityException If the protocol handler of the URL is
+ * different from this one
+ *
+ * @deprecated 1.2 Please use
+ * #setURL(URL,String,String,int,String,String,String,String);
+ */
+ protected void setURL(URL u, String protocol, String host, int port,
+ String file, String ref)
+ {
+ u.set(protocol, host, port, file, ref);
+ }
+
+ /**
+ * Sets the fields of the URL argument to the indicated values
+ *
+ * @param u The URL to modify
+ * @param protocol The protocol to set
+ * @param host The host name to set
+ * @param port The port number to set
+ * @param authority The authority to set
+ * @param userInfo The user information to set
+ * @param path The path/filename to set
+ * @param query The query part to set
+ * @param ref The reference
+ *
+ * @exception SecurityException If the protocol handler of the URL is
+ * different from this one
+ */
+ protected void setURL(URL u, String protocol, String host, int port,
+ String authority, String userInfo, String path,
+ String query, String ref)
+ {
+ u.set(protocol, host, port, authority, userInfo, path, query, ref);
+ }
+
+ /**
+ * This is the default method for computing whether two URLs are
+ * equivalent. This method assumes that neither URL is null.
+ *
+ * @param url1 An URL object
+ * @param url2 Another URL object
+ *
+ * @return True if both given URLs are equal, false otherwise.
+ */
+ protected boolean equals(URL url1, URL url2)
+ {
+ // This comparison is very conservative. It assumes that any
+ // field can be null.
+ int port1 = url1.getPort();
+ if (port1 == -1)
+ port1 = url1.getDefaultPort();
+ int port2 = url2.getPort();
+ if (port2 == -1)
+ port2 = url2.getDefaultPort();
+ // Note that we don't bother checking the 'authority'; it is
+ // redundant.
+ return (port1 == port2
+ && ((url1.getProtocol() == null && url2.getProtocol() == null)
+ || (url1.getProtocol() != null
+ && url1.getProtocol().equals(url2.getProtocol())))
+ && ((url1.getUserInfo() == null && url2.getUserInfo() == null)
+ || (url1.getUserInfo() != null
+ && url1.getUserInfo().equals(url2.getUserInfo())))
+ && ((url1.getHost() == null && url2.getHost() == null)
+ || (url1.getHost() != null && url1.getHost().equals(url2.getHost())))
+ && ((url1.getPath() == null && url2.getPath() == null)
+ || (url1.getPath() != null && url1.getPath().equals(url2.getPath())))
+ && ((url1.getQuery() == null && url2.getQuery() == null)
+ || (url1.getQuery() != null
+ && url1.getQuery().equals(url2.getQuery())))
+ && ((url1.getRef() == null && url2.getRef() == null)
+ || (url1.getRef() != null && url1.getRef().equals(url2.getRef()))));
+ }
+
+ /**
+ * Compares the host components of two URLs.
+ *
+ * @param url1 The first URL.
+ * @param url2 The second URL.
+ *
+ * @return True if both URLs contain the same host.
+ */
+ protected boolean hostsEqual(URL url1, URL url2)
+ {
+ InetAddress addr1 = getHostAddress(url1);
+ InetAddress addr2 = getHostAddress(url2);
+
+ if (addr1 != null && addr2 != null)
+ return addr1.equals(addr2);
+
+ String host1 = url1.getHost();
+ String host2 = url2.getHost();
+
+ if (host1 != null && host2 != null)
+ return host1.equalsIgnoreCase(host2);
+
+ return host1 == null && host2 == null;
+ }
+
+ /**
+ * Get the IP address of our host. An empty host field or a DNS failure will
+ * result in a null return.
+ *
+ * @param url The URL to return the host address for.
+ *
+ * @return The address of the hostname in url.
+ */
+ protected InetAddress getHostAddress(URL url)
+ {
+ String hostname = url.getHost();
+
+ if (hostname.equals(""))
+ return null;
+
+ try
+ {
+ return InetAddress.getByName(hostname);
+ }
+ catch (UnknownHostException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the default port for a URL parsed by this handler. This method is
+ * meant to be overidden by handlers with default port numbers.
+ *
+ * @return The default port number.
+ */
+ protected int getDefaultPort()
+ {
+ return -1;
+ }
+
+ /**
+ * Provides the default hash calculation. May be overidden by handlers for
+ * other protocols that have different requirements for hashCode calculation.
+ *
+ * @param url The URL to calc the hashcode for.
+ *
+ * @return The hashcode for the given URL.
+ */
+ protected int hashCode(URL url)
+ {
+ return url.getProtocol().hashCode()
+ + ((url.getHost() == null) ? 0 : url.getHost().hashCode())
+ + url.getFile().hashCode() + url.getPort();
+ }
+
+ /**
+ * This method converts a URL object into a String. This method creates
+ * Strings in the mold of http URL's, so protocol handlers which use URL's
+ * that have a different syntax should override this method
+ *
+ * @param url The URL object to convert
+ *
+ * @return A string representation of the url
+ */
+ protected String toExternalForm(URL url)
+ {
+ String protocol;
+ String file;
+ String ref;
+ String authority;
+
+ protocol = url.getProtocol();
+ authority = url.getAuthority();
+ if (authority == null)
+ authority = "";
+
+ file = url.getFile();
+ ref = url.getRef();
+
+ // Guess a reasonable size for the string buffer so we have to resize
+ // at most once.
+ int size = protocol.length() + authority.length() + file.length() + 24;
+ CPStringBuilder sb = new CPStringBuilder(size);
+
+ if (protocol.length() > 0)
+ {
+ sb.append(protocol);
+ sb.append(":");
+ }
+
+ // If we have superfluous leading slashes (that means, at least 2)
+ // we always add the authority component ("//" + host) to
+ // avoid ambiguity. Otherwise we would generate an URL like
+ // proto://home/foo
+ // where we meant:
+ // host: <empty> - file: //home/foo
+ // but URL spec says it is:
+ // host: home - file: /foo
+ if (authority.length() != 0 || file.startsWith("//") )
+ sb.append("//").append(authority).append(file);
+ else
+ sb.append(file);
+
+ if (ref != null)
+ sb.append('#').append(ref);
+
+ return sb.toString();
+ }
+}
diff --git a/libjava/classpath/java/net/URLStreamHandlerFactory.java b/libjava/classpath/java/net/URLStreamHandlerFactory.java
new file mode 100644
index 000000000..c92c71fb2
--- /dev/null
+++ b/libjava/classpath/java/net/URLStreamHandlerFactory.java
@@ -0,0 +1,65 @@
+/* URLStreamHandlerFactory.java -- Maps protocols to URLStreamHandlers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * 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.
+ */
+/**
+ * This interface contains one method which maps the protocol portion of
+ * a URL (eg, "http" in "http://www.urbanophile.com/arenn/") to a
+ * <code>URLStreamHandler</code> object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface URLStreamHandlerFactory
+{
+ /**
+ * This method maps the protocol portion of a URL to a
+ * <code>URLStreamHandler</code> object.
+ *
+ * @param protocol The protocol name to map ("http", "ftp", etc).
+ *
+ * @return The <code>URLStreamHandler</code> for the specified protocol
+ */
+ URLStreamHandler createURLStreamHandler(String protocol);
+} // interface URLStreamHandlerFactory
diff --git a/libjava/classpath/java/net/UnknownHostException.java b/libjava/classpath/java/net/UnknownHostException.java
new file mode 100644
index 000000000..c5ba18330
--- /dev/null
+++ b/libjava/classpath/java/net/UnknownHostException.java
@@ -0,0 +1,77 @@
+/* UnknownHostException.java -- The hostname is unknown
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that an attempt was made to reference a hostname
+ * or IP address that is not valid. This could possibly indicate that a
+ * DNS problem has occurred, but most often means that the host was not
+ * correctly specified.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ * @status updated to 1.4
+ */
+public class UnknownHostException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4639126076052875403L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public UnknownHostException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * name of the host that could not be resolved.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public UnknownHostException(String message)
+ {
+ super(message);
+ }
+} // class UnknownHostException
diff --git a/libjava/classpath/java/net/UnknownServiceException.java b/libjava/classpath/java/net/UnknownServiceException.java
new file mode 100644
index 000000000..65cc8f592
--- /dev/null
+++ b/libjava/classpath/java/net/UnknownServiceException.java
@@ -0,0 +1,76 @@
+/* UnknownServiceException.java -- A service error occurred
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * Contrary to what you might think, this does not indicate that the
+ * TCP/IP service name specified was invalid. Instead it indicates that
+ * the MIME type returned from a URL could not be determined or that an
+ * attempt was made to write to a read-only URL.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class UnknownServiceException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4169033248853639508L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public UnknownServiceException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public UnknownServiceException(String message)
+ {
+ super(message);
+ }
+} // class UnknownServiceException
diff --git a/libjava/classpath/java/net/package.html b/libjava/classpath/java/net/package.html
new file mode 100644
index 000000000..133ee716f
--- /dev/null
+++ b/libjava/classpath/java/net/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.net package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.net</title></head>
+
+<body>
+<p>Network communication through TCP and UDP sockets or URLs.</p>
+
+</body>
+</html>