/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.tomcat.util.buf;
/** * Determine if the character is allowed in the scheme of a URI. See RFC 2396, Section 3.1 * * @param c The character to test * * @return {@code true} if a the character is allowed, otherwise {@code * false}
*/ privatestaticboolean isSchemeChar(char c) { return Character.isLetterOrDigit(c) || c == '+' || c == '-' || c == '.';
}
/** * Determine if a URI string has a <code>scheme</code> component. * * @param uri The URI to test * * @return {@code true} if a scheme is present, otherwise {code @false}
*/ publicstaticboolean hasScheme(CharSequence uri) { int len = uri.length(); for (int i = 0; i < len; i++) { char c = uri.charAt(i); if (c == ':') { return i > 0;
} elseif (!isSchemeChar(c)) { returnfalse;
}
} returnfalse;
}
/* * When testing on markt's desktop each iteration was taking ~1420ns when using String.replaceAll(). * * Switching the implementation to use pre-compiled patterns and Pattern.matcher(input).replaceAll(replacement) * reduced this by ~10%. * * Note: Given the very small absolute time of a single iteration, even for a web application with 1000 JARs this is * only going to add ~3ms. It is therefore unlikely that further optimisation will be necessary.
*/ /* * Pulled out into a separate method in case we need to handle other unusual sequences in the future.
*/ privatestatic String makeSafeForJarUrl(String input) { // Since "!/" has a special meaning in a JAR URL, make sure that the // sequence is properly escaped if present.
String tmp = PATTERN_EXCLAMATION_MARK.matcher(input).replaceAll("%21/"); // Tomcat's custom jar:war: URL handling treats */ and ^/ as special
tmp = PATTERN_CARET.matcher(tmp).replaceAll("%5e/");
tmp = PATTERN_ASTERISK.matcher(tmp).replaceAll("%2a/"); if (PATTERN_CUSTOM != null) {
tmp = PATTERN_CUSTOM.matcher(tmp).replaceAll(REPLACE_CUSTOM);
} return tmp;
}
/** * Convert a URL of the form <code>war:file:...</code> to <code>jar:file:...</code>. * * @param warUrl The WAR URL to convert * * @return The equivalent JAR URL * * @throws MalformedURLException If the conversion fails
*/ publicstatic URL warToJar(URL warUrl) throws MalformedURLException { // Assumes that the spec is absolute and starts war:file:/...
String file = warUrl.getFile(); if (file.contains("*/")) {
file = file.replaceFirst("\\*/", "!/");
} elseif (file.contains("^/")) {
file = file.replaceFirst("\\^/", "!/");
} elseif (PATTERN_CUSTOM != null) {
file = file.replaceFirst(PATTERN_CUSTOM.pattern(), "!/");
}
/** * Does the provided path start with <code>file:/</code> or <code><protocol>://</code>. * * @param path The path to test * * @return {@code true} if the supplied path starts with once of the recognised sequences.
*/ publicstaticboolean isAbsoluteURI(String path) { // Special case as only a single / if (path.startsWith("file:/")) { returntrue;
}
// Start at the beginning of the path and skip over any valid protocol // characters int i = 0; while (i < path.length() && isSchemeChar(path.charAt(i))) {
i++;
} // Need at least one protocol character. False positives with Windows // drives such as C:/... will be caught by the later test for "://" if (i == 0) { returnfalse;
} // path starts with something that might be a protocol. Look for a // following "://" if (i + 2 < path.length() && path.charAt(i++) == ':' && path.charAt(i++) == '/' && path.charAt(i) == '/') { returntrue;
} returnfalse;
}
/** * Replicates the behaviour of {@link URI#resolve(String)} and adds support for URIs of the form * {@code jar:file:/... }. * * @param base The base URI to resolve against * @param target The path to resolve * * @return The resulting URI as per {@link URI#resolve(String)} * * @throws MalformedURLException If the base URI cannot be converted to a URL * @throws URISyntaxException If the resulting URL cannot be converted to a URI
*/ publicstatic URI resolve(URI base, String target) throws MalformedURLException, URISyntaxException { if (base.getScheme().equals("jar")) { /* * Previously used: new URL(base.toURL(), target).toURI() This delegated the work to the jar stream handler * which correctly resolved the target against the base. * * Deprecation of all the URL constructors mean a different approach is required.
*/
URI fileUri = new URI(base.getSchemeSpecificPart());
URI fileUriResolved = fileUri.resolve(target);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.