Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8295949

Deprecate URL public constructors

    XMLWordPrintable

Details

    • CSR
    • Resolution: Approved
    • P4
    • 20
    • core-libs
    • None
    • source, behavioral
    • low
    • Old code written before this change may exhibit new deprecation warnings when recompiled if URL constructors are used directly.
    • Java API
    • SE

    Description

      Summary

      Deprecate URL constructors. Developers are encouraged to use java.net.URI to parse or construct any URL.

      Problem

      The java.net.URL class does not itself encode or decode any URL components according to the escaping mechanism defined in RFC2396. It is the responsibility of the caller to encode any fields, which need to be escaped prior to calling URL, and also to decode any escaped fields, that are returned from URL. This has lead to many usability issues, sometimes even to vulnerabilities when the calling code failed to take this into consideration.

      Indeed, if used improperly, there is no guarantee that URL::toString or URL::toExternalForm will lead to a URL string that can be parsed back into the same URL. This can lead to constructing misleading URLs. Another issue is with equals() and hashCode() which may have to perform a lookup, and do not take encoding/escaping into account.

      In Java SE 1.4 a new class, java.net.URI, has been added to mitigate some of the shortcoming of java.net.URL. Conversion methods to create a URL from a URI were also added. However, it was left up to the developers to use java.net.URI, or not.

      Solution

      This CSR proposes to deprecate all public constructors of java.net.URL, in order to provide a stronger warning that these constructors can be misused. To construct a URL, using URI::toURL should be preferred.

      In order to provide an alternative to the constructors that take a stream handler as parameter, a new factory method URL::of(java.net.URI, java.net.URLStreamHandler) is provided.

      Specification

      From java.net.URL, starting at the class-level API documentation:

          --- a/src/java.base/share/classes/java/net/URL.java
          +++ b/src/java.base/share/classes/java/net/URL.java
      @@ -127,10 +127,30 @@
         * <p>
         * The relative URL need not specify all the components of a URL. If
         * the protocol, host name, or port number is missing, the value is
         * inherited from the fully specified URL. The file component must be
         * specified. The optional fragment is not inherited.
      +  *
      +  * <h2><a id="constructor-deprecation"></a>Constructing instances of {@code URL}</h2>
      +  *
      +  * The {@code java.net.URL} constructors are deprecated.
      +  * Developers are encouraged to use {@link URI java.net.URI} to parse
      +  * or construct a {@code URL}. In cases where an instance of {@code
      +  * java.net.URL} is needed to open a connection, {@link URI} can be used
      +  * to construct or parse the URL string, possibly calling {@link
      +  * URI#parseServerAuthority()} to validate that the authority component
      +  * can be parsed as a server-based authority, and then calling
      +  * {@link URI#toURL()} to create the {@code URL} instance.
      +  * <p>
      +  * The URL constructors are specified to throw
      +  * {@link MalformedURLException} but the actual parsing/validation
      +  * that is performed is implementation dependent. Some parsing/validation
      +  * may be delayed until later, when the underlying {@linkplain
      +  * URLStreamHandler stream handler's implementation} is called.
      +  * Being able to construct an instance of {@code URL} doesn't
      +  * provide any guarantee about its conformance to the URL
      +  * syntax specification.
         * <p>
         * The URL class does not itself encode or decode any URL components
         * according to the escaping mechanism defined in RFC2396. It is the
         * responsibility of the caller to encode any fields, which need to be
         * escaped prior to calling URL, and also to decode any escaped fields,
      
      @@ -150,10 +170,11 @@
         * used, but only for HTML form encoding, which is not the same
         * as the encoding scheme defined in RFC2396.
         *
         * @apiNote
         *
      +  * <a id="integrity"></a>
         * Applications working with file paths and file URIs should take great
         * care to use the appropriate methods to convert between the two.
         * The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
         * constructor can be used to create {@link Path} or {@link File}
         * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
      
      @@ -162,10 +183,15 @@
         * Applications should never try to {@linkplain #URL(String, String, String)
         * construct} or {@linkplain #URL(String) parse} a {@code URL}
         * from the direct string representation of a {@code File} or {@code Path}
         * instance.
         * <p>
      +  * Before constructing a {@code URL} from a {@code URI}, and depending
      +  * on the protocol involved, applications should consider validating
      +  * whether the URI authority {@linkplain URI#parseServerAuthority()
      +  * can be parsed as server-based}.
      +  * <p>
         * Some components of a URL or URI, such as <i>userinfo</i>, may
         * be abused to construct misleading URLs or URIs. Applications
         * that deal with URLs or URIs should take into account
         * the recommendations advised in <a
         * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
      
      @@ -371,11 +397,15 @@
             * @see        java.net.URL#setURLStreamHandlerFactory(
             *                  java.net.URLStreamHandlerFactory)
             * @see        java.net.URLStreamHandler
             * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
             *                  java.lang.String)
      +      * @deprecated Use {@link URI#toURL()} to construct an instance of URL. See the note on
      +      * <a href="#constructor-deprecation">constructor deprecation</a> for more
      +      * details.
             */
      +     @Deprecated(since = "20")
            public URL(String protocol, String host, int port, String file)
                throws MalformedURLException
      
      @@ -397,11 +427,15 @@
             * @throws     MalformedURLException  if an unknown protocol is specified,
             *                        or if the underlying stream handler implementation
             *                        rejects, or is known to reject, the {@code URL}
             * @see        java.net.URL#URL(java.lang.String, java.lang.String,
             *                  int, java.lang.String)
      +      * @deprecated Use {@link URI#toURL()} to construct an instance of URL. See the note on
      +      * <a href="#constructor-deprecation">constructor deprecation</a> for more
      +      * details.
             */
      +     @Deprecated(since = "20")
            public URL(String protocol, String host, String file)
                    throws MalformedURLException {      
      
      @@ -444,11 +478,17 @@
             * @see        java.net.URLStreamHandler
             * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
             *                  java.lang.String)
             * @see        SecurityManager#checkPermission
             * @see        java.net.NetPermission
      +      * @deprecated
      +      * Use {@link #of(URI, URLStreamHandler)} to construct an instance of URL
      +      * associated with a custom protocol handler.
      +      * See the note on <a href="#constructor-deprecation">constructor deprecation</a>
      +      * for more details.
             */
      +     @Deprecated(since = "20")
            public URL(String protocol, String host, int port, String file,
                       URLStreamHandler handler) throws MalformedURLException {
      
      @@ -531,11 +571,15 @@
             *               of the associated protocol, or the
             *               underlying stream handler's {@linkplain
             *               URLStreamHandler#parseURL parseURL method} throws
             *               {@code IllegalArgumentException}
             * @see        java.net.URL#URL(java.net.URL, java.lang.String)
      +      * @deprecated Use {@link URI#toURL()} to construct an instance of URL. See the note on
      +      * <a href="#constructor-deprecation">constructor deprecation</a> for more
      +      * details.
             */
      +     @Deprecated(since = "20")
            public URL(String spec) throws MalformedURLException {
      
            /**
      
      @@ -591,11 +635,15 @@
             * @see        java.net.URL#URL(java.lang.String, java.lang.String,
             *                  int, java.lang.String)
             * @see        java.net.URLStreamHandler
             * @see        java.net.URLStreamHandler#parseURL(java.net.URL,
             *                  java.lang.String, int, int)
      +      * @deprecated Use {@link URI#toURL()} to construct an instance of URL. See the note on
      +      * <a href="#constructor-deprecation">constructor deprecation</a> for more
      +      * details.
             */
      +     @Deprecated(since = "20")
            public URL(URL context, String spec) throws MalformedURLException {
      
            /**
      
      @@ -624,11 +672,17 @@
             * @see        java.net.URL#URL(java.lang.String, java.lang.String,
             *                  int, java.lang.String)
             * @see        java.net.URLStreamHandler
             * @see        java.net.URLStreamHandler#parseURL(java.net.URL,
             *                  java.lang.String, int, int)
      +      * @deprecated
      +      * Use {@link #of(URI, URLStreamHandler)} to construct an instance of URL
      +      * associated with a custom protocol handler.
      +      * See the note on <a href="#constructor-deprecation">constructor deprecation</a>
      +      * for more details.
             */
      +     @Deprecated(since = "20")
            public URL(URL context, String spec, URLStreamHandler handler)
                throws MalformedURLException
      
      @@ -746,27 +800,74 @@      
      +     /**
      +      * Creates a URL from a URI, as if by invoking {@code uri.toURL()}, but
      +      * associating it with the given {@code URLStreamHandler}, if allowed.
      +      *
      +      * @apiNote
      +      * Applications should consider performing additional integrity
      +      * checks before constructing a {@code URL} and opening a connection.
      +      * See the <a href=#integrity>API note</a> in the class level API
      +      * documentation.
      +      *
      +      * @implSpec The implementation of this method includes calling the {@link
      +      * URLStreamHandler#parseURL(URL, String, int, int) parseURL} method on the
      +      * selected handler.
      +      *
      +      * @param uri the {@code URI} from which the returned {@code URL} should
      +      *           be built
      +      * @param handler a custom protocol stream handler for
      +      *                      the returned {@code URL}. Can be {@code null},
      +      *                      in which case the default stream handler for
      +      *                      the protocol if any, will be used.
      +      *
      +      * @return a new {@code URL} instance created from the given {@code URI}
      +      *   and associated with the given {@code URLStreamHandler}, if any
      +      *
      +      * @throws NullPointerException if {@code uri} is {@code null}
      +      *
      +      * @throws IllegalArgumentException if no protocol is specified
      +      *         (the {@linkplain URI#getScheme() uri scheme} is {@code null}), or
      +      *         if the {@code URLStreamHandler} is not {@code null} and can not be
      +      *         set for the given protocol
      +      *
      +      * @throws  MalformedURLException if an unknown protocol is found,
      +      *          or the given URI fails to comply with the specific
      +      *          syntax of the associated protocol, or the
      +      *          underlying stream handler's {@linkplain
      +      *          URLStreamHandler#parseURL(URL, String, int, int)
      +      *          parseURL method} throws {@code IllegalArgumentException}
      +      *
      +      * @throws SecurityException
      +      *        if a security manager exists and its
      +      *        {@code checkPermission} method doesn't allow
      +      *        specifying a stream handler
      +      *
      +      * @see java.net.URI#toURL()
      +      *
      +      * @since 20
      +      */
      +     public static URL of(URI uri, URLStreamHandler handler)
      +         throws MalformedURLException {

      Attachments

        Issue Links

          Activity

            People

              dfuchs Daniel Fuchs
              dfuchs Daniel Fuchs
              Alan Bateman, Jaikiran Pai, Michael McMahon
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: