From 13ffcca2c1dee30bde06a10c6405ed41afaeee73 Mon Sep 17 00:00:00 2001 From: Martin Stockhammer Date: Sat, 1 Feb 2020 12:15:18 +0100 Subject: [PATCH] Dependency cleanup --- .../apache/archiva/common/utils/PathUtil.java | 439 ++++++++++++++++++ .../archiva-base/archiva-proxy/pom.xml | 133 ++++-- .../proxy/DefaultRepositoryProxyHandler.java | 9 +- status-dep.txt | 1 + 4 files changed, 536 insertions(+), 46 deletions(-) diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/common/utils/PathUtil.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/common/utils/PathUtil.java index ddf9ededd..8c9a437a4 100644 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/common/utils/PathUtil.java +++ b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/common/utils/PathUtil.java @@ -23,16 +23,27 @@ import org.apache.commons.lang3.StringUtils; import java.net.MalformedURLException; import java.net.URI; +import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.stream.StreamSupport; /** + * * PathUtil - simple utility methods for path manipulation. * + * Some code is from Apache Ant SelectorUtils * */ public class PathUtil { + + public static final String DEEP_TREE_MATCH = "**"; + public static String toUrl( String path ) { // Is our work already done for us? @@ -114,4 +125,432 @@ public class PathUtil return Paths.get(uri); } } + + public static boolean isAbsolutePath(String path) { + try + { + return Paths.get( path ).isAbsolute( ); + } catch (Exception e) { + return false; + } + } + + public static char getSeparatorChar() { + return FileSystems.getDefault( ).getSeparator( ).charAt( 0 ); + } + + public static String[] dissect(String pathString) { + Path path = Paths.get(pathString); + return StreamSupport.stream(path.spliterator(), false).map(Path::toString) + .toArray(String[]::new); + } + + public static String separatorsToUnix(String path) + { + return path != null && path.indexOf( 92 ) != -1 ? path.replace( '\\', '/' ) : path; + } + + + /** + * Tests whether or not a given path matches a given pattern. + * + * If you need to call this method multiple times with the same + * pattern you should rather use TokenizedPath + * + * @param pattern The pattern to match against. Must not be + * null. + * @param str The path to match, as a String. Must not be + * null. + * + * @return true if the pattern matches against the string, + * or false otherwise. + */ + public static boolean matchPath(String pattern, String str) { + String[] patDirs = tokenizePathAsArray(pattern); + return matchPath(patDirs, tokenizePathAsArray(str), true); + } + + /** + * Tests whether or not a given path matches a given pattern. + * + * If you need to call this method multiple times with the same + * pattern you should rather use TokenizedPattern + * + * + * @param pattern The pattern to match against. Must not be + * null. + * @param str The path to match, as a String. Must not be + * null. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * @return true if the pattern matches against the string, + * or false otherwise. + */ + public static boolean matchPath(String pattern, String str, + boolean isCaseSensitive) { + String[] patDirs = tokenizePathAsArray(pattern); + return matchPath(patDirs, tokenizePathAsArray(str), isCaseSensitive); + } + + /** + * Core implementation of matchPath. It is isolated so that it + * can be called from TokenizedPattern. + */ + static boolean matchPath(String[] tokenizedPattern, String[] strDirs, + boolean isCaseSensitive) { + int patIdxStart = 0; + int patIdxEnd = tokenizedPattern.length - 1; + int strIdxStart = 0; + int strIdxEnd = strDirs.length - 1; + + // up to first '**' + while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) { + String patDir = tokenizedPattern[patIdxStart]; + if (patDir.equals(DEEP_TREE_MATCH)) { + break; + } + if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) { + return false; + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // String is exhausted + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) { + return false; + } + } + return true; + } + if (patIdxStart > patIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } + + // up to last '**' + while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) { + String patDir = tokenizedPattern[patIdxEnd]; + if (patDir.equals(DEEP_TREE_MATCH)) { + break; + } + if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) { + return false; + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // String is exhausted + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) { + return false; + } + } + return true; + } + + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (tokenizedPattern[i].equals(DEEP_TREE_MATCH)) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // '**/**' situation, so skip one + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = tokenizedPattern[patIdxStart + j + 1]; + String subStr = strDirs[strIdxStart + i + j]; + if (!match(subPat, subStr, isCaseSensitive)) { + continue strLoop; + } + } + foundIdx = strIdxStart + i; + break; + } + if (foundIdx == -1) { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (!DEEP_TREE_MATCH.equals(tokenizedPattern[i])) { + return false; + } + } + return true; + } + + /** + * Tests whether or not a string matches against a pattern. + * The pattern may contain two special characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * + * @param pattern The pattern to match against. + * Must not be null. + * @param str The string which must be matched against the pattern. + * Must not be null. + * + * @return true if the string matches against the pattern, + * or false otherwise. + */ + public static boolean match(String pattern, String str) { + return match(pattern, str, true); + } + + /** + * Tests whether or not a string matches against a pattern. + * The pattern may contain two special characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * + * @param pattern The pattern to match against. + * Must not be null. + * @param str The string which must be matched against the pattern. + * Must not be null. + * @param caseSensitive Whether or not matching should be performed + * case sensitively. + * + * + * @return true if the string matches against the pattern, + * or false otherwise. + */ + public static boolean match(String pattern, String str, + boolean caseSensitive) { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length - 1; + int strIdxStart = 0; + int strIdxEnd = strArr.length - 1; + + boolean containsStar = false; + for (char ch : patArr) { + if (ch == '*') { + containsStar = true; + break; + } + } + + if (!containsStar) { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) { + char ch = patArr[i]; + if (ch != '?' && different(caseSensitive, ch, strArr[i])) { + return false; // Character mismatch + } + } + return true; // String matches against pattern + } + + if (patIdxEnd == 0) { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while (true) { + char ch = patArr[patIdxStart]; + if (ch == '*' || strIdxStart > strIdxEnd) { + break; + } + if (ch != '?' + && different(caseSensitive, ch, strArr[strIdxStart])) { + return false; // Character mismatch + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + return allStars(patArr, patIdxStart, patIdxEnd); + } + + // Process characters after last star + while (true) { + char ch = patArr[patIdxEnd]; + if (ch == '*' || strIdxStart > strIdxEnd) { + break; + } + if (ch != '?' && different(caseSensitive, ch, strArr[strIdxEnd])) { + return false; // Character mismatch + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + return allStars(patArr, patIdxStart, patIdxEnd); + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*') { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + char ch = patArr[patIdxStart + j + 1]; + if (ch != '?' && different(caseSensitive, ch, + strArr[strIdxStart + i + j])) { + continue strLoop; + } + } + foundIdx = strIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + return allStars(patArr, patIdxStart, patIdxEnd); + } + + private static boolean allStars(char[] chars, int start, int end) { + for (int i = start; i <= end; ++i) { + if (chars[i] != '*') { + return false; + } + } + return true; + } + + private static boolean different( + boolean caseSensitive, char ch, char other) { + return caseSensitive + ? ch != other + : Character.toUpperCase(ch) != Character.toUpperCase(other); + } + + /** + * Breaks a path up into a Vector of path elements, tokenizing on + * File.separator. + * + * @param path Path to tokenize. Must not be null. + * + * @return a Vector of path elements from the tokenized path + */ + public static Vector tokenizePath( String path) { + return tokenizePath(path, FileSystems.getDefault( ).getSeparator()); + } + + /** + * Breaks a path up into a Vector of path elements, tokenizing on + * + * @param path Path to tokenize. Must not be null. + * @param separator the separator against which to tokenize. + * + * @return a Vector of path elements from the tokenized path + * @since Ant 1.6 + */ + public static Vector tokenizePath(String path, String separator) { + Vector ret = new Vector<>(); + if (isAbsolutePath(path)) { + String[] s = dissect(path); + ret.add(s[0]); + path = s[1]; + } + StringTokenizer st = new StringTokenizer(path, separator); + while (st.hasMoreTokens()) { + ret.addElement(st.nextToken()); + } + return ret; + } + + /** + * Same as {@link #tokenizePath tokenizePath} but hopefully faster. + */ + /* package */ + static String[] tokenizePathAsArray(String path) { + String root = null; + if (isAbsolutePath(path)) { + String[] s = dissect(path); + root = s[0]; + path = s[1]; + } + char sep = getSeparatorChar(); + int start = 0; + int len = path.length(); + int count = 0; + for (int pos = 0; pos < len; pos++) { + if (path.charAt(pos) == sep) { + if (pos != start) { + count++; + } + start = pos + 1; + } + } + if (len != start) { + count++; + } + String[] l = new String[count + ((root == null) ? 0 : 1)]; + + if (root != null) { + l[0] = root; + count = 1; + } else { + count = 0; + } + start = 0; + for (int pos = 0; pos < len; pos++) { + if (path.charAt(pos) == sep) { + if (pos != start) { + String tok = path.substring(start, pos); + l[count++] = tok; + } + start = pos + 1; + } + } + if (len != start) { + String tok = path.substring(start); + l[count/*++*/] = tok; + } + return l; + } + + } diff --git a/archiva-modules/archiva-base/archiva-proxy/pom.xml b/archiva-modules/archiva-base/archiva-proxy/pom.xml index f3edcd0ba..3c0281416 100644 --- a/archiva-modules/archiva-base/archiva-proxy/pom.xml +++ b/archiva-modules/archiva-base/archiva-proxy/pom.xml @@ -44,16 +44,6 @@ org.apache.archiva archiva-repository-layer - - - log4j - log4j - - - commons-logging - commons-logging-api - - org.apache.archiva @@ -67,15 +57,64 @@ org.apache.archiva archiva-proxy-api + + org.apache.archiva + archiva-storage-api + + + org.apache.archiva + archiva-storage-fs + + + org.apache.archiva.components + archiva-components-spring-taskqueue + + + org.apache.archiva + archiva-common + + + org.apache.archiva + archiva-policies + + + org.apache.archiva + archiva-repository-api + + + org.apache.archiva + archiva-model + + + org.apache.archiva + archiva-checksum + + + + javax.inject + javax.inject + + + javax.annotation + javax.annotation-api + + + org.springframework + spring-context + + + org.apache.commons commons-lang3 @@ -84,34 +123,43 @@ org.apache.commons commons-collections4 - - org.apache.ant - ant - - - org.eclipse.sisu - org.eclipse.sisu.plexus - + + + org.apache.archiva.components.registry archiva-components-spring-registry-commons test + + org.apache.archiva archiva-test-utils @@ -144,25 +193,28 @@ redback-rbac-cached test + + + + org.hsqldb hsqldb @@ -170,26 +222,6 @@ - - - javax.annotation - javax.annotation-api - test - - - - javax.xml.bind - jaxb-api - test - - - - - - org.ow2.asm - asm - test - @@ -225,4 +257,21 @@ + + + + jdk9+ + + [1.9,) + + + + + javax.xml.bind + jaxb-api + test + + + + diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java index 7cce032e8..71ec9ab64 100644 --- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java +++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyHandler.java @@ -22,6 +22,7 @@ package org.apache.archiva.proxy; import org.apache.archiva.checksum.ChecksumAlgorithm; import org.apache.archiva.checksum.ChecksumUtil; import org.apache.archiva.common.filelock.FileLockManager; +import org.apache.archiva.common.utils.PathUtil; import org.apache.archiva.configuration.ArchivaConfiguration; import org.apache.archiva.configuration.ProxyConnectorConfiguration; import org.apache.archiva.configuration.ProxyConnectorRuleConfiguration; @@ -54,10 +55,8 @@ import org.apache.archiva.repository.storage.StorageUtil; import org.apache.archiva.scheduler.ArchivaTaskScheduler; import org.apache.archiva.scheduler.repository.model.RepositoryTask; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; -import org.apache.tools.ant.types.selectors.SelectorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MarkerFactory; @@ -136,6 +135,8 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa return proxyConnectorRuleConfigurations; } + + @Override public StorageAsset fetchFromProxies( ManagedRepository repository, ArtifactReference artifact ) throws ProxyDownloadException @@ -164,7 +165,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa if ( SystemUtils.IS_OS_WINDOWS ) { // toPath use system PATH_SEPARATOR so on windows url are \ which doesn't work very well :-) - targetPath = FilenameUtils.separatorsToUnix( targetPath ); + targetPath = PathUtil.separatorsToUnix( targetPath ); } try @@ -770,7 +771,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa pattern = "/" + pattern; } - if ( SelectorUtils.matchPath( pattern, path, false ) ) + if ( PathUtil.matchPath( pattern, path, false ) ) { return true; } diff --git a/status-dep.txt b/status-dep.txt index 37e40381f..4730f4892 100644 --- a/status-dep.txt +++ b/status-dep.txt @@ -15,6 +15,7 @@ archiva-modules archiva-repository-api archiva-xml-tools archiva-repository-layer + archiva-proxy-api -- 2.39.5