1. /*
  2. * @(#)URLStreamHandler.java 1.27 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import java.io.File;
  11. import java.io.OutputStream;
  12. import java.util.Hashtable;
  13. /**
  14. * The abstract class <code>URLStreamHandler</code> is the common
  15. * superclass for all stream protocol handlers. A stream protocol
  16. * handler knows how to make a connection for a particular protocol
  17. * type, such as <code>http</code>, <code>ftp</code>, or
  18. * <code>gopher</code>.
  19. * <p>
  20. * In most cases, an instance of a <code>URLStreamHandler</code>
  21. * subclass is not created directly by an application. Rather, the
  22. * first time a protocol name is encountered when constructing a
  23. * <code>URL</code>, the appropriate stream protocol handler is
  24. * automatically loaded.
  25. *
  26. * @author James Gosling
  27. * @version 1.27, 11/29/01
  28. * @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
  29. * @since JDK1.0
  30. */
  31. public abstract class URLStreamHandler {
  32. /**
  33. * Opens a connection to the object referenced by the
  34. * <code>URL</code> argument.
  35. * This method should be overridden by a subclass.
  36. *
  37. * <p>If for the handler's protocol (such as HTTP or JAR), there
  38. * exists a public, specialized URLConnection subclass belonging
  39. * to one of the following packages or one of their subpackages:
  40. * java.lang, java.io, java.util, java.net, the connection
  41. * returned will be of that subclass. For example, for HTTP an
  42. * HttpURLConnection will be returned, and for JAR a
  43. * JarURLConnection will be returned.
  44. *
  45. * @param u the URL that this connects to.
  46. * @return a <code>URLConnection</code> object for the <code>URL</code>.
  47. * @exception IOException if an I/O error occurs while opening the
  48. * connection.
  49. */
  50. abstract protected URLConnection openConnection(URL u) throws IOException;
  51. /**
  52. * Parses the string representation of a <code>URL</code> into a
  53. * <code>URL</code> object.
  54. * <p>
  55. * If there is any inherited context, then it has already been
  56. * copied into the <code>URL</code> argument.
  57. * <p>
  58. * The <code>parseURL</code> method of <code>URLStreamHandler</code>
  59. * parses the string representation as if it were an
  60. * <code>http</code> specification. Most URL protocol families have a
  61. * similar parsing. A stream protocol handler for a protocol that has
  62. * a different syntax must override this routine.
  63. *
  64. * @param u the <code>URL</code> to receive the result of parsing
  65. * the spec.
  66. * @param spec the <code>String</code> representing the URL that
  67. * must be parsed.
  68. * @param start the character index at which to begin parsing. This is
  69. * just past the '<code>:</code>' (if there is one) that
  70. * specifies the determination of the protocol name.
  71. * @param limit the character position to stop parsing at. This is the
  72. * end of the string or the position of the
  73. * "<code>#</code>" character, if present. All information
  74. * after the sharp sign indicates an anchor.
  75. */
  76. protected void parseURL(URL u, String spec, int start, int limit) {
  77. String protocol = u.getProtocol();
  78. String host = u.getHost();
  79. int port = u.getPort();
  80. String file = u.getFile();
  81. String ref = u.getRef();
  82. int i;
  83. if ((start <= limit - 2) && (spec.charAt(start) == '/') &&
  84. (spec.charAt(start + 1) == '/')) {
  85. start += 2;
  86. i = spec.indexOf('/', start);
  87. if (i < 0) {
  88. i = limit;
  89. }
  90. int prn = spec.indexOf(':', start);
  91. port = -1;
  92. if ((prn < i) && (prn >= 0)) {
  93. try {
  94. port = Integer.parseInt(spec.substring(prn + 1, i));
  95. } catch(Exception e) {
  96. // ignore bogus port numbers
  97. }
  98. if (prn > start) {
  99. host = spec.substring(start, prn);
  100. }
  101. } else {
  102. host = spec.substring(start, i);
  103. }
  104. start = i;
  105. file = null;
  106. } else if (host == null) {
  107. host = "";
  108. }
  109. if (start < limit) {
  110. if (spec.charAt(start) == '/') {
  111. file = spec.substring(start, limit);
  112. } else if (file != null && file.length() > 0) {
  113. /* relative to the context file - use either
  114. * Unix separators || platform separators
  115. */
  116. int ind = Math.max(file.lastIndexOf('/'),
  117. file.lastIndexOf(File.separatorChar));
  118. // if there is no file separator there is no relative dir
  119. if (ind < 0)
  120. ind = 0;
  121. file = file.substring(0, ind) + "/" + spec.substring(start, limit);
  122. } else {
  123. file = "/" + spec.substring(start, limit);
  124. }
  125. }
  126. if ((file == null) || (file.length() == 0)) {
  127. file = "/";
  128. }
  129. while ((i = file.indexOf("/./")) >= 0) {
  130. file = file.substring(0, i) + file.substring(i + 2);
  131. }
  132. while ((i = file.indexOf("/../")) >= 0) {
  133. if ((limit = file.lastIndexOf('/', i - 1)) >= 0) {
  134. file = file.substring(0, limit) + file.substring(i + 3);
  135. } else {
  136. file = file.substring(i + 3);
  137. }
  138. }
  139. setURL(u, protocol, host, port, file, ref);
  140. }
  141. /**
  142. * Converts a <code>URL</code> of a specific protocol to a
  143. * <code>String</code>.
  144. *
  145. * @param u the URL.
  146. * @return a string representation of the <code>URL</code> argument.
  147. */
  148. protected String toExternalForm(URL u) {
  149. String result = u.getProtocol() + ":";
  150. if ((u.getHost() != null) && (u.getHost().length() > 0)) {
  151. result = result + "//" + u.getHost();
  152. if (u.getPort() != -1) {
  153. result += ":" + u.getPort();
  154. }
  155. }
  156. result += u.getFile();
  157. if (u.getRef() != null) {
  158. result += "#" + u.getRef();
  159. }
  160. return result;
  161. }
  162. /**
  163. * Sets the fields of the <code>URL</code> argument to the indicated values.
  164. * Only classes derived from URLStreamHandler are supposed to be able
  165. * to call the set method on a URL.
  166. *
  167. * @param u the URL to modify.
  168. * @param protocol the protocol name.
  169. * @param host the remote host value for the URL.
  170. * @param port the port on the remote machine.
  171. * @param file the file.
  172. * @param ref the reference.
  173. * @see java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
  174. */
  175. protected void setURL(URL u, String protocol, String host, int port,
  176. String file, String ref) {
  177. if (this != u.handler) {
  178. throw new SecurityException("handler for url different from " +
  179. "this handler");
  180. }
  181. // ensure that no one can reset the protocol on a given URL.
  182. u.set(u.getProtocol(), host, port, file, ref);
  183. }
  184. }