// URLStreamHandler.java - Superclass of all stream protocol handlers. /* Copyright (C) 1999 Free Software Foundation This file is part of libgcj. This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ package java.net; /** * @author Warren Levy * @date March 4, 1999. */ /** * Written using on-line Java Platform 1.2 API Specification, as well * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). * Status: Believed complete and correct. */ public abstract class URLStreamHandler { protected abstract URLConnection openConnection(URL u) throws java.io.IOException; protected void parseURL(URL u, String spec, int start, int limit) { String host = u.getHost(); int port = u.getPort(); String file = u.getFile(); /* TBD: The JDK 1.2 doc specifically says that limit is the position * to stop parsing at and that it will be either the end of the string * or the position of '#'; thus the doc infers that this method does * not set the ref. */ if (spec.regionMatches (start, "//", 0, 2)) { int hostEnd; int colon; start += 2; int slash = spec.indexOf('/', start); if (slash >= 0) hostEnd = slash; else hostEnd = limit; host = spec.substring (start, hostEnd); // 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 = host.indexOf(':')) >= 0) { try { port = Integer.parseInt(host.substring(colon + 1)); } catch (NumberFormatException e) { ; // Ignore invalid port values; port is already set to u's // port. } host = host.substring(0, colon); } file = null; start = hostEnd; } else if (host == null) host = ""; if (start < limit && spec.charAt(start) == '/') { // This is an absolute path name; ignore any file context. file = spec.substring(start, limit); } else if (file == null || file.length() <= 0) { // No file context available; just spec for file. file = "/" + spec.substring(start, limit); } else if (start < limit) { // Context is available, but only override it if there is a new file. // FIXME: unsure to what extent `/` and File.separatorChar // can mix in URLs. Ignore File.separatorChar for now. file = file.substring(0, file.lastIndexOf('/')) + "/" + spec.substring(start, limit); } 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; } u.set(u.getProtocol(), host, port, file, u.getRef()); } protected void setURL(URL u, String protocol, String host, int port, String file, String ref) { u.set(protocol, host, port, file, ref); } protected String toExternalForm(URL u) { String resStr, host, file, ref; int port; resStr = u.getProtocol() + ":"; host = u.getHost(); port = u.getPort(); file = u.getFile(); ref = u.getRef(); // JDK 1.2 online doc infers that host could be null because it // explicitly states that file cannot be null, but is silent on host. // // Note that this produces different results from JDK 1.2 as JDK 1.2 // ignores a non-default port if host is null or "". That is inconsistent // with the spec since the result of this method is spec'ed so it can be // used to construct a new URL that is equivalent to the original. if (host == null) host = ""; if (port >= 0 || ! (host.length() == 0)) resStr = resStr + "//" + host + (port < 0 ? "" : ":" + port); resStr = resStr + file; if (ref != null) resStr = resStr + "#" + ref; return resStr; } }