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

URI compareTo inconsistent with equals for mixed-case escape sequences

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 15
    • core-libs
    • None
    • behavioral
    • minimal
    • Update the specification and behavior of `URI::compareTo`, in a way that should not surprise ( in fact, would be expected ).
    • Java API
    • SE

      Summary

      Update the java.net.URI::compareTo specification and behavior to adhere to the strong recommendation of the Comparable interface, that (x.compareTo(y)==0) == (x.equals(y)), for URIs that contain hexadecimal digits of escaped octets that differ only in case.

      Problem

      The URI::compareTo method does not strictly follow the strong recommendation of Comparable::compareTo. Specifically, URI::compareTo does not consider two URIs to be equal when they differ only in the case of hexadecimal digits of escaped octets. While URI::equals does consider such URIs to be equal.

      For example:

      jshell> var uri1  = URI.create("http://example.com/%5bsegment%5d")
      uri1 ==> http://example.com/%5bsegment%5d
      
      jshell> var uri2  = URI.create("http://example.com/%5Bsegment%5D")
      uri2 ==> http://example.com/%5Bsegment%5D
      
      jshell> uri1.equals(uri2)
      $4 ==> true
      
      jshell> uri1.compareTo(uri2)
      $5 ==> 32

      The expectation is that uri1.compareTo(uri2) should yield a result of 0, indicating that the URIs compare equal, but it does not. This expectation is derived from the fact that URI::compareTo is specified to satisfy the general contract of Comparable.compareTo.

      Solution

      Update the specification and behavior of URI::compareTo so that hexadecimal digits of escaped octets are compared without regard to case. Similar to, and consistent with, URI::equals.

      With this change, the above example of uri1.compareTo(uri2) will yield a result of 0, indicating that the URIs compare equal.

      Specification

      src/java.base/share/classes/java/net/URI.java

         /**
          * Compares this URI to another object, which must be a URI.
          *
          * <p> When comparing corresponding components of two URIs, if one
          * component is undefined but the other is defined then the first is
          * considered to be less than the second.  Unless otherwise noted, string
          * components are ordered according to their natural, case-sensitive
          * ordering as defined by the {@link java.lang.String#compareTo(Object)
          * String.compareTo} method.  String components that are subject to
          * encoding are compared by comparing their raw forms rather than their
      -   * encoded forms.
      +   * encoded forms and the hexadecimal digits of escaped octets are compared
      +   * without regard to case.
          *
          * <p> The ordering of URIs is defined as follows: </p>
          *
          * ...
          */
         public int compareTo(URI that) { ... }

            kravikumar Kiran Sidhartha Ravikumar (Inactive)
            rmandalasunw Ranjith Mandala (Inactive)
            Chris Hegarty, Daniel Fuchs
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: