1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.net; 19 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.io.ObjectOutputStream; 23 import java.security.AccessController; 24 import java.util.Hashtable; 25 import java.util.StringTokenizer; 26 import org.apache.harmony.luni.util.PriviAction; 27 import org.apache.harmony.luni.util.Util; 28 29 /** 30 * A URL instance specifies the location of a resource on the internet as 31 * specified by RFC 1738. Such a resource can be a simple file or a service 32 * which generates the output dynamically. A URL is divided in its parts 33 * protocol, host name, port, path, file, user-info, query, reference and 34 * authority. However, not each of this parts has to be defined. 35 */ 36 public final class URL implements java.io.Serializable { 37 private static final long serialVersionUID = -7627629688361524110L; 38 39 private static final NetPermission specifyStreamHandlerPermission = new NetPermission( 40 "specifyStreamHandler"); 41 42 private int hashCode; 43 44 /** 45 * The receiver's filename. 46 * 47 * @serial the file of this URL 48 * 49 */ 50 private String file; 51 52 /** 53 * The receiver's protocol identifier. 54 * 55 * @serial the protocol of this URL (http, file) 56 * 57 */ 58 private String protocol = null; 59 60 /** 61 * The receiver's host name. 62 * 63 * @serial the host of this URL 64 * 65 */ 66 private String host; 67 68 /** 69 * The receiver's port number. 70 * 71 * @serial the port of this URL 72 * 73 */ 74 private int port = -1; 75 76 /** 77 * The receiver's authority. 78 * 79 * @serial the authority of this URL 80 * 81 */ 82 private String authority = null; 83 84 /** 85 * The receiver's userInfo. 86 */ 87 private transient String userInfo = null; 88 89 /** 90 * The receiver's path. 91 */ 92 private transient String path = null; 93 94 /** 95 * The receiver's query. 96 */ 97 private transient String query = null; 98 99 /** 100 * The receiver's reference. 101 * 102 * @serial the reference of this URL 103 * 104 */ 105 private String ref = null; 106 107 /** 108 * Cache for storing protocol handler 109 */ 110 private static Hashtable<String, URLStreamHandler> streamHandlers = new Hashtable<String, URLStreamHandler>(); 111 112 /** 113 * The URL Stream (protocol) Handler 114 */ 115 transient URLStreamHandler strmHandler; 116 117 /** 118 * The factory responsible for producing URL Stream (protocol) Handler 119 */ 120 private static URLStreamHandlerFactory streamHandlerFactory; 121 122 /** 123 * Sets the {@code URLStreamHandlerFactory} which creates protocol specific 124 * stream handlers. This method can be invoked only once during an 125 * application's lifetime. If the {@code URLStreamHandlerFactory} is already 126 * set an {@link Error} will be thrown. 127 * <p> 128 * A security check is performed to verify whether the current policy allows 129 * to set the stream handler factory. 130 * 131 * @param streamFactory 132 * the factory to be used for creating stream protocol handlers. 133 */ 134 public static synchronized void setURLStreamHandlerFactory( 135 URLStreamHandlerFactory streamFactory) { 136 if (streamHandlerFactory != null) { 137 throw new Error("Factory already set"); 138 } 139 SecurityManager sm = System.getSecurityManager(); 140 if (sm != null) { 141 sm.checkSetFactory(); 142 } 143 streamHandlers.clear(); 144 streamHandlerFactory = streamFactory; 145 } 146 147 /** 148 * Creates a new URL instance by parsing the string {@code spec}. 149 * 150 * @param spec 151 * the URL string representation which has to be parsed. 152 * @throws MalformedURLException 153 * if the given string {@code spec} could not be parsed as a 154 * URL. 155 */ 156 public URL(String spec) throws MalformedURLException { 157 this((URL) null, spec, (URLStreamHandler) null); 158 } 159 160 /** 161 * Creates a new URL to the specified resource {@code spec}. This URL is 162 * relative to the given {@code context}. If the protocol of the parsed URL 163 * does not match with the protocol of the context URL, then the newly 164 * created URL is absolute and bases only on the given URL represented by 165 * {@code spec}. Otherwise the protocol is defined by the context URL. 166 * 167 * @param context 168 * the URL which is used as the context. 169 * @param spec 170 * the URL string representation which has to be parsed. 171 * @throws MalformedURLException 172 * if the given string {@code spec} could not be parsed as a URL 173 * or an invalid protocol has been found. 174 */ 175 public URL(URL context, String spec) throws MalformedURLException { 176 this(context, spec, (URLStreamHandler) null); 177 } 178 179 /** 180 * Creates a new URL to the specified resource {@code spec}. This URL is 181 * relative to the given {@code context}. The {@code handler} will be used 182 * to parse the URL string representation. If this argument is {@code null} 183 * the default {@code URLStreamHandler} will be used. If the protocol of the 184 * parsed URL does not match with the protocol of the context URL, then the 185 * newly created URL is absolute and bases only on the given URL represented 186 * by {@code spec}. Otherwise the protocol is defined by the context URL. 187 * 188 * @param context 189 * the URL which is used as the context. 190 * @param spec 191 * the URL string representation which has to be parsed. 192 * @param handler 193 * the specific stream handler to be used by this URL. 194 * @throws MalformedURLException 195 * if the given string {@code spec} could not be parsed as a URL 196 * or an invalid protocol has been found. 197 */ 198 public URL(URL context, String spec, URLStreamHandler handler) 199 throws MalformedURLException { 200 if (handler != null) { 201 SecurityManager sm = System.getSecurityManager(); 202 if (sm != null) { 203 sm.checkPermission(specifyStreamHandlerPermission); 204 } 205 strmHandler = handler; 206 } 207 208 if (spec == null) { 209 throw new MalformedURLException(); 210 } 211 spec = spec.trim(); 212 213 // The spec includes a protocol if it includes a colon character 214 // before the first occurrence of a slash character. Note that, 215 // "protocol" is the field which holds this URLs protocol. 216 int index; 217 try { 218 index = spec.indexOf(':'); 219 } catch (NullPointerException e) { 220 throw new MalformedURLException(e.toString()); 221 } 222 int startIPv6Addr = spec.indexOf('['); 223 if (index >= 0) { 224 if ((startIPv6Addr == -1) || (index < startIPv6Addr)) { 225 protocol = spec.substring(0, index); 226 // According to RFC 2396 scheme part should match 227 // the following expression: 228 // alpha *( alpha | digit | "+" | "-" | "." ) 229 char c = protocol.charAt(0); 230 boolean valid = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 231 for (int i = 1; valid && (i < protocol.length()); i++) { 232 c = protocol.charAt(i); 233 valid = ('a' <= c && c <= 'z') || 234 ('A' <= c && c <= 'Z') || 235 ('0' <= c && c <= '9') || 236 (c == '+') || 237 (c == '-') || 238 (c == '.'); 239 } 240 if (!valid) { 241 protocol = null; 242 index = -1; 243 } else { 244 // Ignore case in protocol names. 245 // Scheme is defined by ASCII characters. 246 protocol = Util.toASCIILowerCase(protocol); 247 } 248 } 249 } 250 251 if (protocol != null) { 252 // If the context was specified, and it had the same protocol 253 // as the spec, then fill in the receiver's slots from the values 254 // in the context but still allow them to be over-ridden later 255 // by the values in the spec. 256 if (context != null && protocol.equals(context.getProtocol())) { 257 String cPath = context.getPath(); 258 if (cPath != null && cPath.startsWith("/")) { 259 set(protocol, context.getHost(), context.getPort(), context 260 .getAuthority(), context.getUserInfo(), cPath, 261 context.getQuery(), null); 262 } 263 if (strmHandler == null) { 264 strmHandler = context.strmHandler; 265 } 266 } 267 } else { 268 // If the spec did not include a protocol, then the context 269 // *must* be specified. Fill in the receiver's slots from the 270 // values in the context, but still allow them to be over-ridden 271 // by the values in the ("relative") spec. 272 if (context == null) { 273 throw new MalformedURLException("Protocol not found: " + spec); 274 } 275 set(context.getProtocol(), context.getHost(), context.getPort(), 276 context.getAuthority(), context.getUserInfo(), context 277 .getPath(), context.getQuery(), null); 278 if (strmHandler == null) { 279 strmHandler = context.strmHandler; 280 } 281 } 282 283 // If the stream handler has not been determined, set it 284 // to the default for the specified protocol. 285 if (strmHandler == null) { 286 setupStreamHandler(); 287 if (strmHandler == null) { 288 throw new MalformedURLException("Unknown protocol: " + protocol); 289 } 290 } 291 292 // Let the handler parse the URL. If the handler throws 293 // any exception, throw MalformedURLException instead. 294 // 295 // Note: We want "index" to be the index of the start of the scheme 296 // specific part of the URL. At this point, it will be either 297 // -1 or the index of the colon after the protocol, so we 298 // increment it to point at either character 0 or the character 299 // after the colon. 300 try { 301 strmHandler.parseURL(this, spec, ++index, spec.length()); 302 } catch (Exception e) { 303 throw new MalformedURLException(e.toString()); 304 } 305 306 if (port < -1) { 307 throw new MalformedURLException("Port out of range: " + port); 308 } 309 } 310 311 /** 312 * Creates a new URL instance using the given arguments. The URL uses the 313 * default port for the specified protocol. 314 * 315 * @param protocol 316 * the protocol of the new URL. 317 * @param host 318 * the host name or IP address of the new URL. 319 * @param file 320 * the name of the resource. 321 * @throws MalformedURLException 322 * if the combination of all arguments do not represent a valid 323 * URL or the protocol is invalid. 324 */ 325 public URL(String protocol, String host, String file) 326 throws MalformedURLException { 327 this(protocol, host, -1, file, (URLStreamHandler) null); 328 } 329 330 /** 331 * Creates a new URL instance using the given arguments. The URL uses the 332 * specified port instead of the default port for the given protocol. 333 * 334 * @param protocol 335 * the protocol of the new URL. 336 * @param host 337 * the host name or IP address of the new URL. 338 * @param port 339 * the specific port number of the URL. {@code -1} represents the 340 * default port of the protocol. 341 * @param file 342 * the name of the resource. 343 * @throws MalformedURLException 344 * if the combination of all arguments do not represent a valid 345 * URL or the protocol is invalid. 346 */ 347 public URL(String protocol, String host, int port, String file) 348 throws MalformedURLException { 349 this(protocol, host, port, file, (URLStreamHandler) null); 350 } 351 352 /** 353 * Creates a new URL instance using the given arguments. The URL uses the 354 * specified port instead of the default port for the given protocol. 355 * 356 * @param protocol 357 * the protocol of the new URL. 358 * @param host 359 * the host name or IP address of the new URL. 360 * @param port 361 * the specific port number of the URL. {@code -1} represents the 362 * default port of the protocol. 363 * @param file 364 * the name of the resource. 365 * @param handler 366 * the stream handler to be used by this URL. 367 * @throws MalformedURLException 368 * if the combination of all arguments do not represent a valid 369 * URL or the protocol is invalid. 370 * @throws SecurityException 371 * if {@code handler} is non-{@code null}, and a security 372 * manager is installed that disallows user-defined protocol 373 * handlers. 374 */ 375 public URL(String protocol, String host, int port, String file, 376 URLStreamHandler handler) throws MalformedURLException { 377 if (port < -1) { 378 throw new MalformedURLException("Port out of range: " + port); 379 } 380 381 if (host != null && host.indexOf(":") != -1 && host.charAt(0) != '[') { 382 host = "[" + host + "]"; 383 } 384 385 if (protocol == null) { 386 throw new NullPointerException("Unknown protocol: null"); 387 } 388 389 this.protocol = protocol; 390 this.host = host; 391 this.port = port; 392 393 // Set the fields from the arguments. Handle the case where the 394 // passed in "file" includes both a file and a reference part. 395 int index = -1; 396 index = file.indexOf("#", file.lastIndexOf("/")); 397 if (index >= 0) { 398 this.file = file.substring(0, index); 399 ref = file.substring(index + 1); 400 } else { 401 this.file = file; 402 } 403 fixURL(false); 404 405 // Set the stream handler for the URL either to the handler 406 // argument if it was specified, or to the default for the 407 // receiver's protocol if the handler was null. 408 if (handler == null) { 409 setupStreamHandler(); 410 if (strmHandler == null) { 411 throw new MalformedURLException("Unknown protocol: " + protocol); 412 } 413 } else { 414 SecurityManager sm = System.getSecurityManager(); 415 if (sm != null) { 416 sm.checkPermission(specifyStreamHandlerPermission); 417 } 418 strmHandler = handler; 419 } 420 } 421 422 void fixURL(boolean fixHost) { 423 int index; 424 if (host != null && host.length() > 0) { 425 authority = host; 426 if (port != -1) { 427 authority = authority + ":" + port; 428 } 429 } 430 if (fixHost) { 431 if (host != null && (index = host.lastIndexOf('@')) > -1) { 432 userInfo = host.substring(0, index); 433 host = host.substring(index + 1); 434 } else { 435 userInfo = null; 436 } 437 } 438 if (file != null && (index = file.indexOf('?')) > -1) { 439 query = file.substring(index + 1); 440 path = file.substring(0, index); 441 } else { 442 query = null; 443 path = file; 444 } 445 } 446 447 /** 448 * Sets the properties of this URL using the provided arguments. Only a 449 * {@code URLStreamHandler} can use this method to set fields of the 450 * existing URL instance. A URL is generally constant. 451 * 452 * @param protocol 453 * the protocol to be set. 454 * @param host 455 * the host name to be set. 456 * @param port 457 * the port number to be set. 458 * @param file 459 * the file to be set. 460 * @param ref 461 * the reference to be set. 462 */ 463 protected void set(String protocol, String host, int port, String file, 464 String ref) { 465 if (this.protocol == null) { 466 this.protocol = protocol; 467 } 468 this.host = host; 469 this.file = file; 470 this.port = port; 471 this.ref = ref; 472 hashCode = 0; 473 fixURL(true); 474 } 475 476 /** 477 * Compares this URL instance with the given argument {@code o} and 478 * determines if both are equal. Two URL instances are equal if all single 479 * parts are identical in their meaning. Compares the argument to the 480 * receiver, and returns true if they represent the same URL. Two URLs are 481 * equal if they have the same file, host, port, protocol, and reference 482 * components. 483 * 484 * @param o 485 * the URL this instance has to be compared with. 486 * @return {@code true} if both instances represents the same URL, {@code 487 * false} otherwise. 488 * @see #hashCode() 489 */ 490 @Override 491 public boolean equals(Object o) { 492 if (o == null) { 493 return false; 494 } 495 if (this == o) { 496 return true; 497 } 498 if (this.getClass() != o.getClass()) { 499 return false; 500 } 501 return strmHandler.equals(this, (URL) o); 502 } 503 504 /** 505 * Returns whether this URL refers to the same resource as the given 506 * argument {@code otherURL}. All URL components except the reference field 507 * are compared. 508 * 509 * @param otherURL 510 * the URL to compare against. 511 * @return {@code true} if both instances refer to the same resource, 512 * {@code false} otherwise. 513 */ 514 public boolean sameFile(URL otherURL) { 515 return strmHandler.sameFile(this, otherURL); 516 } 517 518 /** 519 * Gets the hashcode value of this URL instance. 520 * 521 * @return the appropriate hashcode value. 522 */ 523 @Override 524 public int hashCode() { 525 if (hashCode == 0) { 526 hashCode = strmHandler.hashCode(this); 527 } 528 return hashCode; 529 } 530 531 /** 532 * Sets the receiver's stream handler to one which is appropriate for its 533 * protocol. Throws a MalformedURLException if no reasonable handler is 534 * available. 535 * <p> 536 * Note that this will overwrite any existing stream handler with the new 537 * one. Senders must check if the strmHandler is null before calling the 538 * method if they do not want this behavior (a speed optimization). 539 */ 540 void setupStreamHandler() { 541 // Check for a cached (previously looked up) handler for 542 // the requested protocol. 543 strmHandler = streamHandlers.get(protocol); 544 if (strmHandler != null) { 545 return; 546 } 547 548 // If there is a stream handler factory, then attempt to 549 // use it to create the handler. 550 if (streamHandlerFactory != null) { 551 strmHandler = streamHandlerFactory.createURLStreamHandler(protocol); 552 if (strmHandler != null) { 553 streamHandlers.put(protocol, strmHandler); 554 return; 555 } 556 } 557 558 // Check if there is a list of packages which can provide handlers. 559 // If so, then walk this list looking for an applicable one. 560 String packageList = AccessController 561 .doPrivileged(new PriviAction<String>( 562 "java.protocol.handler.pkgs")); 563 if (packageList != null) { 564 StringTokenizer st = new StringTokenizer(packageList, "|"); 565 while (st.hasMoreTokens()) { 566 String className = st.nextToken() + "." + protocol + ".Handler"; 567 568 try { 569 strmHandler = (URLStreamHandler) Class.forName(className, 570 true, ClassLoader.getSystemClassLoader()) 571 .newInstance(); 572 if (strmHandler != null) { 573 streamHandlers.put(protocol, strmHandler); 574 } 575 return; 576 } catch (IllegalAccessException e) { 577 } catch (InstantiationException e) { 578 } catch (ClassNotFoundException e) { 579 } 580 } 581 } 582 583 // No one else has provided a handler, so try our internal one. 584 585 String className = "org.apache.harmony.luni.internal.net.www.protocol." + protocol 586 + ".Handler"; 587 try { 588 strmHandler = (URLStreamHandler) Class.forName(className) 589 .newInstance(); 590 } catch (IllegalAccessException e) { 591 } catch (InstantiationException e) { 592 } catch (ClassNotFoundException e) { 593 } 594 if (strmHandler != null) { 595 streamHandlers.put(protocol, strmHandler); 596 } 597 598 } 599 600 /** 601 * Gets the content of the resource which is referred by this URL. By 602 * default one of the following object types will be returned: 603 * <p> 604 * <li>Image for pictures</li> 605 * <li>AudioClip for audio sequences</li> 606 * <li>{@link InputStream} for all other data</li> 607 * 608 * @return the content of the referred resource. 609 * @throws IOException 610 * if an error occurs obtaining the content. 611 */ 612 public final Object getContent() throws IOException { 613 return openConnection().getContent(); 614 } 615 616 /** 617 * Gets the content of the resource which is referred by this URL. The 618 * argument {@code types} is an array of allowed or expected object types. 619 * {@code null} will be returned if the obtained object type does not match 620 * with one from this list. Otherwise the first type that matches will be 621 * used. 622 * 623 * @param types 624 * the list of allowed or expected object types. 625 * @return the object representing the resource referred by this URL, 626 * {@code null} if the content does not match to a specified content 627 * type. 628 * @throws IOException 629 * if an error occurs obtaining the content. 630 */ 631 // Param not generic in spec 632 @SuppressWarnings("unchecked") 633 public final Object getContent(Class[] types) throws IOException { 634 return openConnection().getContent(types); 635 } 636 637 /** 638 * Opens an InputStream to read the resource referred by this URL. 639 * 640 * @return the stream which allows to read the resource. 641 * @throws IOException 642 * if an error occurs while opening the InputStream. 643 */ 644 public final InputStream openStream() throws java.io.IOException { 645 return openConnection().getInputStream(); 646 } 647 648 /** 649 * Opens a connection to the remote resource specified by this URL. This 650 * connection allows bidirectional data transfer. 651 * 652 * @return the connection to this URL. 653 * @throws IOException 654 * if an error occurs while opening the connection. 655 */ 656 public URLConnection openConnection() throws IOException { 657 return strmHandler.openConnection(this); 658 } 659 660 /** 661 * Converts this URL instance into an equivalent URI object. 662 * 663 * @return the URI instance that represents this URL. 664 * @throws URISyntaxException 665 * if this URL cannot be converted into a URI. 666 */ 667 public URI toURI() throws URISyntaxException { 668 return new URI(toExternalForm()); 669 } 670 671 /** 672 * Opens a connection to the remote resource specified by this URL. The 673 * connection will be established through the given proxy and allows 674 * bidirectional data transfer. 675 * 676 * @param proxy 677 * the proxy through which the connection will be established. 678 * @return the appropriate URLconnection instance representing the 679 * connection to this URL. 680 * @throws IOException 681 * if an I/O error occurs while opening the connection. 682 * @throws SecurityException 683 * if a security manager is installed and it denies to connect 684 * to the proxy. 685 * @throws IllegalArgumentException 686 * if the argument proxy is {@code null} or is an invalid type. 687 * @throws UnsupportedOperationException 688 * if the protocol handler does not support opening connections 689 * through proxies. 690 */ 691 public URLConnection openConnection(Proxy proxy) throws IOException { 692 if (proxy == null) { 693 throw new IllegalArgumentException("proxy == null"); 694 } 695 696 SecurityManager sm = System.getSecurityManager(); 697 if (sm != null && proxy.type() != Proxy.Type.DIRECT) { 698 InetSocketAddress pAddress = (InetSocketAddress) proxy.address(); 699 String pHostName = pAddress.isUnresolved() ? pAddress.getHostName() 700 : pAddress.getAddress().getHostAddress(); 701 sm.checkConnect(pHostName, pAddress.getPort()); 702 } 703 704 return strmHandler.openConnection(this, proxy); 705 } 706 707 /** 708 * Returns a string containing a concise, human-readable representation of 709 * this URL. The returned string is the same as the result of the method 710 * {@code toExternalForm()}. 711 * 712 * @return the string representation of this URL. 713 */ 714 @Override 715 public String toString() { 716 return toExternalForm(); 717 } 718 719 /** 720 * Returns a string containing a concise, human-readable representation of 721 * this URL. 722 * 723 * @return the string representation of this URL. 724 */ 725 public String toExternalForm() { 726 if (strmHandler == null) { 727 return "unknown protocol(" + protocol + ")://" + host + file; 728 } 729 return strmHandler.toExternalForm(this); 730 } 731 732 /** 733 * This method is called to restore the state of a URL object that has been 734 * serialized. The stream handler is determined from the URL's protocol. 735 * 736 * @param stream 737 * the stream to read from. 738 * 739 * @throws IOException 740 * if an IO Exception occurs while reading the stream or the 741 * handler can not be found. 742 */ 743 private void readObject(java.io.ObjectInputStream stream) 744 throws java.io.IOException { 745 try { 746 stream.defaultReadObject(); 747 if (host != null && authority == null) { 748 fixURL(true); 749 } else if (authority != null) { 750 int index; 751 if ((index = authority.lastIndexOf('@')) > -1) { 752 userInfo = authority.substring(0, index); 753 } 754 if (file != null && (index = file.indexOf('?')) > -1) { 755 query = file.substring(index + 1); 756 path = file.substring(0, index); 757 } else { 758 path = file; 759 } 760 } 761 setupStreamHandler(); 762 if (strmHandler == null) { 763 throw new IOException("Unknown protocol: " + protocol); 764 } 765 } catch (ClassNotFoundException e) { 766 throw new IOException(e.toString()); 767 } 768 } 769 770 /** 771 * This method is called to write any non-transient, non-static variables 772 * into the output stream. 773 * <p> 774 * Note that, we really only need the readObject method but the spec that 775 * says readObject will be ignored if no writeObject is present. 776 * 777 * @param s 778 * the stream to write on. 779 * @throws IOException 780 * if an IO Exception occurs during the write. 781 */ 782 private void writeObject(ObjectOutputStream s) throws IOException { 783 s.defaultWriteObject(); 784 } 785 786 /** 787 * Gets the value of the file part of this URL. 788 * 789 * @return the file name this URL refers to or an empty string if the file 790 * part is not set. 791 */ 792 public String getFile() { 793 return file; 794 } 795 796 /** 797 * Gets the value of the host part of this URL. 798 * 799 * @return the host name or IP address of this URL. 800 */ 801 public String getHost() { 802 return host; 803 } 804 805 /** 806 * Gets the port number of this URL or {@code -1} if the port is not set. 807 * 808 * @return the port number of this URL. 809 */ 810 public int getPort() { 811 return port; 812 } 813 814 /** @hide */ 815 public int getEffectivePort() { 816 return URI.getEffectivePort(protocol, port); 817 } 818 819 /** 820 * Gets the protocol of this URL. 821 * 822 * @return the protocol type of this URL. 823 */ 824 public String getProtocol() { 825 return protocol; 826 } 827 828 /** 829 * Gets the value of the reference part of this URL. 830 * 831 * @return the reference part of this URL. 832 */ 833 public String getRef() { 834 return ref; 835 } 836 837 /** 838 * Gets the value of the query part of this URL. 839 * 840 * @return the query part of this URL. 841 */ 842 public String getQuery() { 843 return query; 844 } 845 846 /** 847 * Gets the value of the path part of this URL. 848 * 849 * @return the path part of this URL. 850 */ 851 public String getPath() { 852 return path; 853 } 854 855 /** 856 * Gets the value of the user-info part of this URL. 857 * 858 * @return the user-info part of this URL. 859 */ 860 public String getUserInfo() { 861 return userInfo; 862 } 863 864 /** 865 * Gets the value of the authority part of this URL. 866 * 867 * @return the authority part of this URL. 868 */ 869 public String getAuthority() { 870 return authority; 871 } 872 873 /** 874 * Sets the properties of this URL using the provided arguments. Only a 875 * {@code URLStreamHandler} can use this method to set fields of the 876 * existing URL instance. A URL is generally constant. 877 * 878 * @param protocol 879 * the protocol to be set. 880 * @param host 881 * the host name to be set. 882 * @param port 883 * the port number to be set. 884 * @param authority 885 * the authority to be set. 886 * @param userInfo 887 * the user-info to be set. 888 * @param path 889 * the path to be set. 890 * @param query 891 * the query to be set. 892 * @param ref 893 * the reference to be set. 894 */ 895 protected void set(String protocol, String host, int port, 896 String authority, String userInfo, String path, String query, 897 String ref) { 898 String filePart = path; 899 if (query != null && !query.isEmpty()) { 900 if (filePart != null) { 901 filePart = filePart + "?" + query; 902 } else { 903 filePart = "?" + query; 904 } 905 } 906 set(protocol, host, port, filePart, ref); 907 this.authority = authority; 908 this.userInfo = userInfo; 909 this.path = path; 910 this.query = query; 911 } 912 913 /** 914 * Gets the default port number of the protocol used by this URL. If no 915 * default port is defined by the protocol or the {@code URLStreamHandler}, 916 * {@code -1} will be returned. 917 * 918 * @return the default port number according to the protocol of this URL. 919 * @see URLStreamHandler#getDefaultPort 920 */ 921 public int getDefaultPort() { 922 return strmHandler.getDefaultPort(); 923 } 924 } 925