Author: markt Date: Wed Jan 6 13:36:56 2016 New Revision: 1723316 URL: http://svn.apache.org/viewvc?rev=1723316&view=rev Log: Create a new UriUtil class that contains only those parts of o.a.tomcat.util.URI that a) are required by Tomcat and b) aren't provided by the JRE.
Added: tomcat/trunk/java/org/apache/catalina/util/UriUtil.java - copied, changed from r1723308, tomcat/trunk/java/org/apache/tomcat/util/net/URL.java Copied: tomcat/trunk/java/org/apache/catalina/util/UriUtil.java (from r1723308, tomcat/trunk/java/org/apache/tomcat/util/net/URL.java) URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/UriUtil.java?p2=tomcat/trunk/java/org/apache/catalina/util/UriUtil.java&p1=tomcat/trunk/java/org/apache/tomcat/util/net/URL.java&r1=1723308&r2=1723316&rev=1723316&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/URL.java (original) +++ tomcat/trunk/java/org/apache/catalina/util/UriUtil.java Wed Jan 6 13:36:56 2016 @@ -14,638 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.apache.tomcat.util.net; - - -import java.io.Serializable; -import java.net.MalformedURLException; -import java.util.Locale; - +package org.apache.catalina.util; /** - * <p><strong>URL</strong> is designed to provide public APIs for parsing - * and synthesizing Uniform Resource Locators as similar as possible to the - * APIs of <code>java.net.URL</code>, but without the ability to open a - * stream or connection. One of the consequences of this is that you can - * construct URLs for protocols for which a URLStreamHandler is not - * available (such as an "https" URL when JSSE is not installed).</p> - * - * <p><strong>WARNING</strong> - This class assumes that the string - * representation of a URL conforms to the <code>spec</code> argument - * as described in RFC 2396 "Uniform Resource Identifiers: Generic Syntax":</p> - * <pre> - * <scheme>//<authority><path>?<query>#<fragment> - * </pre> - * - * <p><strong>FIXME</strong> - This class really ought to end up in a Commons - * package someplace.</p> - * - * @author Craig R. McClanahan + * Utility class for working with URIs and URLs. */ -public final class URL implements Serializable { - - private static final long serialVersionUID = 1L; - - - // ----------------------------------------------------------- Constructors - - /** - * Create a URL object from the specified String representation. - * - * @param spec String representation of the URL - * - * @exception MalformedURLException if the string representation - * cannot be parsed successfully - */ - public URL(String spec) throws MalformedURLException { - - this(null, spec); - - } - - - /** - * Create a URL object by parsing a string representation relative - * to a specified context. Based on logic from JDK 1.3.1's - * <code>java.net.URL</code>. - * - * @param context URL against which the relative representation - * is resolved - * @param spec String representation of the URL (usually relative) - * - * @exception MalformedURLException if the string representation - * cannot be parsed successfully - */ - public URL(URL context, String spec) throws MalformedURLException { - - String original = spec; - int i, limit, c; - int start = 0; - String newProtocol = null; - boolean aRef = false; - - try { - - // Eliminate leading and trailing whitespace - limit = spec.length(); - while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { - limit--; - } - while ((start < limit) && (spec.charAt(start) <= ' ')) { - start++; - } - - // If the string representation starts with "url:", skip it - if (spec.regionMatches(true, start, "url:", 0, 4)) { - start += 4; - } - - // Is this a ref relative to the context URL? - if ((start < spec.length()) && (spec.charAt(start) == '#')) { - aRef = true; - } - - // Parse out the new protocol - for (i = start; !aRef && (i < limit) ; i++) { - c = spec.charAt(i); - if (c == ':') { - String s = spec.substring(start, i).toLowerCase(Locale.ENGLISH); - // Assume all protocols are valid - newProtocol = s; - start = i + 1; - break; - } else if( c == '#' ) { - aRef = true; - } else if( !isSchemeChar((char)c) ) { - break; - } - } - - // Only use our context if the protocols match - protocol = newProtocol; - if ((context != null) && ((newProtocol == null) || - newProtocol.equalsIgnoreCase(context.getProtocol()))) { - // If the context is a hierarchical URL scheme and the spec - // contains a matching scheme then maintain backwards - // compatibility and treat it as if the spec didn't contain - // the scheme; see 5.2.3 of RFC2396 - if ((context.getPath() != null) && - (context.getPath().startsWith("/"))) - newProtocol = null; - if (newProtocol == null) { - protocol = context.getProtocol(); - authority = context.getAuthority(); - userInfo = context.getUserInfo(); - host = context.getHost(); - port = context.getPort(); - file = context.getFile(); - int question = file.lastIndexOf('?'); - if (question < 0) - path = file; - else - path = file.substring(0, question); - } - } - - if (protocol == null) - throw new MalformedURLException("no protocol: " + original); - - // Parse out any ref portion of the spec - i = spec.indexOf('#', start); - if (i >= 0) { - ref = spec.substring(i + 1, limit); - limit = i; - } - - // Parse the remainder of the spec in a protocol-specific fashion - parse(spec, start, limit); - if (context != null) - normalize(); - - - } catch (MalformedURLException e) { - throw e; - } catch (Exception e) { - throw new MalformedURLException(e.toString()); - } - - } - - - // ----------------------------------------------------- Instance Variables - - - /** - * The authority part of the URL. - */ - private String authority = null; - - - /** - * The filename part of the URL. - */ - private String file = null; - - - /** - * The host name part of the URL. - */ - private String host = null; - - - /** - * The path part of the URL. - */ - private String path = null; - - - /** - * The port number part of the URL. - */ - private int port = -1; - - - /** - * The protocol name part of the URL. - */ - private String protocol = null; - - - /** - * The query part of the URL. - */ - private String query = null; - - - /** - * The reference part of the URL. - */ - private String ref = null; - - - /** - * The user info part of the URL. - */ - private String userInfo = null; - - - // --------------------------------------------------------- Public Methods - - - /** - * Compare two URLs for equality. The result is <code>true</code> if and - * only if the argument is not null, and is a <code>URL</code> object - * that represents the same <code>URL</code> as this object. Two - * <code>URLs</code> are equal if they have the same protocol and - * reference the same host, the same port number on the host, - * and the same file and anchor on the host. - * - * @param obj The URL to compare against - */ - @Override - public boolean equals(Object obj) { - - if (!(obj instanceof URL)) - return false; - URL other = (URL) obj; - if (!sameFile(other)) - return false; - return (compare(ref, other.getRef())); - - } - - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((file == null) ? 0 : file.hashCode()); - result = prime * result + ((host == null) ? 0 : host.hashCode()); - result = prime * result + port; - result = prime * result + - ((protocol == null) ? 0 : protocol.hashCode()); - result = prime * result + ((ref == null) ? 0 : ref.hashCode()); - return result; - } - - - /** - * Return the authority part of the URL. - */ - public String getAuthority() { - - return (this.authority); - - } - - - /** - * Return the filename part of the URL. <strong>NOTE</strong> - For - * compatibility with <code>java.net.URL</code>, this value includes - * the query string if there was one. For just the path portion, - * call <code>getPath()</code> instead. - */ - public String getFile() { - - if (file == null) - return (""); - return (this.file); - - } - - - /** - * Return the host name part of the URL. - */ - public String getHost() { - - return (this.host); - - } - - - /** - * Return the path part of the URL. - */ - public String getPath() { - - if (this.path == null) - return (""); - return (this.path); - - } - - - /** - * Return the port number part of the URL. - */ - public int getPort() { - - return (this.port); - - } - - - /** - * Return the protocol name part of the URL. - */ - public String getProtocol() { - - return (this.protocol); - - } - - - /** - * Return the query part of the URL. - */ - public String getQuery() { - - return (this.query); - - } - - - /** - * Return the reference part of the URL. - */ - public String getRef() { - - return (this.ref); - - } - - - /** - * Return the user info part of the URL. - */ - public String getUserInfo() { - - return (this.userInfo); - - } - - - /** - * Normalize the <code>path</code> (and therefore <code>file</code>) - * portions of this URL. - * <p> - * <strong>NOTE</strong> - This method is not part of the public API - * of <code>java.net.URL</code>, but is provided as a value added - * service of this implementation. - * - * @exception MalformedURLException if a normalization error occurs, - * such as trying to move about the hierarchical root - */ - public void normalize() throws MalformedURLException { - - // Special case for null path - if (path == null) { - if (query != null) - file = "?" + query; - else - file = ""; - return; - } - - // Create a place for the normalized path - String normalized = path; - if (normalized.equals("/.")) { - path = "/"; - if (query != null) - file = path + "?" + query; - else - file = path; - return; - } - - // Normalize the slashes and add leading slash if necessary - if (normalized.indexOf('\\') >= 0) - normalized = normalized.replace('\\', '/'); - if (!normalized.startsWith("/")) - normalized = "/" + normalized; - - // Resolve occurrences of "//" in the normalized path - while (true) { - int index = normalized.indexOf("//"); - if (index < 0) - break; - normalized = normalized.substring(0, index) + - normalized.substring(index + 1); - } - - // Resolve occurrences of "/./" in the normalized path - while (true) { - int index = normalized.indexOf("/./"); - if (index < 0) - break; - normalized = normalized.substring(0, index) + - normalized.substring(index + 2); - } - - // Resolve occurrences of "/../" in the normalized path - while (true) { - int index = normalized.indexOf("/../"); - if (index < 0) - break; - if (index == 0) - throw new MalformedURLException - ("Invalid relative URL reference"); - int index2 = normalized.lastIndexOf('/', index - 1); - normalized = normalized.substring(0, index2) + - normalized.substring(index + 3); - } - - // Resolve occurrences of "/." at the end of the normalized path - if (normalized.endsWith("/.")) - normalized = normalized.substring(0, normalized.length() - 1); - - // Resolve occurrences of "/.." at the end of the normalized path - if (normalized.endsWith("/..")) { - int index = normalized.length() - 3; - int index2 = normalized.lastIndexOf('/', index - 1); - if (index2 < 0) - throw new MalformedURLException - ("Invalid relative URL reference"); - normalized = normalized.substring(0, index2 + 1); - } - - // Return the normalized path that we have completed - path = normalized; - if (query != null) - file = path + "?" + query; - else - file = path; - - } - - - /** - * Compare two URLs, excluding the "ref" fields. Returns <code>true</code> - * if this <code>URL</code> and the <code>other</code> argument both refer - * to the same resource. The two <code>URLs</code> might not both contain - * the same anchor. - */ - public boolean sameFile(URL other) { - - if (!compare(protocol, other.getProtocol())) - return false; - if (!compare(host, other.getHost())) - return false; - if (port != other.getPort()) - return false; - if (!compare(file, other.getFile())) - return false; - return true; - - } - - - /** - * Return a string representation of this object. - */ - @Override - public String toString() { - - StringBuilder sb = new StringBuilder("URL["); - sb.append("authority="); - sb.append(authority); - sb.append(", file="); - sb.append(file); - sb.append(", host="); - sb.append(host); - sb.append(", port="); - sb.append(port); - sb.append(", protocol="); - sb.append(protocol); - sb.append(", query="); - sb.append(query); - sb.append(", ref="); - sb.append(ref); - sb.append(", userInfo="); - sb.append(userInfo); - sb.append("]"); - return (sb.toString()); - - // return (toExternalForm()); - - } - - - // -------------------------------------------------------- Private Methods - - - /** - * Compare to String values for equality, taking appropriate care if one - * or both of the values are <code>null</code>. - * - * @param first First string - * @param second Second string - */ - private boolean compare(String first, String second) { - - if (first == null) { - if (second == null) - return true; - else - return false; - } else { - if (second == null) - return false; - else - return (first.equals(second)); - } +public final class UriUtil { + private UriUtil() { + // Utility class. Hide default constructor } /** - * Parse the specified portion of the string representation of a URL, - * assuming that it has a format similar to that for <code>http</code>. - * - * <p><strong>FIXME</strong> - This algorithm can undoubtedly be optimized - * for performance. However, that needs to wait until after sufficient - * unit tests are implemented to guarantee correct behavior with no - * regressions.</p> - * - * @param spec String representation being parsed - * @param start Starting offset, which will be just after the ':' (if - * there is one) that determined the protocol name - * @param limit Ending position, which will be the position of the '#' - * (if there is one) that delimited the anchor - * - * @exception MalformedURLException if a parsing error occurs - */ - private void parse(String spec, int start, int limit) - throws MalformedURLException { - - // Trim the query string (if any) off the tail end - int question = spec.lastIndexOf('?', limit - 1); - if ((question >= 0) && (question < limit)) { - query = spec.substring(question + 1, limit); - limit = question; - } else { - query = null; - } - - // Parse the authority section - if (spec.indexOf("//", start) == start) { - int pathStart = spec.indexOf('/', start + 2); - if ((pathStart >= 0) && (pathStart < limit)) { - authority = spec.substring(start + 2, pathStart); - start = pathStart; - } else { - authority = spec.substring(start + 2, limit); - start = limit; - } - if (authority.length() > 0) { - int at = authority.indexOf('@'); - if( at >= 0 ) { - userInfo = authority.substring(0,at); - } - int ipv6 = authority.indexOf('[',at+1); - int hStart = at+1; - if( ipv6 >= 0 ) { - hStart = ipv6; - ipv6 = authority.indexOf(']', ipv6); - if( ipv6 < 0 ) { - throw new MalformedURLException( - "Closing ']' not found in IPV6 address: " + authority); - } else { - at = ipv6-1; - } - } - - int colon = authority.indexOf(':', at+1); - if (colon >= 0) { - try { - port = - Integer.parseInt(authority.substring(colon + 1)); - } catch (NumberFormatException e) { - throw new MalformedURLException(e.toString()); - } - host = authority.substring(hStart, colon); - } else { - host = authority.substring(hStart); - port = -1; - } - } - } - - // Parse the path section - if (spec.indexOf('/', start) == start) { // Absolute path - path = spec.substring(start, limit); - if (query != null) - file = path + "?" + query; - else - file = path; - return; - } - - // Resolve relative path against our context's file - if (path == null) { - if (query != null) - file = "?" + query; - else - file = null; - return; - } - if (!path.startsWith("/")) - throw new MalformedURLException - ("Base path does not start with '/'"); - if (!path.endsWith("/")) - path += "/../"; - path += spec.substring(start, limit); - if (query != null) - file = path + "?" + query; - else - file = path; - return; - - } - - /** * Determine if the character is allowed in the scheme of a URI. * See RFC 2396, Section 3.1 * @@ -655,8 +36,7 @@ public final class URL implements Serial * @false} */ private static boolean isSchemeChar(char c) { - return Character.isLetterOrDigit(c) || - c == '+' || c == '-' || c == '.'; + return Character.isLetterOrDigit(c) || c == '+' || c == '-' || c == '.'; } @@ -673,7 +53,7 @@ public final class URL implements Serial char c = uri.charAt(i); if(c == ':') { return i > 0; - } else if(!URL.isSchemeChar(c)) { + } else if(!UriUtil.isSchemeChar(c)) { return false; } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org