Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / java / net / URL.java
blob967cc80f69b81fcd1acf778756d7fe86cb479cf5
1 /* URL.java -- Uniform Resource Locator Class
2 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
39 package java.net;
41 import gnu.classpath.SystemProperties;
42 import gnu.java.net.URLParseError;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.ObjectInputStream;
47 import java.io.ObjectOutputStream;
48 import java.io.Serializable;
49 import java.security.AccessController;
50 import java.security.PrivilegedAction;
51 import java.util.HashMap;
52 import java.util.StringTokenizer;
56 * Written using on-line Java Platform 1.2 API Specification, as well
57 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
58 * Status: Believed complete and correct.
61 /**
62 * This final class represents an Internet Uniform Resource Locator (URL).
63 * For details on the syntax of URL's and what they can be used for,
64 * refer to RFC 1738, available from <a
65 * href="http://ds.internic.net/rfcs/rfc1738.txt">
66 * http://ds.internic.net/rfcs/rfc1738.txt</a>
67 * <p>
68 * There are a great many protocols supported by URL's such as "http",
69 * "ftp", and "file". This object can handle any arbitrary URL for which
70 * a URLStreamHandler object can be written. Default protocol handlers
71 * are provided for the "http" and "ftp" protocols. Additional protocols
72 * handler implementations may be provided in the future. In any case,
73 * an application or applet can install its own protocol handlers that
74 * can be "chained" with other protocol hanlders in the system to extend
75 * the base functionality provided with this class. (Note, however, that
76 * unsigned applets cannot access properties by default or install their
77 * own protocol handlers).
78 * <p>
79 * This chaining is done via the system property java.protocol.handler.pkgs
80 * If this property is set, it is assumed to be a "|" separated list of
81 * package names in which to attempt locating protocol handlers. The
82 * protocol handler is searched for by appending the string
83 * ".&lt;protocol&gt;.Handler" to each packed in the list until a hander is
84 * found. If a protocol handler is not found in this list of packages, or if
85 * the property does not exist, then the default protocol handler of
86 * "gnu.java.net.&lt;protocol&gt;.Handler" is tried. If this is
87 * unsuccessful, a MalformedURLException is thrown.
88 * <p>
89 * All of the constructor methods of URL attempt to load a protocol
90 * handler and so any needed protocol handlers must be installed when
91 * the URL is constructed.
92 * <p>
93 * Here is an example of how URL searches for protocol handlers. Assume
94 * the value of java.protocol.handler.pkgs is "com.foo|com.bar" and the
95 * URL is "news://comp.lang.java.programmer". URL would looking the
96 * following places for protocol handlers:
97 * <p><pre>
98 * com.foo.news.Handler
99 * com.bar.news.Handler
100 * gnu.java.net.news.Handler
101 * </pre><p>
102 * If the protocol handler is not found in any of those locations, a
103 * MalformedURLException would be thrown.
104 * <p>
105 * Please note that a protocol handler must be a subclass of
106 * URLStreamHandler.
107 * <p>
108 * Normally, this class caches protocol handlers. Once it finds a handler
109 * for a particular protocol, it never tries to look up a new handler
110 * again. However, if the system property
111 * gnu.java.net.nocache_protocol_handlers is set, then this
112 * caching behavior is disabled. This property is specific to this
113 * implementation. Sun's JDK may or may not do protocol caching, but it
114 * almost certainly does not examine this property.
115 * <p>
116 * Please also note that an application can install its own factory for
117 * loading protocol handlers (see setURLStreamHandlerFactory). If this is
118 * done, then the above information is superseded and the behavior of this
119 * class in loading protocol handlers is dependent on that factory.
121 * @author Aaron M. Renn (arenn@urbanophile.com)
122 * @author Warren Levy (warrenl@cygnus.com)
124 * @see URLStreamHandler
126 public final class URL implements Serializable
128 private static final String DEFAULT_SEARCH_PATH =
129 "gnu.java.net.protocol|gnu.inet";
131 // Cached System ClassLoader
132 private static ClassLoader systemClassLoader;
135 * The name of the protocol for this URL.
136 * The protocol is always stored in lower case.
138 private String protocol;
141 * The "authority" portion of the URL.
143 private String authority;
146 * The hostname or IP address of this protocol.
147 * This includes a possible user. For example <code>joe@some.host.net</code>.
149 private String host;
152 * The user information necessary to establish the connection.
154 private String userInfo;
157 * The port number of this protocol or -1 if the port number used is
158 * the default for this protocol.
160 private int port = -1; // Initialize for constructor using context.
163 * The "file" portion of the URL. It is defined as <code>path[?query]</code>.
165 private String file;
168 * The anchor portion of the URL.
170 private String ref;
173 * This is the hashCode for this URL
175 private int hashCode;
178 * The protocol handler in use for this URL
180 transient URLStreamHandler ph;
183 * If an application installs its own protocol handler factory, this is
184 * where we keep track of it.
186 private static URLStreamHandlerFactory factory;
187 private static final long serialVersionUID = -7627629688361524110L;
190 * This a table where we cache protocol handlers to avoid the overhead
191 * of looking them up each time.
193 private static HashMap ph_cache = new HashMap();
196 * Whether or not to cache protocol handlers.
198 private static boolean cache_handlers;
200 static
202 String s = SystemProperties.getProperty("gnu.java.net.nocache_protocol_handlers");
204 if (s == null)
205 cache_handlers = true;
206 else
207 cache_handlers = false;
211 * Constructs a URL and loads a protocol handler for the values passed as
212 * arguments.
214 * @param protocol The protocol for this URL ("http", "ftp", etc)
215 * @param host The hostname or IP address to connect to
216 * @param port The port number to use, or -1 to use the protocol's
217 * default port
218 * @param file The "file" portion of the URL.
220 * @exception MalformedURLException If a protocol handler cannot be loaded or
221 * a parse error occurs.
223 public URL(String protocol, String host, int port, String file)
224 throws MalformedURLException
226 this(protocol, host, port, file, null);
230 * Constructs a URL and loads a protocol handler for the values passed in
231 * as arugments. Uses the default port for the protocol.
233 * @param protocol The protocol for this URL ("http", "ftp", etc)
234 * @param host The hostname or IP address for this URL
235 * @param file The "file" portion of this URL.
237 * @exception MalformedURLException If a protocol handler cannot be loaded or
238 * a parse error occurs.
240 public URL(String protocol, String host, String file)
241 throws MalformedURLException
243 this(protocol, host, -1, file, null);
247 * This method initializes a new instance of <code>URL</code> with the
248 * specified protocol, host, port, and file. Additionally, this method
249 * allows the caller to specify a protocol handler to use instead of
250 * the default. If this handler is specified, the caller must have
251 * the "specifyStreamHandler" permission (see <code>NetPermission</code>)
252 * or a <code>SecurityException</code> will be thrown.
254 * @param protocol The protocol for this URL ("http", "ftp", etc)
255 * @param host The hostname or IP address to connect to
256 * @param port The port number to use, or -1 to use the protocol's default
257 * port
258 * @param file The "file" portion of the URL.
259 * @param ph The protocol handler to use with this URL.
261 * @exception MalformedURLException If no protocol handler can be loaded
262 * for the specified protocol.
263 * @exception SecurityException If the <code>SecurityManager</code> exists
264 * and does not allow the caller to specify its own protocol handler.
266 * @since 1.2
268 public URL(String protocol, String host, int port, String file,
269 URLStreamHandler ph) throws MalformedURLException
271 if (protocol == null)
272 throw new MalformedURLException("null protocol");
273 protocol = protocol.toLowerCase();
274 this.protocol = protocol;
276 if (ph != null)
278 SecurityManager s = System.getSecurityManager();
279 if (s != null)
280 s.checkPermission(new NetPermission("specifyStreamHandler"));
282 this.ph = ph;
284 else
285 this.ph = getURLStreamHandler(protocol);
287 if (this.ph == null)
288 throw new MalformedURLException("Protocol handler not found: "
289 + protocol);
291 this.host = host;
292 this.port = port;
293 this.authority = (host != null) ? host : "";
294 if (port >= 0 && host != null)
295 this.authority += ":" + port;
297 int hashAt = file.indexOf('#');
298 if (hashAt < 0)
300 this.file = file;
301 this.ref = null;
303 else
305 this.file = file.substring(0, hashAt);
306 this.ref = file.substring(hashAt + 1);
308 hashCode = hashCode(); // Used for serialization.
312 * Initializes a URL from a complete string specification such as
313 * "http://www.urbanophile.com/arenn/". First the protocol name is parsed
314 * out of the string. Then a handler is located for that protocol and
315 * the parseURL() method of that protocol handler is used to parse the
316 * remaining fields.
318 * @param spec The complete String representation of a URL
320 * @exception MalformedURLException If a protocol handler cannot be found
321 * or the URL cannot be parsed
323 public URL(String spec) throws MalformedURLException
325 this((URL) null, spec != null ? spec : "", (URLStreamHandler) null);
329 * This method parses a String representation of a URL within the
330 * context of an existing URL. Principally this means that any
331 * fields not present the URL are inheritied from the context URL.
332 * This allows relative URL's to be easily constructed. If the
333 * context argument is null, then a complete URL must be specified
334 * in the URL string. If the protocol parsed out of the URL is
335 * different from the context URL's protocol, then then URL String
336 * is also expected to be a complete URL.
338 * @param context The context on which to parse the specification
339 * @param spec The string to parse an URL
341 * @exception MalformedURLException If a protocol handler cannot be found
342 * for the URL cannot be parsed
344 public URL(URL context, String spec) throws MalformedURLException
346 this(context, spec, (context == null) ? (URLStreamHandler)null : context.ph);
350 * Creates an URL from given arguments
351 * This method parses a String representation of a URL within the
352 * context of an existing URL. Principally this means that any fields
353 * not present the URL are inheritied from the context URL. This allows
354 * relative URL's to be easily constructed. If the context argument is
355 * null, then a complete URL must be specified in the URL string.
356 * If the protocol parsed out of the URL is different
357 * from the context URL's protocol, then then URL String is also
358 * expected to be a complete URL.
359 * <p>
360 * Additionally, this method allows the caller to specify a protocol handler
361 * to use instead of the default. If this handler is specified, the caller
362 * must have the "specifyStreamHandler" permission
363 * (see <code>NetPermission</code>) or a <code>SecurityException</code>
364 * will be thrown.
366 * @param context The context in which to parse the specification
367 * @param spec The string to parse as an URL
368 * @param ph The stream handler for the URL
370 * @exception MalformedURLException If a protocol handler cannot be found
371 * or the URL cannot be parsed
372 * @exception SecurityException If the <code>SecurityManager</code> exists
373 * and does not allow the caller to specify its own protocol handler.
375 * @since 1.2
377 public URL(URL context, String spec, URLStreamHandler ph)
378 throws MalformedURLException
380 /* A protocol is defined by the doc as the substring before a ':'
381 * as long as the ':' occurs before any '/'.
383 * If context is null, then spec must be an absolute URL.
385 * The relative URL need not specify all the components of a URL.
386 * If the protocol, host name, or port number is missing, the value
387 * is inherited from the context. A bare file component is appended
388 * to the context's file. The optional anchor is not inherited.
391 // If this is an absolute URL, then ignore context completely.
392 // An absolute URL must have chars prior to "://" but cannot have a colon
393 // right after the "://". The second colon is for an optional port value
394 // and implies that the host from the context is used if available.
395 int colon;
396 int slash = spec.indexOf('/');
397 if ((colon = spec.indexOf("://", 1)) > 0
398 && ((colon < slash || slash < 0))
399 && ! spec.regionMatches(colon, "://:", 0, 4))
400 context = null;
402 boolean protocolSpecified = false;
404 if ((colon = spec.indexOf(':')) > 0
405 && (colon < slash || slash < 0))
407 // Protocol may have been specified in spec string.
408 protocolSpecified = true;
409 protocol = spec.substring(0, colon).toLowerCase();
410 if (context != null)
412 if (context.protocol.equals(protocol))
414 // The 1.2 doc specifically says these are copied to the new URL.
415 host = context.host;
416 port = context.port;
417 userInfo = context.userInfo;
418 authority = context.authority;
420 else
422 // There was a colon in the spec. Check to see if
423 // what precedes it is a valid protocol. If it was
424 // not, assume that it is relative to the context.
425 URLStreamHandler specPh = getURLStreamHandler(protocol.trim());
426 if (null == specPh)
427 protocolSpecified = false;
432 if (!protocolSpecified)
434 if (context != null)
436 // Protocol NOT specified in spec string.
437 // Use context fields (except ref) as a foundation for relative URLs.
438 colon = -1;
439 protocol = context.protocol;
440 host = context.host;
441 port = context.port;
442 userInfo = context.userInfo;
443 if (spec.indexOf(":/", 1) < 0)
445 file = context.file;
446 if (file == null || file.length() == 0)
447 file = "/";
449 authority = context.authority;
451 else // Protocol NOT specified in spec. and no context available.
452 throw new MalformedURLException("Absolute URL required with null"
453 + " context: " + spec);
456 protocol = protocol.trim();
458 if (ph != null)
460 SecurityManager s = System.getSecurityManager();
461 if (s != null)
462 s.checkPermission(new NetPermission("specifyStreamHandler"));
464 this.ph = ph;
466 else
467 this.ph = getURLStreamHandler(protocol);
469 if (this.ph == null)
470 throw new MalformedURLException("Protocol handler not found: "
471 + protocol);
473 // JDK 1.2 doc for parseURL specifically states that any '#' ref
474 // is to be excluded by passing the 'limit' as the indexOf the '#'
475 // if one exists, otherwise pass the end of the string.
476 int hashAt = spec.indexOf('#', colon + 1);
480 this.ph.parseURL(this, spec, colon + 1,
481 hashAt < 0 ? spec.length() : hashAt);
483 catch (URLParseError e)
485 throw new MalformedURLException(e.getMessage());
488 if (hashAt >= 0)
489 ref = spec.substring(hashAt + 1);
491 hashCode = hashCode(); // Used for serialization.
495 * Test another URL for equality with this one. This will be true only if
496 * the argument is non-null and all of the fields in the URL's match
497 * exactly (ie, protocol, host, port, file, and ref). Overrides
498 * Object.equals(), implemented by calling the equals method of the handler.
500 * @param obj The URL to compare with
502 * @return true if the URL is equal, false otherwise
504 public boolean equals(Object obj)
506 if (! (obj instanceof URL))
507 return false;
509 return ph.equals(this, (URL) obj);
513 * Returns the contents of this URL as an object by first opening a
514 * connection, then calling the getContent() method against the connection
516 * @return A content object for this URL
517 * @exception IOException If opening the connection or getting the
518 * content fails.
520 * @since 1.3
522 public Object getContent() throws IOException
524 return openConnection().getContent();
528 * Gets the contents of this URL
530 * @param classes The allow classes for the content object.
532 * @return a context object for this URL.
534 * @exception IOException If an error occurs
536 public Object getContent(Class[] classes) throws IOException
538 // FIXME: implement this
539 return getContent();
543 * Returns the file portion of the URL.
544 * Defined as <code>path[?query]</code>.
545 * Returns the empty string if there is no file portion.
547 * @return The filename specified in this URL, or an empty string if empty.
549 public String getFile()
551 return file == null ? "" : file;
555 * Returns the path of the URL. This is the part of the file before any '?'
556 * character.
558 * @return The path specified in this URL, or null if empty.
560 * @since 1.3
562 public String getPath()
564 // The spec says we need to return an empty string, but some
565 // applications depends on receiving null when the path is empty.
566 if (file == null)
567 return null;
568 int quest = file.indexOf('?');
569 return quest < 0 ? getFile() : file.substring(0, quest);
573 * Returns the authority of the URL
575 * @return The authority specified in this URL.
577 * @since 1.3
579 public String getAuthority()
581 return authority;
585 * Returns the host of the URL
587 * @return The host specified in this URL.
589 public String getHost()
591 int at = (host == null) ? -1 : host.indexOf('@');
592 return at < 0 ? host : host.substring(at + 1, host.length());
596 * Returns the port number of this URL or -1 if the default port number is
597 * being used.
599 * @return The port number
601 * @see #getDefaultPort()
603 public int getPort()
605 return port;
609 * Returns the default port of the URL. If the StreamHandler for the URL
610 * protocol does not define a default port it returns -1.
612 * @return The default port of the current protocol.
614 public int getDefaultPort()
616 return ph.getDefaultPort();
620 * Returns the protocol of the URL
622 * @return The specified protocol.
624 public String getProtocol()
626 return protocol;
630 * Returns the ref (sometimes called the "# reference" or "anchor") portion
631 * of the URL.
633 * @return The ref
635 public String getRef()
637 return ref;
641 * Returns the user information of the URL. This is the part of the host
642 * name before the '@'.
644 * @return the user at a particular host or null when no user defined.
646 public String getUserInfo()
648 if (userInfo != null)
649 return userInfo;
650 int at = (host == null) ? -1 : host.indexOf('@');
651 return at < 0 ? null : host.substring(0, at);
655 * Returns the query of the URL. This is the part of the file before the
656 * '?'.
658 * @return the query part of the file, or null when there is no query part.
660 public String getQuery()
662 int quest = (file == null) ? -1 : file.indexOf('?');
663 return quest < 0 ? null : file.substring(quest + 1, file.length());
667 * Returns a hashcode computed by the URLStreamHandler of this URL
669 * @return The hashcode for this URL.
671 public int hashCode()
673 if (hashCode != 0)
674 return hashCode; // Use cached value if available.
675 else
676 return ph.hashCode(this);
680 * Returns a URLConnection object that represents a connection to the remote
681 * object referred to by the URL. The URLConnection is created by calling the
682 * openConnection() method of the protocol handler
684 * @return A URLConnection for this URL
686 * @exception IOException If an error occurs
688 public URLConnection openConnection() throws IOException
690 return ph.openConnection(this);
694 * Opens a connection to this URL and returns an InputStream for reading
695 * from that connection
697 * @return An <code>InputStream</code> for this URL.
699 * @exception IOException If an error occurs
701 public InputStream openStream() throws IOException
703 return openConnection().getInputStream();
707 * Tests whether or not another URL refers to the same "file" as this one.
708 * This will be true if and only if the passed object is not null, is a
709 * URL, and matches all fields but the ref (ie, protocol, host, port,
710 * and file);
712 * @param url The URL object to test with
714 * @return true if URL matches this URL's file, false otherwise
716 public boolean sameFile(URL url)
718 return ph.sameFile(this, url);
722 * Sets the specified fields of the URL. This is not a public method so
723 * that only URLStreamHandlers can modify URL fields. This might be called
724 * by the <code>parseURL()</code> method in that class. URLs are otherwise
725 * constant. If the given protocol does not exist, it will keep the previously
726 * set protocol.
728 * @param protocol The protocol name for this URL
729 * @param host The hostname or IP address for this URL
730 * @param port The port number of this URL
731 * @param file The "file" portion of this URL.
732 * @param ref The anchor portion of this URL.
734 protected void set(String protocol, String host, int port, String file,
735 String ref)
737 URLStreamHandler protocolHandler = null;
738 protocol = protocol.toLowerCase();
739 if (! this.protocol.equals(protocol))
740 protocolHandler = getURLStreamHandler(protocol);
742 // It is an hidden feature of the JDK. If the protocol does not exist,
743 // we keep the previously initialized protocol.
744 if (protocolHandler != null)
746 this.ph = protocolHandler;
747 this.protocol = protocol;
749 this.authority = "";
750 this.port = port;
751 this.host = host;
752 this.file = file;
753 this.ref = ref;
755 if (host != null)
756 this.authority += host;
757 if (port >= 0)
758 this.authority += ":" + port;
760 hashCode = hashCode(); // Used for serialization.
764 * Sets the specified fields of the URL. This is not a public method so
765 * that only URLStreamHandlers can modify URL fields. URLs are otherwise
766 * constant. If the given protocol does not exist, it will keep the previously
767 * set protocol.
769 * @param protocol The protocol name for this URL.
770 * @param host The hostname or IP address for this URL.
771 * @param port The port number of this URL.
772 * @param authority The authority of this URL.
773 * @param userInfo The user and password (if needed) of this URL.
774 * @param path The "path" portion of this URL.
775 * @param query The query of this URL.
776 * @param ref The anchor portion of this URL.
778 * @since 1.3
780 protected void set(String protocol, String host, int port, String authority,
781 String userInfo, String path, String query, String ref)
783 URLStreamHandler protocolHandler = null;
784 protocol = protocol.toLowerCase();
785 if (! this.protocol.equals(protocol))
786 protocolHandler = getURLStreamHandler(protocol);
788 // It is an hidden feature of the JDK. If the protocol does not exist,
789 // we keep the previously initialized protocol.
790 if (protocolHandler != null)
792 this.ph = protocolHandler;
793 this.protocol = protocol;
795 this.host = host;
796 this.userInfo = userInfo;
797 this.port = port;
798 this.authority = authority;
799 if (query == null)
800 this.file = path;
801 else
802 this.file = path + "?" + query;
803 this.ref = ref;
804 hashCode = hashCode(); // Used for serialization.
808 * Sets the URLStreamHandlerFactory for this class. This factory is
809 * responsible for returning the appropriate protocol handler for
810 * a given URL.
812 * @param fac The URLStreamHandlerFactory class to use
814 * @exception Error If the factory is alread set.
815 * @exception SecurityException If a security manager exists and its
816 * checkSetFactory method doesn't allow the operation
818 public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac)
820 if (factory != null)
821 throw new Error("URLStreamHandlerFactory already set");
823 // Throw an exception if an extant security mgr precludes
824 // setting the factory.
825 SecurityManager s = System.getSecurityManager();
826 if (s != null)
827 s.checkSetFactory();
828 factory = fac;
832 * Returns a String representing this URL. The String returned is
833 * created by calling the protocol handler's toExternalForm() method.
835 * @return A string for this URL
837 public String toExternalForm()
839 // Identical to toString().
840 return ph.toExternalForm(this);
844 * Returns a String representing this URL. Identical to toExternalForm().
845 * The value returned is created by the protocol handler's
846 * toExternalForm method. Overrides Object.toString()
848 * @return A string for this URL
850 public String toString()
852 // Identical to toExternalForm().
853 return ph.toExternalForm(this);
857 * This internal method is used in two different constructors to load
858 * a protocol handler for this URL.
860 * @param protocol The protocol to load a handler for
862 * @return A URLStreamHandler for this protocol, or null when not found.
864 private static synchronized URLStreamHandler getURLStreamHandler(String protocol)
866 URLStreamHandler ph = null;
868 // First, see if a protocol handler is in our cache.
869 if (cache_handlers)
871 if ((ph = (URLStreamHandler) ph_cache.get(protocol)) != null)
872 return ph;
875 // If a non-default factory has been set, use it to find the protocol.
876 if (factory != null)
878 ph = factory.createURLStreamHandler(protocol);
881 // Non-default factory may have returned null or a factory wasn't set.
882 // Use the default search algorithm to find a handler for this protocol.
883 if (ph == null)
885 // Get the list of packages to check and append our default handler
886 // to it, along with the JDK specified default as a last resort.
887 // Except in very unusual environments the JDK specified one shouldn't
888 // ever be needed (or available).
889 String ph_search_path =
890 SystemProperties.getProperty("java.protocol.handler.pkgs");
892 // Tack our default package on at the ends.
893 if (ph_search_path != null)
894 ph_search_path += "|" + DEFAULT_SEARCH_PATH;
895 else
896 ph_search_path = DEFAULT_SEARCH_PATH;
898 // Finally loop through our search path looking for a match.
899 StringTokenizer pkgPrefix = new StringTokenizer(ph_search_path, "|");
901 // Cache the systemClassLoader
902 if (systemClassLoader == null)
904 systemClassLoader = (ClassLoader) AccessController.doPrivileged
905 (new PrivilegedAction() {
906 public Object run()
908 return ClassLoader.getSystemClassLoader();
917 // Try to get a class from the system/application
918 // classloader, initialize it, make an instance
919 // and try to cast it to a URLStreamHandler.
920 String clsName =
921 (pkgPrefix.nextToken() + "." + protocol + ".Handler");
922 Class c = Class.forName(clsName, true, systemClassLoader);
923 ph = (URLStreamHandler) c.newInstance();
925 catch (ThreadDeath death)
927 throw death;
929 catch (Throwable t)
931 // Ignored.
934 while (ph == null && pkgPrefix.hasMoreTokens());
937 // Update the hashtable with the new protocol handler.
938 if (ph != null && cache_handlers)
939 ph_cache.put(protocol, ph);
940 else
941 ph = null;
943 return ph;
946 private void readObject(ObjectInputStream ois)
947 throws IOException, ClassNotFoundException
949 ois.defaultReadObject();
950 this.ph = getURLStreamHandler(protocol);
951 if (this.ph == null)
952 throw new IOException("Handler for protocol " + protocol + " not found");
955 private void writeObject(ObjectOutputStream oos) throws IOException
957 oos.defaultWriteObject();
961 * Returns the equivalent <code>URI</code> object for this <code>URL</code>.
962 * This is the same as calling <code>new URI(this.toString())</code>.
963 * RFC2396-compliant URLs are guaranteed a successful conversion to
964 * a <code>URI</code> instance. However, there are some values which
965 * form valid URLs, but which do not also form RFC2396-compliant URIs.
967 * @throws URISyntaxException if this URL is not RFC2396-compliant,
968 * and thus can not be successfully converted to a URI.
970 public URI toURI()
971 throws URISyntaxException
973 return new URI(toString());