Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for java.net.URL

 1:  /* URL.java -- Uniform Resource Locator Class
 2:  Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
 3:  Free Software Foundation, Inc.
 4: 
 5: This file is part of GNU Classpath.
 6: 
 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.
 11: 
 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.
 16: 
 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.
 21: 
 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.
 26: 
 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. */
 38: 
 39:  package java.net;
 40: 
 41:  import gnu.classpath.SystemProperties;
 42:  import gnu.java.net.URLParseError;
 43: 
 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;
 53: 
 54: 
 55:  /*
 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.
 59:  */
 60: 
 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.
 120:  *
 121:  * @author Aaron M. Renn (arenn@urbanophile.com)
 122:  * @author Warren Levy (warrenl@cygnus.com)
 123:  *
 124:  * @see URLStreamHandler
 125:  */
 126:  public final class URL implements Serializable
 127: {
 128:  private static final String DEFAULT_SEARCH_PATH =
 129:  "gnu.java.net.protocol|gnu.inet";
 130: 
 131:  // Cached System ClassLoader
 132:  private static ClassLoader systemClassLoader;
 133: 
 134:  /**
 135:  * The name of the protocol for this URL.
 136:  * The protocol is always stored in lower case.
 137:  */
 138:  private String protocol;
 139: 
 140:  /**
 141:  * The "authority" portion of the URL.
 142:  */
 143:  private String authority;
 144: 
 145:  /**
 146:  * The hostname or IP address of this protocol.
 147:  * This includes a possible user. For example <code>joe@some.host.net</code>.
 148:  */
 149:  private String host;
 150: 
 151:  /**
 152:  * The user information necessary to establish the connection.
 153:  */
 154:  private String userInfo;
 155: 
 156:  /**
 157:  * The port number of this protocol or -1 if the port number used is
 158:  * the default for this protocol.
 159:  */
 160:  private int port = -1; // Initialize for constructor using context.
 161: 
 162:  /**
 163:  * The "file" portion of the URL. It is defined as <code>path[?query]</code>.
 164:  */
 165:  private String file;
 166: 
 167:  /**
 168:  * The anchor portion of the URL.
 169:  */
 170:  private String ref;
 171: 
 172:  /**
 173:  * This is the hashCode for this URL
 174:  */
 175:  private int hashCode;
 176: 
 177:  /**
 178:  * The protocol handler in use for this URL
 179:  */
 180:  transient URLStreamHandler ph;
 181: 
 182:  /**
 183:  * If an application installs its own protocol handler factory, this is
 184:  * where we keep track of it.
 185:  */
 186:  private static URLStreamHandlerFactory factory;
 187:  private static final long serialVersionUID = -7627629688361524110L;
 188: 
 189:  /**
 190:  * This a table where we cache protocol handlers to avoid the overhead
 191:  * of looking them up each time.
 192:  */
 193:  private static HashMap<String, URLStreamHandler> ph_cache
 194:  = new HashMap<String, URLStreamHandler>();
 195: 
 196:  /**
 197:  * Whether or not to cache protocol handlers.
 198:  */
 199:  private static boolean cache_handlers;
 200: 
 201:  static
 202:  {
 203:  String s = SystemProperties.getProperty("gnu.java.net.nocache_protocol_handlers");
 204: 
 205:  if (s == null)
 206:  cache_handlers = true;
 207:  else
 208:  cache_handlers = false;
 209:  }
 210: 
 211:  /**
 212:  * Constructs a URL and loads a protocol handler for the values passed as
 213:  * arguments.
 214:  *
 215:  * @param protocol The protocol for this URL ("http", "ftp", etc)
 216:  * @param host The hostname or IP address to connect to
 217:  * @param port The port number to use, or -1 to use the protocol's
 218:  * default port
 219:  * @param file The "file" portion of the URL.
 220:  *
 221:  * @exception MalformedURLException If a protocol handler cannot be loaded or
 222:  * a parse error occurs.
 223:  */
 224:  public URL(String protocol, String host, int port, String file)
 225:  throws MalformedURLException
 226:  {
 227:  this(protocol, host, port, file, null);
 228:  }
 229: 
 230:  /**
 231:  * Constructs a URL and loads a protocol handler for the values passed in
 232:  * as arugments. Uses the default port for the protocol.
 233:  *
 234:  * @param protocol The protocol for this URL ("http", "ftp", etc)
 235:  * @param host The hostname or IP address for this URL
 236:  * @param file The "file" portion of this URL.
 237:  *
 238:  * @exception MalformedURLException If a protocol handler cannot be loaded or
 239:  * a parse error occurs.
 240:  */
 241:  public URL(String protocol, String host, String file)
 242:  throws MalformedURLException
 243:  {
 244:  this(protocol, host, -1, file, null);
 245:  }
 246: 
 247:  /**
 248:  * This method initializes a new instance of <code>URL</code> with the
 249:  * specified protocol, host, port, and file. Additionally, this method
 250:  * allows the caller to specify a protocol handler to use instead of
 251:  * the default. If this handler is specified, the caller must have
 252:  * the "specifyStreamHandler" permission (see <code>NetPermission</code>)
 253:  * or a <code>SecurityException</code> will be thrown.
 254:  *
 255:  * @param protocol The protocol for this URL ("http", "ftp", etc)
 256:  * @param host The hostname or IP address to connect to
 257:  * @param port The port number to use, or -1 to use the protocol's default
 258:  * port
 259:  * @param file The "file" portion of the URL.
 260:  * @param ph The protocol handler to use with this URL.
 261:  *
 262:  * @exception MalformedURLException If no protocol handler can be loaded
 263:  * for the specified protocol.
 264:  * @exception SecurityException If the <code>SecurityManager</code> exists
 265:  * and does not allow the caller to specify its own protocol handler.
 266:  *
 267:  * @since 1.2
 268:  */
 269:  public URL(String protocol, String host, int port, String file,
 270:  URLStreamHandler ph) throws MalformedURLException
 271:  {
 272:  if (protocol == null)
 273:  throw new MalformedURLException("null protocol");
 274:  protocol = protocol.toLowerCase();
 275:  this.protocol = protocol;
 276: 
 277:  if (ph != null)
 278:  {
 279:  SecurityManager s = System.getSecurityManager();
 280:  if (s != null)
 281:  s.checkPermission(new NetPermission("specifyStreamHandler"));
 282: 
 283:  this.ph = ph;
 284:  }
 285:  else
 286:  this.ph = getURLStreamHandler(protocol);
 287: 
 288:  if (this.ph == null)
 289:  throw new MalformedURLException("Protocol handler not found: "
 290:  + protocol);
 291: 
 292:  this.host = host;
 293:  this.port = port;
 294:  this.authority = (host != null) ? host : "";
 295:  if (port >= 0 && host != null)
 296:  this.authority += ":" + port;
 297: 
 298:  int hashAt = file.indexOf('#');
 299:  if (hashAt < 0)
 300:  {
 301:  this.file = file;
 302:  this.ref = null;
 303:  }
 304:  else
 305:  {
 306:  this.file = file.substring(0, hashAt);
 307:  this.ref = file.substring(hashAt + 1);
 308:  }
 309:  hashCode = hashCode(); // Used for serialization.
 310:  }
 311: 
 312:  /**
 313:  * Initializes a URL from a complete string specification such as
 314:  * "http://www.urbanophile.com/arenn/". First the protocol name is parsed
 315:  * out of the string. Then a handler is located for that protocol and
 316:  * the parseURL() method of that protocol handler is used to parse the
 317:  * remaining fields.
 318:  *
 319:  * @param spec The complete String representation of a URL
 320:  *
 321:  * @exception MalformedURLException If a protocol handler cannot be found
 322:  * or the URL cannot be parsed
 323:  */
 324:  public URL(String spec) throws MalformedURLException
 325:  {
 326:  this((URL) null, spec != null ? spec : "", (URLStreamHandler) null,
 327:  false);
 328:  }
 329: 
 330:  /**
 331:  * This method parses a String representation of a URL within the
 332:  * context of an existing URL. Principally this means that any
 333:  * fields not present the URL are inheritied from the context URL.
 334:  * This allows relative URL's to be easily constructed. If the
 335:  * context argument is null, then a complete URL must be specified
 336:  * in the URL string. If the protocol parsed out of the URL is
 337:  * different from the context URL's protocol, then then URL String
 338:  * is also expected to be a complete URL.
 339:  *
 340:  * @param context The context on which to parse the specification
 341:  * @param spec The string to parse an URL
 342:  *
 343:  * @exception MalformedURLException If a protocol handler cannot be found
 344:  * for the URL cannot be parsed
 345:  */
 346:  public URL(URL context, String spec) throws MalformedURLException
 347:  {
 348:  this(context, spec,
 349:  (context == null) ? (URLStreamHandler) null : context.ph,
 350:  false);
 351:  }
 352: 
 353:  /**
 354:  * Creates an URL from given arguments
 355:  * This method parses a String representation of a URL within the
 356:  * context of an existing URL. Principally this means that any fields
 357:  * not present the URL are inheritied from the context URL. This allows
 358:  * relative URL's to be easily constructed. If the context argument is
 359:  * null, then a complete URL must be specified in the URL string.
 360:  * If the protocol parsed out of the URL is different
 361:  * from the context URL's protocol, then then URL String is also
 362:  * expected to be a complete URL.
 363:  * <p>
 364:  * Additionally, this method allows the caller to specify a protocol handler
 365:  * to use instead of the default. If this handler is specified, the caller
 366:  * must have the "specifyStreamHandler" permission
 367:  * (see <code>NetPermission</code>) or a <code>SecurityException</code>
 368:  * will be thrown.
 369:  *
 370:  * @param context The context in which to parse the specification
 371:  * @param spec The string to parse as an URL
 372:  * @param ph The stream handler for the URL
 373:  *
 374:  * @exception MalformedURLException If a protocol handler cannot be found
 375:  * or the URL cannot be parsed
 376:  * @exception SecurityException If the <code>SecurityManager</code> exists
 377:  * and does not allow the caller to specify its own protocol handler.
 378:  *
 379:  * @since 1.2
 380:  */
 381:  public URL(URL context, String spec, URLStreamHandler ph)
 382:  throws MalformedURLException
 383:  {
 384:  this(context, spec, ph, true);
 385:  }
 386: 
 387:  /**
 388:  * Private constructor called by all other constructors taking
 389:  * a context and spec.
 390:  *
 391:  * @param context The context in which to parse the specification
 392:  * @param spec The string to parse as an URL
 393:  * @param ph The stream handler for the URL
 394:  * @param phFromUser Whether or not the user supplied the URLStreamHandler
 395:  *
 396:  */
 397:  private URL(URL context, String spec, URLStreamHandler ph,
 398:  boolean phFromUser)
 399:  throws MalformedURLException
 400:  {
 401:  /* A protocol is defined by the doc as the substring before a ':'
 402:  * as long as the ':' occurs before any '/'.
 403:  *
 404:  * If context is null, then spec must be an absolute URL.
 405:  *
 406:  * The relative URL need not specify all the components of a URL.
 407:  * If the protocol, host name, or port number is missing, the value
 408:  * is inherited from the context. A bare file component is appended
 409:  * to the context's file. The optional anchor is not inherited.
 410:  */
 411: 
 412:  // If this is an absolute URL, then ignore context completely.
 413:  // An absolute URL must have chars prior to "://" but cannot have a colon
 414:  // right after the "://". The second colon is for an optional port value
 415:  // and implies that the host from the context is used if available.
 416:  int colon;
 417:  int slash = spec.indexOf('/');
 418:  if ((colon = spec.indexOf("://", 1)) > 0
 419:  && ((colon < slash || slash < 0))
 420:  && ! spec.regionMatches(colon, "://:", 0, 4))
 421:  {
 422:  context = null;
 423:  if (! phFromUser)
 424:  ph = null;
 425:  }
 426: 
 427:  boolean protocolSpecified = false;
 428: 
 429:  if ((colon = spec.indexOf(':')) > 0
 430:  && (colon < slash || slash < 0))
 431:  {
 432:  // Protocol may have been specified in spec string.
 433:  protocolSpecified = true;
 434:  protocol = spec.substring(0, colon).toLowerCase();
 435:  if (context != null)
 436:  {
 437:  if (context.protocol.equals(protocol))
 438:  {
 439:  // The 1.2 doc specifically says these are copied to the new URL.
 440:  host = context.host;
 441:  port = context.port;
 442:  userInfo = context.userInfo;
 443:  authority = context.authority;
 444:  }
 445:  else
 446:  {
 447:  // There was a colon in the spec. Check to see if
 448:  // what precedes it is a valid protocol. If it was
 449:  // not, assume that it is relative to the context.
 450:  URLStreamHandler specPh = getURLStreamHandler(protocol.trim());
 451:  if (null == specPh)
 452:  protocolSpecified = false;
 453:  }
 454:  }
 455:  }
 456: 
 457:  if (!protocolSpecified)
 458:  {
 459:  if (context != null)
 460:  {
 461:  // Protocol NOT specified in spec string.
 462:  // Use context fields (except ref) as a foundation for relative URLs.
 463:  colon = -1;
 464:  protocol = context.protocol;
 465:  host = context.host;
 466:  port = context.port;
 467:  userInfo = context.userInfo;
 468:  if (spec.indexOf(":/", 1) < 0)
 469:  {
 470:  file = context.file;
 471:  if (file == null || file.length() == 0)
 472:  file = "/";
 473:  }
 474:  authority = context.authority;
 475:  }
 476:  else // Protocol NOT specified in spec. and no context available.
 477:  throw new MalformedURLException("Absolute URL required with null"
 478:  + " context: " + spec);
 479:  }
 480: 
 481:  protocol = protocol.trim();
 482: 
 483:  if (ph != null)
 484:  {
 485:  SecurityManager s = System.getSecurityManager();
 486:  if (s != null && phFromUser)
 487:  s.checkPermission(new NetPermission("specifyStreamHandler"));
 488: 
 489:  this.ph = ph;
 490:  }
 491:  else
 492:  this.ph = getURLStreamHandler(protocol);
 493: 
 494:  if (this.ph == null)
 495:  throw new MalformedURLException("Protocol handler not found: "
 496:  + protocol);
 497: 
 498:  // JDK 1.2 doc for parseURL specifically states that any '#' ref
 499:  // is to be excluded by passing the 'limit' as the indexOf the '#'
 500:  // if one exists, otherwise pass the end of the string.
 501:  int hashAt = spec.indexOf('#', colon + 1);
 502: 
 503:  try
 504:  {
 505:  this.ph.parseURL(this, spec, colon + 1,
 506:  hashAt < 0 ? spec.length() : hashAt);
 507:  }
 508:  catch (URLParseError e)
 509:  {
 510:  MalformedURLException mue = new MalformedURLException(e.getMessage());
 511:  mue.initCause(e);
 512:  throw mue;
 513:  }
 514:  catch (RuntimeException e)
 515:  {
 516:  // This isn't documented, but the JDK also catches
 517:  // RuntimeExceptions here.
 518:  MalformedURLException mue = new MalformedURLException(e.getMessage());
 519:  mue.initCause(e);
 520:  throw mue;
 521:  }
 522: 
 523:  if (hashAt >= 0)
 524:  ref = spec.substring(hashAt + 1);
 525: 
 526:  hashCode = hashCode(); // Used for serialization.
 527:  }
 528: 
 529:  /**
 530:  * Test another URL for equality with this one. This will be true only if
 531:  * the argument is non-null and all of the fields in the URL's match
 532:  * exactly (ie, protocol, host, port, file, and ref). Overrides
 533:  * Object.equals(), implemented by calling the equals method of the handler.
 534:  *
 535:  * @param obj The URL to compare with
 536:  *
 537:  * @return true if the URL is equal, false otherwise
 538:  */
 539:  public boolean equals(Object obj)
 540:  {
 541:  if (! (obj instanceof URL))
 542:  return false;
 543: 
 544:  return ph.equals(this, (URL) obj);
 545:  }
 546: 
 547:  /**
 548:  * Returns the contents of this URL as an object by first opening a
 549:  * connection, then calling the getContent() method against the connection
 550:  *
 551:  * @return A content object for this URL
 552:  * @exception IOException If opening the connection or getting the
 553:  * content fails.
 554:  *
 555:  * @since 1.3
 556:  */
 557:  public Object getContent() throws IOException
 558:  {
 559:  return openConnection().getContent();
 560:  }
 561: 
 562:  /**
 563:  * Gets the contents of this URL
 564:  *
 565:  * @param classes The allow classes for the content object.
 566:  *
 567:  * @return a context object for this URL.
 568:  *
 569:  * @exception IOException If an error occurs
 570:  */
 571:  public Object getContent(Class[] classes) throws IOException
 572:  {
 573:  return openConnection().getContent(classes);
 574:  }
 575: 
 576:  /**
 577:  * Returns the file portion of the URL.
 578:  * Defined as <code>path[?query]</code>.
 579:  * Returns the empty string if there is no file portion.
 580:  *
 581:  * @return The filename specified in this URL, or an empty string if empty.
 582:  */
 583:  public String getFile()
 584:  {
 585:  return file == null ? "" : file;
 586:  }
 587: 
 588:  /**
 589:  * Returns the path of the URL. This is the part of the file before any '?'
 590:  * character.
 591:  *
 592:  * @return The path specified in this URL, or null if empty.
 593:  *
 594:  * @since 1.3
 595:  */
 596:  public String getPath()
 597:  {
 598:  // The spec says we need to return an empty string, but some
 599:  // applications depends on receiving null when the path is empty.
 600:  if (file == null)
 601:  return null;
 602:  int quest = file.indexOf('?');
 603:  return quest < 0 ? getFile() : file.substring(0, quest);
 604:  }
 605: 
 606:  /**
 607:  * Returns the authority of the URL
 608:  *
 609:  * @return The authority specified in this URL.
 610:  *
 611:  * @since 1.3
 612:  */
 613:  public String getAuthority()
 614:  {
 615:  return authority;
 616:  }
 617: 
 618:  /**
 619:  * Returns the host of the URL
 620:  *
 621:  * @return The host specified in this URL.
 622:  */
 623:  public String getHost()
 624:  {
 625:  int at = (host == null) ? -1 : host.indexOf('@');
 626:  return at < 0 ? host : host.substring(at + 1, host.length());
 627:  }
 628: 
 629:  /**
 630:  * Returns the port number of this URL or -1 if the default port number is
 631:  * being used.
 632:  *
 633:  * @return The port number
 634:  *
 635:  * @see #getDefaultPort()
 636:  */
 637:  public int getPort()
 638:  {
 639:  return port;
 640:  }
 641: 
 642:  /**
 643:  * Returns the default port of the URL. If the StreamHandler for the URL
 644:  * protocol does not define a default port it returns -1.
 645:  *
 646:  * @return The default port of the current protocol.
 647:  */
 648:  public int getDefaultPort()
 649:  {
 650:  return ph.getDefaultPort();
 651:  }
 652: 
 653:  /**
 654:  * Returns the protocol of the URL
 655:  *
 656:  * @return The specified protocol.
 657:  */
 658:  public String getProtocol()
 659:  {
 660:  return protocol;
 661:  }
 662: 
 663:  /**
 664:  * Returns the ref (sometimes called the "# reference" or "anchor") portion
 665:  * of the URL.
 666:  *
 667:  * @return The ref
 668:  */
 669:  public String getRef()
 670:  {
 671:  return ref;
 672:  }
 673: 
 674:  /**
 675:  * Returns the user information of the URL. This is the part of the host
 676:  * name before the '@'.
 677:  *
 678:  * @return the user at a particular host or null when no user defined.
 679:  */
 680:  public String getUserInfo()
 681:  {
 682:  if (userInfo != null)
 683:  return userInfo;
 684:  int at = (host == null) ? -1 : host.indexOf('@');
 685:  return at < 0 ? null : host.substring(0, at);
 686:  }
 687: 
 688:  /**
 689:  * Returns the query of the URL. This is the part of the file before the
 690:  * '?'.
 691:  *
 692:  * @return the query part of the file, or null when there is no query part.
 693:  */
 694:  public String getQuery()
 695:  {
 696:  int quest = (file == null) ? -1 : file.indexOf('?');
 697:  return quest < 0 ? null : file.substring(quest + 1, file.length());
 698:  }
 699: 
 700:  /**
 701:  * Returns a hashcode computed by the URLStreamHandler of this URL
 702:  *
 703:  * @return The hashcode for this URL.
 704:  */
 705:  public int hashCode()
 706:  {
 707:  if (hashCode != 0)
 708:  return hashCode; // Use cached value if available.
 709:  else
 710:  return ph.hashCode(this);
 711:  }
 712: 
 713:  /**
 714:  * Returns a URLConnection object that represents a connection to the remote
 715:  * object referred to by the URL. The URLConnection is created by calling the
 716:  * openConnection() method of the protocol handler
 717:  *
 718:  * @return A URLConnection for this URL
 719:  *
 720:  * @exception IOException If an error occurs
 721:  */
 722:  public URLConnection openConnection() throws IOException
 723:  {
 724:  return ph.openConnection(this);
 725:  }
 726: 
 727:  /**
 728:  * Opens a connection to this URL and returns an InputStream for reading
 729:  * from that connection
 730:  *
 731:  * @return An <code>InputStream</code> for this URL.
 732:  *
 733:  * @exception IOException If an error occurs
 734:  */
 735:  public InputStream openStream() throws IOException
 736:  {
 737:  return openConnection().getInputStream();
 738:  }
 739: 
 740:  /**
 741:  * Tests whether or not another URL refers to the same "file" as this one.
 742:  * This will be true if and only if the passed object is not null, is a
 743:  * URL, and matches all fields but the ref (ie, protocol, host, port,
 744:  * and file);
 745:  *
 746:  * @param url The URL object to test with
 747:  *
 748:  * @return true if URL matches this URL's file, false otherwise
 749:  */
 750:  public boolean sameFile(URL url)
 751:  {
 752:  return ph.sameFile(this, url);
 753:  }
 754: 
 755:  /**
 756:  * Sets the specified fields of the URL. This is not a public method so
 757:  * that only URLStreamHandlers can modify URL fields. This might be called
 758:  * by the <code>parseURL()</code> method in that class. URLs are otherwise
 759:  * constant. If the given protocol does not exist, it will keep the previously
 760:  * set protocol.
 761:  *
 762:  * @param protocol The protocol name for this URL
 763:  * @param host The hostname or IP address for this URL
 764:  * @param port The port number of this URL
 765:  * @param file The "file" portion of this URL.
 766:  * @param ref The anchor portion of this URL.
 767:  */
 768:  protected void set(String protocol, String host, int port, String file,
 769:  String ref)
 770:  {
 771:  URLStreamHandler protocolHandler = null;
 772:  protocol = protocol.toLowerCase();
 773:  if (! this.protocol.equals(protocol))
 774:  protocolHandler = getURLStreamHandler(protocol);
 775:  
 776:  // It is an hidden feature of the JDK. If the protocol does not exist,
 777:  // we keep the previously initialized protocol.
 778:  if (protocolHandler != null)
 779:  {
 780:  this.ph = protocolHandler;
 781:  this.protocol = protocol;
 782:  }
 783:  this.authority = "";
 784:  this.port = port;
 785:  this.host = host;
 786:  this.file = file;
 787:  this.ref = ref;
 788: 
 789:  if (host != null)
 790:  this.authority += host;
 791:  if (port >= 0)
 792:  this.authority += ":" + port;
 793: 
 794:  hashCode = hashCode(); // Used for serialization.
 795:  }
 796: 
 797:  /**
 798:  * Sets the specified fields of the URL. This is not a public method so
 799:  * that only URLStreamHandlers can modify URL fields. URLs are otherwise
 800:  * constant. If the given protocol does not exist, it will keep the previously
 801:  * set protocol.
 802:  *
 803:  * @param protocol The protocol name for this URL.
 804:  * @param host The hostname or IP address for this URL.
 805:  * @param port The port number of this URL.
 806:  * @param authority The authority of this URL.
 807:  * @param userInfo The user and password (if needed) of this URL.
 808:  * @param path The "path" portion of this URL.
 809:  * @param query The query of this URL.
 810:  * @param ref The anchor portion of this URL.
 811:  *
 812:  * @since 1.3
 813:  */
 814:  protected void set(String protocol, String host, int port, String authority,
 815:  String userInfo, String path, String query, String ref)
 816:  {
 817:  URLStreamHandler protocolHandler = null;
 818:  protocol = protocol.toLowerCase();
 819:  if (! this.protocol.equals(protocol))
 820:  protocolHandler = getURLStreamHandler(protocol);
 821:  
 822:  // It is an hidden feature of the JDK. If the protocol does not exist,
 823:  // we keep the previously initialized protocol.
 824:  if (protocolHandler != null)
 825:  {
 826:  this.ph = protocolHandler;
 827:  this.protocol = protocol;
 828:  }
 829:  this.host = host;
 830:  this.userInfo = userInfo;
 831:  this.port = port;
 832:  this.authority = authority;
 833:  if (query == null)
 834:  this.file = path;
 835:  else
 836:  this.file = path + "?" + query;
 837:  this.ref = ref;
 838:  hashCode = hashCode(); // Used for serialization.
 839:  }
 840: 
 841:  /**
 842:  * Sets the URLStreamHandlerFactory for this class. This factory is
 843:  * responsible for returning the appropriate protocol handler for
 844:  * a given URL.
 845:  *
 846:  * @param fac The URLStreamHandlerFactory class to use
 847:  *
 848:  * @exception Error If the factory is alread set.
 849:  * @exception SecurityException If a security manager exists and its
 850:  * checkSetFactory method doesn't allow the operation
 851:  */
 852:  public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac)
 853:  {
 854:  if (factory != null)
 855:  throw new Error("URLStreamHandlerFactory already set");
 856: 
 857:  // Throw an exception if an extant security mgr precludes
 858:  // setting the factory.
 859:  SecurityManager s = System.getSecurityManager();
 860:  if (s != null)
 861:  s.checkSetFactory();
 862:  factory = fac;
 863:  }
 864: 
 865:  /**
 866:  * Returns a String representing this URL. The String returned is
 867:  * created by calling the protocol handler's toExternalForm() method.
 868:  *
 869:  * @return A string for this URL
 870:  */
 871:  public String toExternalForm()
 872:  {
 873:  // Identical to toString().
 874:  return ph.toExternalForm(this);
 875:  }
 876: 
 877:  /**
 878:  * Returns a String representing this URL. Identical to toExternalForm().
 879:  * The value returned is created by the protocol handler's
 880:  * toExternalForm method. Overrides Object.toString()
 881:  *
 882:  * @return A string for this URL
 883:  */
 884:  public String toString()
 885:  {
 886:  // Identical to toExternalForm().
 887:  return ph.toExternalForm(this);
 888:  }
 889: 
 890:  /**
 891:  * This internal method is used in two different constructors to load
 892:  * a protocol handler for this URL.
 893:  *
 894:  * @param protocol The protocol to load a handler for
 895:  *
 896:  * @return A URLStreamHandler for this protocol, or null when not found.
 897:  */
 898:  private static synchronized URLStreamHandler getURLStreamHandler(String protocol)
 899:  {
 900:  URLStreamHandler ph = null;
 901: 
 902:  // First, see if a protocol handler is in our cache.
 903:  if (cache_handlers)
 904:  {
 905:  if ((ph = ph_cache.get(protocol)) != null)
 906:  return ph;
 907:  }
 908: 
 909:  // If a non-default factory has been set, use it to find the protocol.
 910:  if (factory != null)
 911:  {
 912:  ph = factory.createURLStreamHandler(protocol);
 913:  }
 914: 
 915:  // Non-default factory may have returned null or a factory wasn't set.
 916:  // Use the default search algorithm to find a handler for this protocol.
 917:  if (ph == null)
 918:  {
 919:  // Get the list of packages to check and append our default handler
 920:  // to it, along with the JDK specified default as a last resort.
 921:  // Except in very unusual environments the JDK specified one shouldn't
 922:  // ever be needed (or available).
 923:  String ph_search_path =
 924:  SystemProperties.getProperty("java.protocol.handler.pkgs");
 925: 
 926:  // Tack our default package on at the ends.
 927:  if (ph_search_path != null)
 928:  ph_search_path += "|" + DEFAULT_SEARCH_PATH;
 929:  else
 930:  ph_search_path = DEFAULT_SEARCH_PATH;
 931: 
 932:  // Finally loop through our search path looking for a match.
 933:  StringTokenizer pkgPrefix = new StringTokenizer(ph_search_path, "|");
 934: 
 935:  // Cache the systemClassLoader
 936:  if (systemClassLoader == null)
 937:  {
 938:  systemClassLoader = AccessController.doPrivileged
 939:  (new PrivilegedAction<ClassLoader>() {
 940:  public ClassLoader run()
 941:  {
 942:  return ClassLoader.getSystemClassLoader();
 943:  }
 944:  });
 945:  }
 946: 
 947:  do
 948:  {
 949:  try
 950:  {
 951:  // Try to get a class from the system/application
 952:  // classloader, initialize it, make an instance
 953:  // and try to cast it to a URLStreamHandler.
 954:  String clsName =
 955:  (pkgPrefix.nextToken() + "." + protocol + ".Handler");
 956:  Class c = Class.forName(clsName, true, systemClassLoader);
 957:  ph = (URLStreamHandler) c.newInstance();
 958:  }
 959:  catch (ThreadDeath death)
 960:  {
 961:  throw death;
 962:  }
 963:  catch (Throwable t)
 964:  {
 965:  // Ignored.
 966:  }
 967:  }
 968:  while (ph == null && pkgPrefix.hasMoreTokens());
 969:  }
 970: 
 971:  // Update the hashtable with the new protocol handler.
 972:  if (ph != null && cache_handlers)
 973:  ph_cache.put(protocol, ph);
 974:  else
 975:  ph = null;
 976: 
 977:  return ph;
 978:  }
 979: 
 980:  private void readObject(ObjectInputStream ois)
 981:  throws IOException, ClassNotFoundException
 982:  {
 983:  ois.defaultReadObject();
 984:  this.ph = getURLStreamHandler(protocol);
 985:  if (this.ph == null)
 986:  throw new IOException("Handler for protocol " + protocol + " not found");
 987:  }
 988: 
 989:  private void writeObject(ObjectOutputStream oos) throws IOException
 990:  {
 991:  oos.defaultWriteObject();
 992:  }
 993: 
 994:  /**
 995:  * Returns the equivalent <code>URI</code> object for this <code>URL</code>.
 996:  * This is the same as calling <code>new URI(this.toString())</code>.
 997:  * RFC2396-compliant URLs are guaranteed a successful conversion to
 998:  * a <code>URI</code> instance. However, there are some values which
 999:  * form valid URLs, but which do not also form RFC2396-compliant URIs.
1000:  *
1001:  * @throws URISyntaxException if this URL is not RFC2396-compliant,
1002:  * and thus can not be successfully converted to a URI.
1003:  */
1004:  public URI toURI()
1005:  throws URISyntaxException
1006:  {
1007:  return new URI(toString());
1008:  }
1009: 
1010: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /