protected void parseURL(final URL purl, final String pspec, final int pstart, final int plimit) {
    // These fields may receive context content if this was relative URL
    final String protocol = purl.getProtocol();
    String authority = purl.getAuthority();
    String userInfo = purl.getUserInfo();
    String host = purl.getHost();
    int port = purl.getPort();
    String path = purl.getPath();
    String query = purl.getQuery();
    String spec = pspec;
    int start = pstart;
    int limit = plimit;

    // This field has already been parsed
    final String ref = purl.getRef();

    boolean isRelPath = false;
    boolean queryOnly = false;

    // FIX: should not assume query if opaque
    // Strip off the query part
    if (start < limit) {
      final int queryStart = spec.indexOf('?');
      queryOnly = queryStart == start;
      if (queryStart != -1 && queryStart < limit) {
        query = spec.substring(queryStart + 1, limit);
        if (limit > queryStart) {
          limit = queryStart;
        }
        spec = spec.substring(0, queryStart);
      }
    }

    int indexI = 0;
    // Parse the authority part if any
    final boolean isUncName =
        start <= limit - 4 && spec.charAt(start) == '/' && spec.charAt(start + 1) == '/'
            && spec.charAt(start + 2) == '/' && spec.charAt(start + 3) == '/';
    if (!isUncName && start <= limit - 2 && spec.charAt(start) == '/'
        && spec.charAt(start + 1) == '/') {
      start += 2;
      indexI = spec.indexOf('/', start);
      if (indexI < 0) {
        indexI = spec.indexOf('?', start);
        if (indexI < 0) {
          indexI = limit;
        }
      }

      host = authority = spec.substring(start, indexI);

      int ind = authority.indexOf('@');
      if (ind == -1) {
        userInfo = null;
      } else {
        userInfo = authority.substring(0, ind);
        host = authority.substring(ind + 1);
      }
      if (host == null) {
        host = "";
      } else {
        // If the host is surrounded by [ and ] then its an IPv6
        // literal address as specified in RFC2732
        if (host.length() > 0 && host.charAt(0) == '[') {
          if ((ind = host.indexOf(']')) > 2) { // NOPMD

            final String nhost = host;
            host = nhost.substring(0, ind + 1);
            if (!this.isIPv6LiteralAddress(host.substring(1, ind))) {
              throw new IllegalArgumentException("Invalid host: " + host);
            }

            port = -1;
            if (nhost.length() > ind + 1) {
              if (nhost.charAt(ind + 1) == ':') {
                ++ind;
                // port can be null according to RFC2396
                if (nhost.length() > ind + 1) {
                  port = Integer.parseInt(nhost.substring(ind + 1));
                }
              } else {
                throw new IllegalArgumentException("Invalid authority field: " + authority);
              }
            }
          } else {
            throw new IllegalArgumentException("Invalid authority field: " + authority);
          }
        } else {
          ind = host.indexOf(':');
          port = -1;
          if (ind >= 0) {
            // port can be null according to RFC2396
            if (host.length() > ind + 1) {
              port = Integer.parseInt(host.substring(ind + 1));
            }
            host = host.substring(0, ind);
          }
        }
      }
      if (port < -1) {
        throw new IllegalArgumentException("Invalid port number :" + port);
      }
      start = indexI;
      // If the authority is defined then the path is defined by the
      // spec only; See RFC 2396 Section 5.2.4.
      if (authority != null && authority.length() > 0) {
        path = "";
      }
    }

    if (host == null) {
      host = "";
    }

    // Parse the file path if any
    if (start < limit) {
      if (spec.charAt(start) == '/') {
        path = spec.substring(start, limit);
      } else if (path != null && path.length() > 0) {
        isRelPath = true;
        final int ind = path.lastIndexOf('/');
        String seperator = "";
        if (ind == -1 && authority != null) {
          seperator = "/";
        }
        path = path.substring(0, ind + 1) + seperator + spec.substring(start, limit);

      } else {
        final String seperator = authority == null ? "" : "/";
        path = seperator + spec.substring(start, limit);
      }
    } else if (queryOnly && path != null) {
      int ind = path.lastIndexOf('/');
      if (ind < 0) {
        ind = 0;
      }
      path = path.substring(0, ind) + "/";
    }
    if (path == null) {
      path = "";
    }

    if (isRelPath) {
      // Remove embedded /./
      while ((indexI = path.indexOf("/./")) >= 0) { // NOPMD
        path = path.substring(0, indexI) + path.substring(indexI + 2);
      }
      // Remove embedded /../ if possible
      indexI = 0;
      while ((indexI = path.indexOf("/../", indexI)) >= 0) { // NOPMD
        /*
         * A "/../" will cancel the previous segment and itself, unless that segment is a "/../"
         * itself i.e. "/a/b/../c" becomes "/a/c" but "/../../a" should stay unchanged
         */
        limit = path.lastIndexOf('/', indexI - 1);
        if (indexI > 0 && limit >= 0 && path.indexOf("/../", limit) != 0) {
          path = path.substring(0, limit) + path.substring(indexI + 3);
          indexI = 0;
        } else {
          indexI = indexI + 3;
        }
      }
      // Remove trailing .. if possible
      while (path.endsWith("/..")) {
        indexI = path.indexOf("/..");
        limit = path.lastIndexOf('/', indexI - 1);
        if (limit >= 0) {
          path = path.substring(0, limit + 1);
        } else {
          break;
        }
      }
      // Remove starting .
      if (path.startsWith("./") && path.length() > 2) {
        path = path.substring(2);
      }

      // Remove trailing .
      if (path.endsWith("/.")) {
        path = path.substring(0, path.length() - 1);
      }
    }

    purl.set(protocol, host, port, authority, userInfo, path, query, ref);
  }
