* All files: Updated copyright to reflect Cygnus purchase.
[official-gcc.git] / libjava / java / net / URL.java
blobc59d6942e548db801671c961430435a0e8ce898b
1 // URL.java - A Uniform Resource Locator.
3 /* Copyright (C) 1999 Red Hat, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 package java.net;
13 import java.io.*;
14 import java.util.Hashtable;
15 import java.util.StringTokenizer;
17 /**
18 * @author Warren Levy <warrenl@cygnus.com>
19 * @date March 4, 1999.
22 /**
23 * Written using on-line Java Platform 1.2 API Specification, as well
24 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
25 * Status: Believed complete and correct.
28 public final class URL implements Serializable
30 private String protocol;
31 private String host;
32 private int port = -1; // Initialize for constructor using context.
33 private String file;
34 private String ref;
35 private URLStreamHandler handler;
36 private static Hashtable handlers = new Hashtable();
37 private static URLStreamHandlerFactory factory;
39 public URL(String protocol, String host, int port, String file)
40 throws MalformedURLException
42 this(protocol, host, port, file, null);
45 public URL(String protocol, String host, String file)
46 throws MalformedURLException
48 this(protocol, host, -1, file, null);
51 // JDK1.2
52 public URL(String protocol, String host, int port, String file,
53 URLStreamHandler handler) throws MalformedURLException
55 if (protocol == null)
56 throw new MalformedURLException("null protocol");
57 this.protocol = protocol;
59 if (handler != null)
61 // TODO12: Need SecurityManager.checkPermission and
62 // TODO12: java.net.NetPermission from JDK 1.2 to be implemented.
63 // Throw an exception if an extant security mgr precludes
64 // specifying a StreamHandler.
66 // SecurityManager s = System.getSecurityManager();
67 // if (s != null)
68 // s.checkPermission(NetPermission("specifyStreamHandler"));
70 this.handler = handler;
72 else
73 this.handler = setURLStreamHandler(protocol);
75 if (this.handler == null)
76 throw new MalformedURLException("Handler for protocol not found");
78 this.host = host;
80 this.port = port;
82 int hashAt = file.indexOf('#');
83 if (hashAt < 0)
85 this.file = file;
86 this.ref = null;
88 else
90 this.file = file.substring(0, hashAt);
91 this.ref = file.substring(hashAt + 1);
95 public URL(String spec) throws MalformedURLException
97 this((URL) null, spec, (URLStreamHandler) null);
100 public URL(URL context, String spec) throws MalformedURLException
102 this(context, spec, (URLStreamHandler) null);
105 // JDK1.2
106 public URL(URL context, String spec, URLStreamHandler handler)
107 throws MalformedURLException
109 /* A protocol is defined by the doc as the substring before a ':'
110 * as long as the ':' occurs before any '/'.
112 * If context is null, then spec must be an absolute URL.
114 * The relative URL need not specify all the components of a URL.
115 * If the protocol, host name, or port number is missing, the value
116 * is inherited from the context. A bare file component is appended
117 * to the context's file. The optional anchor is not inherited.
120 // If this is an absolute URL, then ignore context completely.
121 // An absolute URL must have chars prior to "://" but cannot have a colon
122 // right after the "://". The second colon is for an optional port value
123 // and implies that the host from the context is used if available.
124 int colon;
125 if ((colon = spec.indexOf("://", 1)) > 0 &&
126 ! spec.regionMatches(colon, "://:", 0, 4))
127 context = null;
129 int slash;
130 if ((colon = spec.indexOf(':')) > 0 &&
131 (colon < (slash = spec.indexOf('/')) || slash < 0))
133 // Protocol specified in spec string.
134 protocol = spec.substring(0, colon);
135 if (context != null && context.protocol.equals(protocol))
137 // The 1.2 doc specifically says these are copied to the new URL.
138 host = context.host;
139 port = context.port;
140 file = context.file;
143 else if (context != null)
145 // Protocol NOT specified in spec string.
146 // Use context fields (except ref) as a foundation for relative URLs.
147 colon = -1;
148 protocol = context.protocol;
149 host = context.host;
150 port = context.port;
151 file = context.file;
153 else // Protocol NOT specified in spec. and no context available.
154 throw new
155 MalformedURLException("Absolute URL required with null context");
157 if (handler != null)
159 // TODO12: Need SecurityManager.checkPermission and
160 // TODO12: java.net.NetPermission from JDK 1.2 to be implemented.
161 // Throw an exception if an extant security mgr precludes
162 // specifying a StreamHandler.
164 // SecurityManager s = System.getSecurityManager();
165 // if (s != null)
166 // s.checkPermission(NetPermission("specifyStreamHandler"));
168 this.handler = handler;
170 else
171 this.handler = setURLStreamHandler(protocol);
173 if (this.handler == null)
174 throw new MalformedURLException("Handler for protocol not found");
176 // JDK 1.2 doc for parseURL specifically states that any '#' ref
177 // is to be excluded by passing the 'limit' as the indexOf the '#'
178 // if one exists, otherwise pass the end of the string.
179 int hashAt = spec.indexOf('#', colon + 1);
180 this.handler.parseURL(this, spec, colon + 1,
181 hashAt < 0 ? spec.length() : hashAt);
182 if (hashAt >= 0)
183 ref = spec.substring(hashAt + 1);
186 public boolean equals(Object obj)
188 if (obj == null || ! (obj instanceof URL))
189 return false;
191 URL uObj = (URL) obj;
193 // This comparison is very conservative. It assumes that any
194 // field can be null.
195 return (port == uObj.port
196 && ((protocol == null && uObj.protocol == null)
197 || (protocol != null && protocol.equals(uObj.protocol)))
198 && ((host == null && uObj.host == null)
199 || (host != null && host.equals(uObj.host)))
200 && ((file == null && uObj.file == null)
201 || (file != null && file.equals(uObj.file)))
202 && ((ref == null && uObj.ref == null)
203 || (ref != null && ref.equals(uObj.ref))));
206 public final Object getContent() throws IOException
208 return openConnection().getContent();
211 public String getFile()
213 return file;
216 public String getHost()
218 return host;
221 public int getPort()
223 return port;
226 public String getProtocol()
228 return protocol;
231 public String getRef()
233 return ref;
236 public int hashCode()
238 // JCL book says this is computed using (only) the hashcodes of the
239 // protocol, host and file fields. Empirical evidence indicates this
240 // is probably XOR in JDK 1.1. In JDK 1.2 it seems to be a sum including
241 // the port.
243 // JDK 1.2 online doc infers that host could be null because it
244 // explicitly states that file cannot be null but is silent on host.
245 // A simple example with protocol "http" (hashcode 3213448), host null,
246 // file "/" (hashcode 47) produced a hashcode (3213494) which appeared
247 // to be the sum of the two hashcodes plus the port. Another example
248 // using "/index.html" for file bore this out; as well as "#" for file
249 // (which was reduced to "" with a hashcode of zero). A "" host also
250 // causes the port number and the two hashcodes to be summed.
252 return (protocol.hashCode() + ((host == null) ? 0 : host.hashCode()) +
253 port + file.hashCode());
256 public URLConnection openConnection() throws IOException
258 return handler.openConnection(this);
261 public final InputStream openStream() throws IOException
263 return openConnection().getInputStream();
266 public boolean sameFile(URL other)
268 // This comparison is very conservative. It assumes that any
269 // field can be null.
270 return (other != null
271 && port == other.port
272 && ((protocol == null && other.protocol == null)
273 || (protocol != null && protocol.equals(other.protocol)))
274 && ((host == null && other.host == null)
275 || (host != null && host.equals(other.host)))
276 && ((file == null && other.file == null)
277 || (file != null && file.equals(other.file))));
280 protected void set(String protocol, String host, int port, String file,
281 String ref)
283 // TBD: Theoretically, a poorly written StreamHandler could pass an
284 // invalid protocol. It will cause the handler to be set to null
285 // thus overriding a valid handler. Callers of this method should
286 // be aware of this.
287 this.handler = setURLStreamHandler(protocol);
288 this.protocol = protocol;
289 this.port = port;
290 this.host = host;
291 this.file = file;
292 this.ref = ref;
295 public static synchronized void
296 setURLStreamHandlerFactory(URLStreamHandlerFactory fac)
298 if (factory != null)
299 throw new Error("URLStreamHandlerFactory already set");
301 // Throw an exception if an extant security mgr precludes
302 // setting the factory.
303 SecurityManager s = System.getSecurityManager();
304 if (s != null)
305 s.checkSetFactory();
306 factory = fac;
309 public String toExternalForm()
311 // Identical to toString().
312 return handler.toExternalForm(this);
315 public String toString()
317 // Identical to toExternalForm().
318 return handler.toExternalForm(this);
321 private URLStreamHandler setURLStreamHandler(String protocol)
323 URLStreamHandler handler;
325 // See if a handler has been cached for this protocol.
326 if ((handler = (URLStreamHandler) handlers.get(protocol)) != null)
327 return handler;
329 // If a non-default factory has been set, use it to find the protocol.
330 if (factory != null)
331 handler = factory.createURLStreamHandler(protocol);
333 // Non-default factory may have returned null or a factory wasn't set.
334 // Use the default search algorithm to find a handler for this protocol.
335 if (handler == null)
337 // Get the list of packages to check and append our default handler
338 // to it, along with the JDK specified default as a last resort.
339 // Except in very unusual environments the JDK specified one shouldn't
340 // ever be needed (or available).
341 String propVal = System.getProperty("java.protocol.handler.pkgs");
342 propVal = (propVal == null) ? "" : (propVal + "|");
343 propVal = propVal + "gnu.gcj.protocol|sun.net.www.protocol";
345 StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
348 String facName = pkgPrefix.nextToken() + "." + protocol +
349 ".Handler";
352 handler =
353 (URLStreamHandler) Class.forName(facName).newInstance();
355 catch (Exception e)
357 // Can't instantiate; handler still null, go on to next element.
359 } while ((handler == null ||
360 ! (handler instanceof URLStreamHandler)) &&
361 pkgPrefix.hasMoreTokens());
364 // Update the hashtable with the new protocol handler.
365 if (handler != null)
366 if (handler instanceof URLStreamHandler)
367 handlers.put(protocol, handler);
368 else
369 handler = null;
371 return handler;