diff options
Diffstat (limited to 'libjava/classpath/java/net')
-rw-r--r-- | libjava/classpath/java/net/Inet6Address.java | 171 | ||||
-rw-r--r-- | libjava/classpath/java/net/InetSocketAddress.java | 9 | ||||
-rw-r--r-- | libjava/classpath/java/net/URL.java | 15 | ||||
-rw-r--r-- | libjava/classpath/java/net/URLClassLoader.java | 758 | ||||
-rw-r--r-- | libjava/classpath/java/net/URLConnection.java | 47 | ||||
-rw-r--r-- | libjava/classpath/java/net/URLStreamHandler.java | 21 |
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) |