summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/net
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/net')
-rw-r--r--libjava/classpath/java/net/Inet6Address.java171
-rw-r--r--libjava/classpath/java/net/InetSocketAddress.java9
-rw-r--r--libjava/classpath/java/net/URL.java15
-rw-r--r--libjava/classpath/java/net/URLClassLoader.java758
-rw-r--r--libjava/classpath/java/net/URLConnection.java47
-rw-r--r--libjava/classpath/java/net/URLStreamHandler.java21
6 files changed, 373 insertions, 648 deletions
diff --git a/libjava/classpath/java/net/Inet6Address.java b/libjava/classpath/java/net/Inet6Address.java
index 0d62fe919a0..8d834a6fd28 100644
--- a/libjava/classpath/java/net/Inet6Address.java
+++ b/libjava/classpath/java/net/Inet6Address.java
@@ -39,13 +39,16 @@ exception statement from your version. */
package java.net;
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 Believed complete and correct.
+ * @status Updated to 1.5. Serialization compatibility is tested.
*/
public final class Inet6Address extends InetAddress
{
@@ -57,6 +60,39 @@ public final class Inet6Address extends InetAddress
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;
+
+ /**
* Create an Inet6Address object
*
* @param addr The IP address
@@ -67,6 +103,10 @@ public final class Inet6Address extends InetAddress
super(addr, host);
// 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;
}
/**
@@ -199,6 +239,75 @@ public final class Inet6Address extends InetAddress
}
/**
+ * 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()
@@ -214,12 +323,17 @@ public final class Inet6Address extends InetAddress
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()
{
@@ -234,10 +348,23 @@ public final class Inet6Address extends InetAddress
if (! (obj instanceof Inet6Address))
return false;
- // this.ipaddress is never set in this class except to
- // the value of the super class' addr. The super classes
- // equals(Object) will do the compare.
- return super.equals(obj);
+ 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;
}
/**
@@ -258,4 +385,38 @@ public final class Inet6Address extends InetAddress
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/InetSocketAddress.java b/libjava/classpath/java/net/InetSocketAddress.java
index 91254575265..5267cc11a5d 100644
--- a/libjava/classpath/java/net/InetSocketAddress.java
+++ b/libjava/classpath/java/net/InetSocketAddress.java
@@ -86,7 +86,6 @@ public class InetSocketAddress extends SocketAddress
this.addr = addr;
this.port = port;
- this.hostname = addr.getHostName();
}
/**
@@ -186,7 +185,7 @@ public class InetSocketAddress extends SocketAddress
if (addr == null && sa.addr != null)
return false;
- else if (addr == null && sa.addr == null)
+ 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;
@@ -213,6 +212,9 @@ public class InetSocketAddress extends SocketAddress
*/
public final String getHostName()
{
+ if (hostname == null) // we know addr != null
+ hostname = addr.getHostName();
+
return hostname;
}
@@ -249,10 +251,11 @@ public class InetSocketAddress extends SocketAddress
/**
* Returns the <code>InetSocketAddress</code> as string
*
- * @return A string represenation of this address.
+ * @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/URL.java b/libjava/classpath/java/net/URL.java
index 967cc80f69b..ed7decc7992 100644
--- a/libjava/classpath/java/net/URL.java
+++ b/libjava/classpath/java/net/URL.java
@@ -482,7 +482,17 @@ public final class URL implements Serializable
}
catch (URLParseError e)
{
- throw new MalformedURLException(e.getMessage());
+ 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)
@@ -535,8 +545,7 @@ public final class URL implements Serializable
*/
public Object getContent(Class[] classes) throws IOException
{
- // FIXME: implement this
- return getContent();
+ return openConnection().getContent(classes);
}
/**
diff --git a/libjava/classpath/java/net/URLClassLoader.java b/libjava/classpath/java/net/URLClassLoader.java
index 183e645c85f..403f7485c79 100644
--- a/libjava/classpath/java/net/URLClassLoader.java
+++ b/libjava/classpath/java/net/URLClassLoader.java
@@ -39,15 +39,21 @@ exception statement from your version. */
package java.net;
-import java.io.BufferedReader;
+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.FileInputStream;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSource;
@@ -55,14 +61,10 @@ 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.HashMap;
-import java.util.Iterator;
-import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
import java.util.jar.Manifest;
@@ -128,19 +130,17 @@ public class URLClassLoader extends SecureClassLoader
// Class Variables
/**
- * A global cache to store mappings between URLLoader and URL,
- * so we can avoid do all the homework each time the same URL
- * comes.
- * XXX - Keeps these loaders forever which prevents garbage collection.
+ * 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 HashMap urlloaders = new HashMap();
+ private static URLStreamHandlerCache factoryCache
+ = new URLStreamHandlerCache();
/**
- * A cache to store mappings between handler factory and its
- * private protocol handler cache (also a HashMap), so we can avoid
- * create handlers each time the same protocol comes.
+ * The prefix for URL loaders.
*/
- private static HashMap factoryCache = new HashMap(5);
+ private static final String URL_LOADER_PREFIX = "gnu.java.net.loader.Load_";
// Instance variables
@@ -168,516 +168,6 @@ public class URLClassLoader extends SecureClassLoader
// Helper classes
/**
- * A <code>URLLoader</code> contains all logic to load resources from a
- * given base <code>URL</code>.
- */
- abstract static class URLLoader
- {
- /**
- * Our classloader to get info from if needed.
- */
- final URLClassLoader classloader;
-
- /**
- * The base URL from which all resources are loaded.
- */
- final URL baseURL;
-
- /**
- * A <code>CodeSource</code> without any associated certificates.
- * It is common for classes to not have certificates associated
- * with them. If they come from the same <code>URLLoader</code>
- * then it is safe to share the associated <code>CodeSource</code>
- * between them since <code>CodeSource</code> is immutable.
- */
- final CodeSource noCertCodeSource;
-
- URLLoader(URLClassLoader classloader, URL baseURL)
- {
- this(classloader, baseURL, baseURL);
- }
-
- URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
- {
- this.classloader = classloader;
- this.baseURL = baseURL;
- this.noCertCodeSource = new CodeSource(overrideURL, null);
- }
-
- /**
- * Returns a <code>Resource</code> loaded by this
- * <code>URLLoader</code>, or <code>null</code> when no
- * <code>Resource</code> with the given name exists.
- */
- abstract Resource getResource(String s);
-
- /**
- * Returns the <code>Manifest</code> associated with the
- * <code>Resource</code>s loaded by this <code>URLLoader</code> or
- * <code>null</code> there is no such <code>Manifest</code>.
- */
- Manifest getManifest()
- {
- return null;
- }
-
- Vector getClassPath()
- {
- return null;
- }
- }
-
- /**
- * A <code>Resource</code> represents a resource in some
- * <code>URLLoader</code>. It also contains all information (e.g.,
- * <code>URL</code>, <code>CodeSource</code>, <code>Manifest</code> and
- * <code>InputStream</code>) that is necessary for loading resources
- * and creating classes from a <code>URL</code>.
- */
- abstract static class Resource
- {
- final URLLoader loader;
-
- Resource(URLLoader loader)
- {
- this.loader = loader;
- }
-
- /**
- * Returns the non-null <code>CodeSource</code> associated with
- * this resource.
- */
- CodeSource getCodeSource()
- {
- Certificate[] certs = getCertificates();
- if (certs == null)
- return loader.noCertCodeSource;
- else
- return new CodeSource(loader.baseURL, certs);
- }
-
- /**
- * Returns <code>Certificates</code> associated with this
- * resource, or null when there are none.
- */
- Certificate[] getCertificates()
- {
- return null;
- }
-
- /**
- * Return a <code>URL</code> that can be used to access this resource.
- */
- abstract URL getURL();
-
- /**
- * Returns the size of this <code>Resource</code> in bytes or
- * <code>-1</code> when unknown.
- */
- abstract int getLength();
-
- /**
- * Returns the non-null <code>InputStream</code> through which
- * this resource can be loaded.
- */
- abstract InputStream getInputStream() throws IOException;
- }
-
- /**
- * A <code>JarURLLoader</code> is a type of <code>URLLoader</code>
- * only loading from jar url.
- */
- static final class JarURLLoader extends URLLoader
- {
- final JarFile jarfile; // The jar file for this url
- final URL baseJarURL; // Base jar: url for all resources loaded from jar
-
- Vector classPath; // The "Class-Path" attribute of this Jar's manifest
-
- public JarURLLoader(URLClassLoader classloader, URL baseURL,
- URL absoluteUrl)
- {
- super(classloader, baseURL, absoluteUrl);
-
- // Cache url prefix for all resources in this jar url.
- String external = baseURL.toExternalForm();
- StringBuffer sb = new StringBuffer(external.length() + 6);
- sb.append("jar:");
- sb.append(external);
- sb.append("!/");
- String jarURL = sb.toString();
-
- this.classPath = null;
- URL baseJarURL = null;
- JarFile jarfile = null;
- try
- {
- baseJarURL =
- new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
-
- jarfile =
- ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
-
- Manifest manifest;
- Attributes attributes;
- String classPathString;
-
- this.classPath = new Vector();
-
- // This goes through the cached jar files listed
- // in the INDEX.LIST file. All the jars found are added
- // to the classPath vector so they can be loaded.
- String dir = "META-INF/INDEX.LIST";
- if (jarfile.getEntry(dir) != null)
- {
- BufferedReader br = new BufferedReader(new InputStreamReader(new URL(baseJarURL,
- dir).openStream()));
- String line = br.readLine();
- while (line != null)
- {
- if (line.endsWith(".jar"))
- {
- try
- {
- this.classPath.add(new URL(baseURL, line));
- }
- catch (java.net.MalformedURLException xx)
- {
- // Give up
- }
- }
- line = br.readLine();
- }
- }
- else if ((manifest = jarfile.getManifest()) != null
- && (attributes = manifest.getMainAttributes()) != null
- && ((classPathString
- = attributes.getValue(Attributes.Name.CLASS_PATH))
- != null))
- {
- StringTokenizer st = new StringTokenizer(classPathString, " ");
- while (st.hasMoreElements ())
- {
- String e = st.nextToken ();
- try
- {
- this.classPath.add(new URL(baseURL, e));
- }
- catch (java.net.MalformedURLException xx)
- {
- // Give up
- }
- }
- }
- }
- catch (IOException ioe)
- {
- /* ignored */
- }
-
- this.baseJarURL = baseJarURL;
- this.jarfile = jarfile;
- }
-
- /** get resource with the name "name" in the jar url */
- Resource getResource(String name)
- {
- if (jarfile == null)
- return null;
-
- if (name.startsWith("/"))
- name = name.substring(1);
-
- JarEntry je = jarfile.getJarEntry(name);
- if (je != null)
- return new JarURLResource(this, name, je);
- else
- return null;
- }
-
- Manifest getManifest()
- {
- try
- {
- return (jarfile == null) ? null : jarfile.getManifest();
- }
- catch (IOException ioe)
- {
- return null;
- }
- }
-
- Vector getClassPath()
- {
- return classPath;
- }
- }
-
- static final class JarURLResource extends Resource
- {
- private final JarEntry entry;
- private final String name;
-
- JarURLResource(JarURLLoader loader, String name, JarEntry entry)
- {
- super(loader);
- this.entry = entry;
- this.name = name;
- }
-
- InputStream getInputStream() throws IOException
- {
- return ((JarURLLoader) loader).jarfile.getInputStream(entry);
- }
-
- int getLength()
- {
- return (int) entry.getSize();
- }
-
- Certificate[] getCertificates()
- {
- // We have to get the entry from the jar file again, because the
- // certificates will not be available until the entire entry has
- // been read.
- return ((JarEntry) ((JarURLLoader) loader).jarfile.getEntry(name))
- .getCertificates();
- }
-
- URL getURL()
- {
- try
- {
- return new URL(((JarURLLoader) loader).baseJarURL, name,
- loader.classloader.getURLStreamHandler("jar"));
- }
- catch (MalformedURLException e)
- {
- InternalError ie = new InternalError();
- ie.initCause(e);
- throw ie;
- }
- }
- }
-
- /**
- * Loader for remote directories.
- */
- static final class RemoteURLLoader extends URLLoader
- {
- private final String protocol;
-
- RemoteURLLoader(URLClassLoader classloader, URL url)
- {
- super(classloader, url);
- protocol = url.getProtocol();
- }
-
- /**
- * Get a remote resource.
- * Returns null if no such resource exists.
- */
- Resource getResource(String name)
- {
- try
- {
- URL url =
- new URL(baseURL, name, classloader.getURLStreamHandler(protocol));
- URLConnection connection = url.openConnection();
-
- // Open the connection and check the stream
- // just to be sure it exists.
- int length = connection.getContentLength();
- InputStream stream = connection.getInputStream();
-
- // We can do some extra checking if it is a http request
- if (connection instanceof HttpURLConnection)
- {
- int response =
- ((HttpURLConnection) connection).getResponseCode();
- if (response / 100 != 2)
- return null;
- }
-
- if (stream != null)
- return new RemoteResource(this, name, url, stream, length);
- else
- return null;
- }
- catch (IOException ioe)
- {
- return null;
- }
- }
- }
-
- /**
- * A resource from some remote location.
- */
- static final class RemoteResource extends Resource
- {
- private final URL url;
- private final InputStream stream;
- private final int length;
-
- RemoteResource(RemoteURLLoader loader, String name, URL url,
- InputStream stream, int length)
- {
- super(loader);
- this.url = url;
- this.stream = stream;
- this.length = length;
- }
-
- InputStream getInputStream() throws IOException
- {
- return stream;
- }
-
- public int getLength()
- {
- return length;
- }
-
- public URL getURL()
- {
- return url;
- }
- }
-
- /**
- * A <code>FileURLLoader</code> is a type of <code>URLLoader</code>
- * only loading from file url.
- */
- static final class FileURLLoader extends URLLoader
- {
- File dir; //the file for this file url
-
- FileURLLoader(URLClassLoader classloader, URL url, URL absoluteUrl)
- {
- super(classloader, url, absoluteUrl);
- dir = new File(absoluteUrl.getFile());
- }
-
- /** get resource with the name "name" in the file url */
- Resource getResource(String name)
- {
- try
- {
- // Make sure that all components in name are valid by walking through
- // them
- File file = walkPathComponents(name);
-
- if (file == null)
- return null;
-
- return new FileResource(this, file);
- }
- catch (IOException e)
- {
- // Fall through...
- }
- return null;
- }
-
- /**
- * Walk all path tokens and check them for validity. At no moment, we are
- * allowed to reach a directory located "above" the root directory, stored
- * in "dir" property. We are also not allowed to enter a non existing
- * directory or a non directory component (plain file, symbolic link, ...).
- * An empty or null path is valid. Pathnames components are separated by
- * <code>File.separatorChar</code>
- *
- * @param resourceFileName the name to be checked for validity.
- * @return the canonical file pointed by the resourceFileName or null if the
- * walking failed
- * @throws IOException in case of issue when creating the canonical
- * resulting file
- * @see File#separatorChar
- */
- private File walkPathComponents(String resourceFileName) throws IOException
- {
- StringTokenizer stringTokenizer = new StringTokenizer(resourceFileName, File.separator);
- File currentFile = dir;
- int tokenCount = stringTokenizer.countTokens();
-
- for (int i = 0; i < tokenCount - 1; i++)
- {
- String currentToken = stringTokenizer.nextToken();
-
- // If we are at the root directory and trying to go up, the walking is
- // finished with an error
- if ("..".equals(currentToken) && currentFile.equals(dir))
- return null;
-
- currentFile = new File(currentFile, currentToken);
-
- // If the current file doesn't exist or is not a directory, the walking is
- // finished with an error
- if (! (currentFile.exists() && currentFile.isDirectory()))
- return null;
-
- }
-
- // Treat the last token differently, if it exists, because it does not need
- // to be a directory
- if (tokenCount > 0)
- {
- String currentToken = stringTokenizer.nextToken();
-
- if ("..".equals(currentToken) && currentFile.equals(dir))
- return null;
-
- currentFile = new File(currentFile, currentToken);
-
- // If the current file doesn't exist, the walking is
- // finished with an error
- if (! currentFile.exists())
- return null;
- }
-
- return currentFile.getCanonicalFile();
- }
- }
-
- static final class FileResource extends Resource
- {
- final File file;
-
- FileResource(FileURLLoader loader, File file)
- {
- super(loader);
- this.file = file;
- }
-
- InputStream getInputStream() throws IOException
- {
- return new FileInputStream(file);
- }
-
- public int getLength()
- {
- return (int) file.length();
- }
-
- public URL getURL()
- {
- try
- {
- return file.toURL();
- }
- catch (MalformedURLException e)
- {
- InternalError ie = new InternalError();
- ie.initCause(e);
- throw ie;
- }
- }
- }
-
- // Constructors
-
- /**
* 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
@@ -774,14 +264,8 @@ public class URLClassLoader extends SecureClassLoader
this.factory = factory;
addURLs(urls);
- // If this factory is still not in factoryCache, add it,
- // since we only support three protocols so far, 5 is enough
- // for cache initial size
- synchronized (factoryCache)
- {
- if (factory != null && factoryCache.get(factory) == null)
- factoryCache.put(factory, new HashMap(5));
- }
+ // If this factory is still not in factoryCache, add it.
+ factoryCache.add(factory);
}
// Methods
@@ -806,72 +290,114 @@ public class URLClassLoader extends SecureClassLoader
// Reset the toString() value.
thisString = null;
- // Check global cache to see if there're already url loader
- // for this url.
- URLLoader loader = (URLLoader) urlloaders.get(newUrl);
- if (loader == 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);
+ URL absUrl;
+ try
+ {
+ absoluteURL = dir.getCanonicalFile().toURL();
+ }
+ catch (IOException ignore)
+ {
+ try
+ {
+ absoluteURL = dir.getAbsoluteFile().toURL();
+ }
+ catch (MalformedURLException _)
+ {
+ // This really should not happen.
+ absoluteURL = newUrl;
+ }
+ }
+ }
+ else
{
- String file = newUrl.getFile();
- String protocol = newUrl.getProtocol();
+ // This doesn't hurt, and it simplifies the logic a
+ // little.
+ absoluteURL = newUrl;
+ }
- // 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);
- URL absUrl;
- 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;
+ }
- // Check that it is not a directory
+ if (loader == null)
+ {
+ // If it is not a directory, use the jar loader.
if (! (file.endsWith("/") || file.endsWith(File.separator)))
- loader = new JarURLLoader(this, newUrl, absoluteURL);
+ loader = new JarURLLoader(this, factoryCache, factory,
+ newUrl, absoluteURL);
else if ("file".equals(protocol))
- loader = new FileURLLoader(this, newUrl, absoluteURL);
+ loader = new FileURLLoader(this, factoryCache, factory,
+ newUrl, absoluteURL);
else
- loader = new RemoteURLLoader(this, newUrl);
-
- // Cache it.
- urlloaders.put(newUrl, loader);
+ loader = new RemoteURLLoader(this, factoryCache, factory,
+ newUrl);
}
urlinfos.add(loader);
-
- Vector extraUrls = loader.getClassPath();
- if (extraUrls != null)
- {
- Iterator it = extraUrls.iterator();
- while (it.hasNext())
- {
- URL url = (URL)it.next();
- URLLoader extraLoader = (URLLoader) urlloaders.get(url);
- if (! urlinfos.contains (extraLoader))
- addURLImpl(url);
- }
- }
-
+ ArrayList extra = loader.getClassPath();
+ if (extra != null)
+ urlinfos.addAll(extra);
}
}
@@ -987,7 +513,20 @@ public class URLClassLoader extends SecureClassLoader
{
// Just try to find the resource by the (almost) same name
String resourceName = className.replace('.', '/') + ".class";
- Resource resource = findURLResource(resourceName);
+ 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);
@@ -1049,12 +588,13 @@ public class URLClassLoader extends SecureClassLoader
if (packageName != null && getPackage(packageName) == null)
{
// define the package
- Manifest manifest = resource.loader.getManifest();
+ Manifest manifest = resource.getLoader().getManifest();
if (manifest == null)
definePackage(packageName, null, null, null, null, null, null,
null);
else
- definePackage(packageName, manifest, resource.loader.baseURL);
+ definePackage(packageName, manifest,
+ resource.getLoader().getBaseURL());
}
// And finally construct the class!
@@ -1166,34 +706,6 @@ public class URLClassLoader extends SecureClassLoader
}
/**
- * If the URLStreamHandlerFactory has been set this return the appropriate
- * URLStreamHandler for the given protocol, if not set returns null.
- *
- * @param protocol the protocol for which we need a URLStreamHandler
- * @return the appropriate URLStreamHandler or null
- */
- URLStreamHandler getURLStreamHandler(String protocol)
- {
- if (factory == null)
- return null;
-
- URLStreamHandler handler;
- synchronized (factoryCache)
- {
- // Check if there're handler for the same protocol in cache.
- HashMap cache = (HashMap) factoryCache.get(factory);
- handler = (URLStreamHandler) cache.get(protocol);
- if (handler == null)
- {
- // Add it to cache.
- handler = factory.createURLStreamHandler(protocol);
- cache.put(protocol, handler);
- }
- }
- return handler;
- }
-
- /**
* Finds all the resources with a particular name from all the locations.
*
* @param resourceName the name of the resource to lookup
diff --git a/libjava/classpath/java/net/URLConnection.java b/libjava/classpath/java/net/URLConnection.java
index 1f78dd8e8dd..28142b10aad 100644
--- a/libjava/classpath/java/net/URLConnection.java
+++ b/libjava/classpath/java/net/URLConnection.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package java.net;
-import gnu.classpath.NotImplementedException;
import gnu.classpath.SystemProperties;
import java.io.IOException;
@@ -173,6 +172,11 @@ public abstract class URLConnection
private static SimpleDateFormat[] dateFormats;
private static boolean dateformats_initialized;
+
+ /**
+ * The timeout period.
+ */
+ private int timeout;
/* Cached ParsePosition, used when parsing dates. */
private ParsePosition position;
@@ -212,6 +216,38 @@ public abstract class URLConnection
}
/**
+ * 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 timeout;
+ }
+
+ /**
+ * 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.");
+ this.timeout = timeout;
+ }
+
+ /**
* Returns the value of the content-length header field or -1 if the value
* is not known or not present.
*
@@ -934,11 +970,12 @@ public abstract class URLConnection
* @exception IOException If an error occurs
*/
public static String guessContentTypeFromStream(InputStream is)
- throws IOException, NotImplementedException
+ throws IOException
{
- // See /etc/gnome-vfs-mime-magic or /etc/mime-magic for a reasonable
- // idea of how to handle this.
- return "application/octet-stream";
+ String result = VMURLConnection.guessContentTypeFromStream(is);
+ if (result == null)
+ return "application/octet-stream";
+ return result;
}
/**
diff --git a/libjava/classpath/java/net/URLStreamHandler.java b/libjava/classpath/java/net/URLStreamHandler.java
index ed95092219e..9a5d73ad0d0 100644
--- a/libjava/classpath/java/net/URLStreamHandler.java
+++ b/libjava/classpath/java/net/URLStreamHandler.java
@@ -369,13 +369,11 @@ public abstract class URLStreamHandler
}
/**
- * Provides the default equals calculation. May be overidden by handlers for
- * other protocols that have different requirements for equals(). This method
- * requires that none of its arguments is null. This is guaranteed by the
- * fact that it is only called by java.net.URL class.
+ * 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 An URL object
+ * @param url2 Another URL object
*
* @return True if both given URLs are equal, false otherwise.
*/
@@ -383,16 +381,21 @@ public abstract class URLStreamHandler
{
// This comparison is very conservative. It assumes that any
// field can be null.
- return (url1.getPort() == url2.getPort()
+ 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.getAuthority() == null && url2.getAuthority() == null)
- || (url1.getAuthority() != null
- && url1.getAuthority().equals(url2.getAuthority())))
&& ((url1.getHost() == null && url2.getHost() == null)
|| (url1.getHost() != null && url1.getHost().equals(url2.getHost())))
&& ((url1.getPath() == null && url2.getPath() == null)