📄 uri.java
字号:
*/ private static String quote(String str, String legalCharacters) { StringBuffer sb = new StringBuffer(str.length()); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (legalCharacters.indexOf(c) == -1) { if (c <= 127) { sb.append('%'); sb.append(HEX.charAt(c / 16)); sb.append(HEX.charAt(c % 16)); } } else sb.append(c); } return sb.toString(); } /** * Quote characters illegal in URI hosts in given string. * * Replace illegal characters by encoding their UTF-8 * representation as "%" + hex code for each resulting * UTF-8 character. * * @param str The string to quote * * @return The quoted string. */ private static String quoteHost(String str) { return quote(str, RFC3986_HOST); } /** * Quote characters illegal in URI paths in given string. * * Replace illegal characters by encoding their UTF-8 * representation as "%" + hex code for each resulting * UTF-8 character. * * @param str The string to quote * * @return The quoted string. */ private static String quotePath(String str) { // Technically, we should be using RFC2396_PATH, but // it contains no additional characters. return quote(str, RFC3986_PATH_SEGMENTS); } /** * Quote characters illegal in URI user infos in given string. * * Replace illegal characters by encoding their UTF-8 * representation as "%" + hex code for each resulting * UTF-8 character. * * @param str The string to quote * * @return The quoted string. */ private static String quoteUserInfo(String str) { return quote(str, RFC3986_USERINFO); } /** * Creates an URI from the given string * * @param str The string to create the URI from * * @exception URISyntaxException If the given string violates RFC 2396 * @exception NullPointerException If str is null */ public URI(String str) throws URISyntaxException { this.string = str; parseURI(str); } /** * Create an URI from the given components * * @param scheme The scheme name * @param userInfo The username and authorization info * @param host The hostname * @param port The port number * @param path The path * @param query The query * @param fragment The fragment * * @exception URISyntaxException If the given string violates RFC 2396 */ public URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment) throws URISyntaxException { this((scheme == null ? "" : scheme + ":") + (userInfo == null && host == null && port == -1 ? "" : "//") + (userInfo == null ? "" : quoteUserInfo(userInfo) + "@") + (host == null ? "" : quoteHost(host)) + (port == -1 ? "" : ":" + String.valueOf(port)) + (path == null ? "" : quotePath(path)) + (query == null ? "" : "?" + quote(query)) + (fragment == null ? "" : "#" + quote(fragment))); } /** * Create an URI from the given components * * @param scheme The scheme name * @param authority The authority * @param path The apth * @param query The query * @param fragment The fragment * * @exception URISyntaxException If the given string violates RFC 2396 */ public URI(String scheme, String authority, String path, String query, String fragment) throws URISyntaxException { this((scheme == null ? "" : scheme + ":") + (authority == null ? "" : "//" + quoteAuthority(authority)) + (path == null ? "" : quotePath(path)) + (query == null ? "" : "?" + quote(query)) + (fragment == null ? "" : "#" + quote(fragment))); } /** * Create an URI from the given components * * @param scheme The scheme name * @param host The hostname * @param path The path * @param fragment The fragment * * @exception URISyntaxException If the given string violates RFC 2396 */ public URI(String scheme, String host, String path, String fragment) throws URISyntaxException { this(scheme, null, host, -1, path, null, fragment); } /** * Create an URI from the given components * * @param scheme The scheme name * @param ssp The scheme specific part * @param fragment The fragment * * @exception URISyntaxException If the given string violates RFC 2396 */ public URI(String scheme, String ssp, String fragment) throws URISyntaxException { this((scheme == null ? "" : scheme + ":") + (ssp == null ? "" : quote(ssp)) + (fragment == null ? "" : "#" + quote(fragment))); } /** * Create an URI from the given string * * @param str The string to create the URI from * * @exception IllegalArgumentException If the given string violates RFC 2396 * @exception NullPointerException If str is null */ public static URI create(String str) { try { return new URI(str); } catch (URISyntaxException e) { throw (IllegalArgumentException) new IllegalArgumentException() .initCause(e); } } /** * Attempts to parse this URI's authority component, if defined, * into user-information, host, and port components. The purpose * of this method was to disambiguate between some authority sections, * which form invalid server-based authories, but valid registry * based authorities. In the updated RFC 3986, the authority section * is defined differently, with registry-based authorities part of * the host section. Thus, this method is now simply an explicit * way of parsing any authority section. * * @return the URI, with the authority section parsed into user * information, host and port components. * @throws URISyntaxException if the given string violates RFC 2396 */ public URI parseServerAuthority() throws URISyntaxException { if (rawAuthority != null) { Matcher matcher = AUTHORITY_PATTERN.matcher(rawAuthority); if (matcher.matches()) { rawUserInfo = getURIGroup(matcher, AUTHORITY_USERINFO_GROUP); rawHost = getURIGroup(matcher, AUTHORITY_HOST_GROUP); String portStr = getURIGroup(matcher, AUTHORITY_PORT_GROUP); if (portStr != null) try { port = Integer.parseInt(portStr); } catch (NumberFormatException e) { URISyntaxException use = new URISyntaxException (string, "doesn't match URI regular expression"); use.initCause(e); throw use; } } else throw new URISyntaxException(string, "doesn't match URI regular expression"); } return this; } /** * <p> * Returns a normalized version of the URI. If the URI is opaque, * or its path is already in normal form, then this URI is simply * returned. Otherwise, the following transformation of the path * element takes place: * </p> * <ol> * <li>All `.' segments are removed.</li> * <li>Each `..' segment which can be paired with a prior non-`..' segment * is removed along with the preceding segment.</li> * <li>A `.' segment is added to the front if the first segment contains * a colon (`:'). This is a deviation from the RFC, which prevents * confusion between the path and the scheme.</li> * </ol> * <p> * The resulting URI will be free of `.' and `..' segments, barring those * that were prepended or which couldn't be paired, respectively. * </p> * * @return the normalized URI. */ public URI normalize() { if (isOpaque() || path.indexOf("/./") == -1 && path.indexOf("/../") == -1) return this; try { return new URI(scheme, authority, normalizePath(path), query, fragment); } catch (URISyntaxException e) { throw (Error) new InternalError("Normalized URI variant could not "+ "be constructed").initCause(e); } } /** * <p> * Normalize the given path. The following transformation takes place: * </p> * <ol> * <li>All `.' segments are removed.</li> * <li>Each `..' segment which can be paired with a prior non-`..' segment * is removed along with the preceding segment.</li> * <li>A `.' segment is added to the front if the first segment contains * a colon (`:'). This is a deviation from the RFC, which prevents * confusion between the path and the scheme.</li> * </ol> * <p> * The resulting URI will be free of `.' and `..' segments, barring those * that were prepended or which couldn't be paired, respectively. * </p> * * @param relativePath the relative path to be normalized. * @return the normalized path. */ private String normalizePath(String relativePath) { /* This follows the algorithm in section 5.2.4. of RFC3986, but doesn't modify the input buffer. */ StringBuffer input = new StringBuffer(relativePath); StringBuffer output = new StringBuffer(); int start = 0; while (start < input.length()) { /* A */ if (input.indexOf("../",start) == start) { start += 3; continue; } if (input.indexOf("./",start) == start) { start += 2; continue; } /* B */ if (input.indexOf("/./",start) == start) { start += 2; continue; } if (input.indexOf("/.",start) == start && input.charAt(start + 2) != '.') { start += 1; input.setCharAt(start,'/'); continue; } /* C */ if (input.indexOf("/../",start) == start) { start += 3; removeLastSegment(output); continue; } if (input.indexOf("/..",start) == start) { start += 2; input.setCharAt(start,'/'); removeLastSegment(output); continue; } /* D */ if (start == input.length() - 1 && input.indexOf(".",start) == start) { input.delete(0,1); continue; } if (start == input.length() - 2 && input.indexOf("..",start) == start) { input.delete(0,2); continue; } /* E */ int indexOfSlash = input.indexOf("/",start); while (indexOfSlash == start) { output.append("/"); ++start; indexOfSlash = input.indexOf("/",start); } if (indexOfSlash == -1) indexOfSlash = input.length(); output.append(input.substring(start, indexOfSlash)); start = indexOfSlash; } return output.toString(); } /** * Removes the last segment of the path from the specified buffer. * * @param buffer the buffer containing the path. */ private void removeLastSegment(StringBuffer buffer) { int lastSlash = buffer.lastIndexOf("/"); if (lastSlash == -1) buffer.setLength(0); else buffer.setLength(lastSlash); } /** * Resolves the given URI against this URI * * @param uri The URI to resolve against this URI * * @return The resulting URI, or null when it couldn't be resolved * for some reason. * * @throws NullPointerException if uri is null */ public URI resolve(URI uri) { if (uri.isAbsolute()) return uri; if (uri.isOpaque()) return uri; String scheme = uri.getScheme(); String schemeSpecificPart = uri.getSchemeSpecificPart(); String authority = uri.getAuthority(); String path = uri.getPath(); String query = uri.getQuery(); String fragment = uri.getFragment(); try { if (fragment != null && path != null && path.equals("") && scheme == null && authority == null && query == null) return new URI(this.scheme, this.schemeSpecificPart, fragment); if (authority == null) { authority = this.authority; if (path == null) path = ""; if (! (path.startsWith("/"))) { StringBuffer basepath = new StringBuffer(this.path); int i = this.path.lastIndexOf('/'); if (i >= 0) basepath.delete(i + 1, basepath.length()); basepath.append(path); path = normalizePath(basepath.toString()); } } return new URI(this.scheme, authority, path, query, fragment); } catch (URISyntaxException e) { throw (Error) new InternalError("Resolved URI variant could not "+ "be constructed").initCause(e); } } /** * Resolves the given URI string against this URI * * @param str The URI as string to resolve against this URI * * @return The resulting URI * * @throws IllegalArgumentException If the given URI string * violates RFC 2396 * @throws NullPointerException If uri is null */ public URI resolve(String str) throws IllegalArgumentException { return resolve(create(str)); } /** * <p> * Relativizes the given URI against this URI. The following * algorithm is used: * </p> * <ul> * <li>If either URI is opaque, the given URI is returned.</li> * <li>If the schemes of the URIs differ, the given URI is returned.</li> * <li>If the authority components of the URIs differ, then the given * URI is returned.</li> * <li>If the path of this URI is not a prefix of the supplied URI, * then the given URI is returned.</li> * <li>If all the above conditions hold, a new URI is created using the * query and fragment components of the given URI, along with a path * computed by removing the path of this URI from the start of the path * of the supplied URI.</li> * </ul> * * @param uri the URI to relativize agsint this URI * @return the resulting URI * @throws NullPointerException if the uri is null */ public URI relativize(URI uri) { if (isOpaque() || uri.isOpaque()) return uri;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -