Просмотр исходного кода

Use nio Filesystem getPathMatcher

pull/59/head
Eric Barboni 4 лет назад
Родитель
Сommit
eb813618c5

+ 4
- 7
archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/FileTypes.java Просмотреть файл

@@ -21,12 +21,8 @@ package org.apache.archiva.configuration;

import org.apache.archiva.common.FileTypeUtils;
import org.apache.archiva.configuration.functors.FiletypeSelectionPredicate;
import org.apache.archiva.configuration.io.registry.ConfigurationRegistryReader;
import org.apache.archiva.configuration.util.PathMatcher;
import org.apache.archiva.components.registry.Registry;
import org.apache.archiva.components.registry.RegistryException;
import org.apache.archiva.components.registry.RegistryListener;
import org.apache.archiva.components.registry.commons.CommonsConfigurationRegistry;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
@@ -35,7 +31,8 @@ import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.lang.reflect.Field;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -136,7 +133,7 @@ public class FileTypes

for ( String pattern : artifactPatterns )
{
if ( PathMatcher.matchPath( pattern, relativePath, false ) )
if ( FileSystems.getDefault().getPathMatcher( "glob:" + pattern).matches( Paths.get( relativePath ) ) )
{
// Found match
return true;
@@ -154,7 +151,7 @@ public class FileTypes

for ( String pattern : DEFAULT_EXCLUSIONS )
{
if ( PathMatcher.matchPath( pattern, relativePath, false ) )
if ( FileSystems.getDefault().getPathMatcher( "glob:" + pattern).matches( Paths.get( relativePath ) ) )
{
// Found match
return true;

+ 0
- 421
archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/util/PathMatcher.java Просмотреть файл

@@ -1,421 +0,0 @@
package org.apache.archiva.configuration.util;

/*
* 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.
*/

import java.io.File;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
*
* This provides a path matcher like in the SelectorUtils of the ant project.
*
* Using code from apache ant org.apache.tools.ant.types.selectors.SelectorUtils to remove the ant dependency for code
* compilation.
* See https://github.com/apache/ant/blob/master/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
*
* @author Martin Stockhammer <martin_s@apache.org>
*
*
*/
public class PathMatcher
{

private static final String DEEP_TREE_MATCH = "**";


/**
* Tests whether or not a string matches against a pattern.
* The pattern may contain two special characters:<br>
* '*' means zero or more characters<br>
* '?' means one and only one character
*
* @param pattern The pattern to match against.
* Must not be <code>null</code>.
* @param str The string which must be matched against the pattern.
* Must not be <code>null</code>.
*
* @return <code>true</code> if the string matches against the pattern,
* or <code>false</code> 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:<br>
* '*' means zero or more characters<br>
* '?' means one and only one character
*
* @param pattern The pattern to match against.
* Must not be <code>null</code>.
* @param str The string which must be matched against the pattern.
* Must not be <code>null</code>.
* @param caseSensitive Whether or not matching should be performed
* case sensitively.
*
*
* @return <code>true</code> if the string matches against the pattern,
* or <code>false</code> 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);
}

/**
* 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
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
*
* @return <code>true</code> if the pattern matches against the string,
* or <code>false</code> otherwise.
*/
public static boolean matchPath(String pattern, String str) {
String[] patDirs = tokenizePathAsArray( pattern, false );
return matchPath(patDirs, tokenizePathAsArray( str, true ), 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
* <code>null</code>.
* @param str The path to match, as a String. Must not be
* <code>null</code>.
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
*
* @return <code>true</code> if the pattern matches against the string,
* or <code>false</code> otherwise.
*/
public static boolean matchPath(String pattern, String str,
boolean isCaseSensitive) {
String[] patDirs = tokenizePathAsArray( pattern, false );
return matchPath(patDirs, tokenizePathAsArray( str, false ), isCaseSensitive);
}

/**
*
* @param path
* @param osspecific
* @return
*/
static String[] tokenizePathAsArray(String path, boolean osSpecific) {
Path root = null;
try
{
Path fsPath = Paths.get( path );
if ( fsPath.isAbsolute() ) {
root = fsPath.getRoot();
path = root.relativize( fsPath ).toString();
}
} catch (InvalidPathException ipe )
{
// invalid path, windauze hate **/*
}
char sep = osSpecific ? File.separatorChar : '/';
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.toString();
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;
}

/**
* Core implementation of matchPath. It is isolated so that it
* can be called from TokenizedPattern.
*/
public 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;
}


}

Загрузка…
Отмена
Сохранить