protected void parseURL ( final URL purl , final String pspec , final int pstart , final int plimit ) { final String protocol = purl . getProtocol ( ) ; String authority = purl . getAuthority ( ) ; String userInfo = purl . getUserInfo ( ) ; String host = purl . getHost ( ) ; int port = purl . getPort ( ) ; String path = purl . getPath ( ) ; String query = purl . getQuery ( ) ; String spec = pspec ; int start = pstart ; int limit = plimit ; final String ref = purl . getRef ( ) ; boolean isRelPath = false ; boolean queryOnly = false ; if ( start < limit ) { final int queryStart = spec . indexOf ( '?' ) ; queryOnly = queryStart == start ; if ( queryStart != - 1 && queryStart < limit ) { query = spec . substring ( queryStart + 1 , limit ) ; if ( limit > queryStart ) { limit = queryStart ; } spec = spec . substring ( 0 , queryStart ) ; } } int indexI = 0 ; final boolean isUncName = start <= limit - 4 && spec . charAt ( start ) == '/' && spec . charAt ( start + 1 ) == '/' && spec . charAt ( start + 2 ) == '/' && spec . charAt ( start + 3 ) == '/' ; if ( ! isUncName && start <= limit - 2 && spec . charAt ( start ) == '/' && spec . charAt ( start + 1 ) == '/' ) { start += 2 ; indexI = spec . indexOf ( '/' , start ) ; if ( indexI < 0 ) { indexI = spec . indexOf ( '?' , start ) ; if ( indexI < 0 ) { indexI = limit ; } } host = authority = spec . substring ( start , indexI ) ; int ind = authority . indexOf ( '@' ) ; if ( ind == - 1 ) { userInfo = null ; } else { userInfo = authority . substring ( 0 , ind ) ; host = authority . substring ( ind + 1 ) ; } if ( host == null ) { host = "" ; } else { if ( host . length ( ) > 0 && host . charAt ( 0 ) == '[' ) { if ( ( ind = host . indexOf ( ']' ) ) > 2 ) { final String nhost = host ; host = nhost . substring ( 0 , ind + 1 ) ; if ( ! this . isIPv6LiteralAddress ( host . substring ( 1 , ind ) ) ) { throw new IllegalArgumentException ( "Invalid host: " + host ) ; } port = - 1 ; if ( nhost . length ( ) > ind + 1 ) { if ( nhost . charAt ( ind + 1 ) == ':' ) { ++ ind ; if ( nhost . length ( ) > ind + 1 ) { port = Integer . parseInt ( nhost . substring ( ind + 1 ) ) ; } } else { throw new IllegalArgumentException ( "Invalid authority field: " + authority ) ; } } } else { throw new IllegalArgumentException ( "Invalid authority field: " + authority ) ; } } else { ind = host . indexOf ( ':' ) ; port = - 1 ; if ( ind >= 0 ) { if ( host . length ( ) > ind + 1 ) { port = Integer . parseInt ( host . substring ( ind + 1 ) ) ; } host = host . substring ( 0 , ind ) ; } } } if ( port < - 1 ) { throw new IllegalArgumentException ( "Invalid port number :" + port ) ; } start = indexI ; if ( authority != null && authority . length ( ) > 0 ) { path = "" ; } } if ( host == null ) { host = "" ; } if ( start < limit ) { if ( spec . charAt ( start ) == '/' ) { path = spec . substring ( start , limit ) ; } else if ( path != null && path . length ( ) > 0 ) { isRelPath = true ; final int ind = path . lastIndexOf ( '/' ) ; String seperator = "" ; if ( ind == - 1 && authority != null ) { seperator = "/" ; } path = path . substring ( 0 , ind + 1 ) + seperator + spec . substring ( start , limit ) ; } else { final String seperator = authority == null ? "" : "/" ; path = seperator + spec . substring ( start , limit ) ; } } else if ( queryOnly && path != null ) { int ind = path . lastIndexOf ( '/' ) ; if ( ind < 0 ) { ind = 0 ; } path = path . substring ( 0 , ind ) + "/" ; } if ( path == null ) { path = "" ; } if ( isRelPath ) { while ( ( indexI = path . indexOf ( "/./" ) ) >= 0 ) { path = path . substring ( 0 , indexI ) + path . substring ( indexI + 2 ) ; } indexI = 0 ; while ( ( indexI = path . indexOf ( "/../" , indexI ) ) >= 0 ) { limit = path . lastIndexOf ( '/' , indexI - 1 ) ; if ( indexI > 0 && limit >= 0 && path . indexOf ( "/../" , limit ) != 0 ) { path = path . substring ( 0 , limit ) + path . substring ( indexI + 3 ) ; indexI = 0 ; } else { indexI = indexI + 3 ; } } while ( path . endsWith ( "/.." ) ) { indexI = path . indexOf ( "/.." ) ; limit = path . lastIndexOf ( '/' , indexI - 1 ) ; if ( limit >= 0 ) { path = path . substring ( 0 , limit + 1 ) ; } else { break ; } } if ( path . startsWith ( "./" ) && path . length ( ) > 2 ) { path = path . substring ( 2 ) ; } if ( path . endsWith ( "/." ) ) { path = path . substring ( 0 , path . length ( ) - 1 ) ; } } purl . set ( protocol , host , port , authority , userInfo , path , query , ref ) ; }
Parses the string representation of a <code>URL</code> into a <code>URL</code> object.
<p>
If there is any inherited context, then it has already been copied into the <code>URL</code>
argument.
</p>
<p>
The <code>parseURL</code> method of <code>URLStreamHandler</code> parses the string
representation as if it were an <code>http</code> specification. Most URL protocol families
have a similar parsing. A stream protocol handler for a protocol that has a different syntax
must override this routine.
</p>

@param purl the <code>URL</code> to receive the result of parsing the spec.
@param pspec the <code>String</code> representing the URL that must be parsed.
@param pstart the character index at which to begin parsing. This is just past the '
<code>:</code>' (if there is one) that specifies the determination of the protocol name.
@param plimit the character position to stop parsing at. This is the end of the string or the
position of the "<code>#</code>" character, if present. All information after the sharp
sign indicates an anchor.