mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-23 09:31:32 +01:00
resolved merge
This commit is contained in:
@@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.owasp.dependencycheck.org.apache.tools.ant;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
|
|
||||||
import org.xml.sax.Locator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the location of a piece of text within a file (file name,
|
|
||||||
* line number and column number). Note that the column number is
|
|
||||||
* currently ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Location implements Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** Name of the file. */
|
|
||||||
private final String fileName;
|
|
||||||
/** Line number within the file. */
|
|
||||||
private final int lineNumber;
|
|
||||||
/** Column number within the file. */
|
|
||||||
private final int columnNumber;
|
|
||||||
|
|
||||||
/** Location to use when one is needed but no information is available */
|
|
||||||
public static final Location UNKNOWN_LOCATION = new Location();
|
|
||||||
|
|
||||||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an "unknown" location.
|
|
||||||
*/
|
|
||||||
private Location() {
|
|
||||||
this(null, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a location consisting of a file name but no line number or
|
|
||||||
* column number.
|
|
||||||
*
|
|
||||||
* @param fileName The name of the file. May be <code>null</code>,
|
|
||||||
* in which case the location is equivalent to
|
|
||||||
* {@link #UNKNOWN_LOCATION UNKNOWN_LOCATION}.
|
|
||||||
*/
|
|
||||||
public Location(String fileName) {
|
|
||||||
this(fileName, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a location from the SAX locator using the system ID as
|
|
||||||
* the filename.
|
|
||||||
*
|
|
||||||
* @param loc Must not be <code>null</code>.
|
|
||||||
*
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public Location(Locator loc) {
|
|
||||||
this(loc.getSystemId(), loc.getLineNumber(), loc.getColumnNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a location consisting of a file name, line number and
|
|
||||||
* column number.
|
|
||||||
*
|
|
||||||
* @param fileName The name of the file. May be <code>null</code>,
|
|
||||||
* in which case the location is equivalent to
|
|
||||||
* {@link #UNKNOWN_LOCATION UNKNOWN_LOCATION}.
|
|
||||||
*
|
|
||||||
* @param lineNumber Line number within the file. Use 0 for unknown
|
|
||||||
* positions within a file.
|
|
||||||
* @param columnNumber Column number within the line.
|
|
||||||
*/
|
|
||||||
public Location(String fileName, int lineNumber, int columnNumber) {
|
|
||||||
if (fileName != null && fileName.startsWith("file:")) {
|
|
||||||
this.fileName = FILE_UTILS.fromURI(fileName);
|
|
||||||
} else {
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
this.lineNumber = lineNumber;
|
|
||||||
this.columnNumber = columnNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the filename portion of the location
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public String getFileName() {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the line number
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public int getLineNumber() {
|
|
||||||
return lineNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the column number
|
|
||||||
* @since Ant 1.7
|
|
||||||
*/
|
|
||||||
public int getColumnNumber() {
|
|
||||||
return columnNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the file name, line number, a colon and a trailing space.
|
|
||||||
* An error message can be appended easily. For unknown locations, an
|
|
||||||
* empty string is returned.
|
|
||||||
*
|
|
||||||
* @return a String of the form <code>"fileName:lineNumber: "</code>
|
|
||||||
* if both file name and line number are known,
|
|
||||||
* <code>"fileName: "</code> if only the file name is known,
|
|
||||||
* and the empty string for unknown locations.
|
|
||||||
*/
|
|
||||||
public String toString() {
|
|
||||||
final StringBuilder buf = new StringBuilder();
|
|
||||||
|
|
||||||
if (fileName != null) {
|
|
||||||
buf.append(fileName);
|
|
||||||
|
|
||||||
if (lineNumber != 0) {
|
|
||||||
buf.append(':').append(lineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.append(": ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Equality operation.
|
|
||||||
* @param other the object to compare to.
|
|
||||||
* @return true if the other object contains the same information
|
|
||||||
* as this object.
|
|
||||||
* @since Ant 1.6.3
|
|
||||||
*/
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (this == other) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (other == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(other.getClass() == getClass())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return toString().equals(other.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash operation.
|
|
||||||
* @return a hash code value for this location.
|
|
||||||
* @since Ant 1.6.3
|
|
||||||
*/
|
|
||||||
public int hashCode() {
|
|
||||||
return toString().hashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,530 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.owasp.dependencycheck.org.apache.tools.ant.launch;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.text.CharacterIterator;
|
|
||||||
import java.text.StringCharacterIterator;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
|
|
||||||
|
|
||||||
// CheckStyle:LineLengthCheck OFF - urls are long!
|
|
||||||
/**
|
|
||||||
* The Locator is a utility class which is used to find certain items
|
|
||||||
* in the environment.
|
|
||||||
*
|
|
||||||
* It is used at boot time in the launcher, and cannot make use of any of Ant's other classes.
|
|
||||||
*
|
|
||||||
* This is a surprisingly brittle piece of code, and has had lots of bugs filed against it.
|
|
||||||
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42275">running ant off a network share can cause Ant to fail</a>}
|
|
||||||
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=8031">use File.toURI().toURL().toExternalForm()</a>}
|
|
||||||
* {@link <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=42222">Locator implementation not encoding URI strings properly: spaces in paths</a>}
|
|
||||||
* It also breaks Eclipse 3.3 Betas
|
|
||||||
* {@link <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=183283">Exception if installation path has spaces</a>}
|
|
||||||
*
|
|
||||||
* Be very careful when making changes to this class, as a break will upset a lot of people.
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
// CheckStyle:LineLengthCheck ON - urls are long!
|
|
||||||
public final class Locator {
|
|
||||||
|
|
||||||
private static final int NIBBLE = 4;
|
|
||||||
private static final int NIBBLE_MASK = 0xF;
|
|
||||||
|
|
||||||
private static final int ASCII_SIZE = 128;
|
|
||||||
|
|
||||||
private static final int BYTE_SIZE = 256;
|
|
||||||
|
|
||||||
private static final int WORD = 16;
|
|
||||||
|
|
||||||
private static final int SPACE = 0x20;
|
|
||||||
private static final int DEL = 0x7F;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* encoding used to represent URIs
|
|
||||||
*/
|
|
||||||
public static final String URI_ENCODING = "UTF-8";
|
|
||||||
// stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir()
|
|
||||||
// of the Xerces-J team
|
|
||||||
// which ASCII characters need to be escaped
|
|
||||||
private static boolean[] gNeedEscaping = new boolean[ASCII_SIZE];
|
|
||||||
// the first hex character if a character needs to be escaped
|
|
||||||
private static char[] gAfterEscaping1 = new char[ASCII_SIZE];
|
|
||||||
// the second hex character if a character needs to be escaped
|
|
||||||
private static char[] gAfterEscaping2 = new char[ASCII_SIZE];
|
|
||||||
private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
|
||||||
/** Error string used when an invalid uri is seen */
|
|
||||||
public static final String ERROR_NOT_FILE_URI
|
|
||||||
= "Can only handle valid file: URIs, not ";
|
|
||||||
|
|
||||||
// initialize the above 3 arrays
|
|
||||||
static {
|
|
||||||
for (int i = 0; i < SPACE; i++) {
|
|
||||||
gNeedEscaping[i] = true;
|
|
||||||
gAfterEscaping1[i] = gHexChs[i >> NIBBLE];
|
|
||||||
gAfterEscaping2[i] = gHexChs[i & NIBBLE_MASK];
|
|
||||||
}
|
|
||||||
gNeedEscaping[DEL] = true;
|
|
||||||
gAfterEscaping1[DEL] = '7';
|
|
||||||
gAfterEscaping2[DEL] = 'F';
|
|
||||||
char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
|
|
||||||
'|', '\\', '^', '~', '[', ']', '`'};
|
|
||||||
int len = escChs.length;
|
|
||||||
char ch;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
ch = escChs[i];
|
|
||||||
gNeedEscaping[ch] = true;
|
|
||||||
gAfterEscaping1[ch] = gHexChs[ch >> NIBBLE];
|
|
||||||
gAfterEscaping2[ch] = gHexChs[ch & NIBBLE_MASK];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Not instantiable
|
|
||||||
*/
|
|
||||||
private Locator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the directory or jar file the class has been loaded from.
|
|
||||||
*
|
|
||||||
* @param c the class whose location is required.
|
|
||||||
* @return the file or jar with the class or null if we cannot
|
|
||||||
* determine the location.
|
|
||||||
*
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public static File getClassSource(Class<?> c) {
|
|
||||||
String classResource = c.getName().replace('.', '/') + ".class";
|
|
||||||
return getResourceSource(c.getClassLoader(), classResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the directory or jar a given resource has been loaded from.
|
|
||||||
*
|
|
||||||
* @param c the classloader to be consulted for the source.
|
|
||||||
* @param resource the resource whose location is required.
|
|
||||||
*
|
|
||||||
* @return the file with the resource source or null if
|
|
||||||
* we cannot determine the location.
|
|
||||||
*
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public static File getResourceSource(ClassLoader c, String resource) {
|
|
||||||
if (c == null) {
|
|
||||||
c = Locator.class.getClassLoader();
|
|
||||||
}
|
|
||||||
URL url = null;
|
|
||||||
if (c == null) {
|
|
||||||
url = ClassLoader.getSystemResource(resource);
|
|
||||||
} else {
|
|
||||||
url = c.getResource(resource);
|
|
||||||
}
|
|
||||||
if (url != null) {
|
|
||||||
String u = url.toString();
|
|
||||||
try {
|
|
||||||
if (u.startsWith("jar:file:")) {
|
|
||||||
return new File(fromJarURI(u));
|
|
||||||
} else if (u.startsWith("file:")) {
|
|
||||||
int tail = u.indexOf(resource);
|
|
||||||
String dirName = u.substring(0, tail);
|
|
||||||
return new File(fromURI(dirName));
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
//unable to determine the URI for reasons unknown.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a file path from a <code>file:</code> URI.
|
|
||||||
*
|
|
||||||
* <p>Will be an absolute path if the given URI is absolute.</p>
|
|
||||||
*
|
|
||||||
* <p>Prior to Java 1.4,<!-- TODO is JDK version actually relevant? -->
|
|
||||||
* swallows '%' that are not followed by two characters.</p>
|
|
||||||
*
|
|
||||||
* See <a href="http://www.w3.org/TR/xml11/#dt-sysid">dt-sysid</a>
|
|
||||||
* which makes some mention of how
|
|
||||||
* characters not supported by URI Reference syntax should be escaped.
|
|
||||||
*
|
|
||||||
* @param uri the URI designating a file in the local filesystem.
|
|
||||||
* @return the local file system path for the file.
|
|
||||||
* @throws IllegalArgumentException if the URI is malformed or not a legal file: URL
|
|
||||||
* @since Ant 1.6
|
|
||||||
*/
|
|
||||||
public static String fromURI(String uri) {
|
|
||||||
return fromURIJava13(uri);
|
|
||||||
// #buzilla8031: first try Java 1.4.
|
|
||||||
// TODO should use java.net.URI now that we can rely on 1.4...
|
|
||||||
// but check for UNC-related regressions, e.g. #42275
|
|
||||||
// (and remember that \\server\share\file -> file:////server/share/file
|
|
||||||
// rather than -> file://server/share/file as it should;
|
|
||||||
// fixed only in JDK 7's java.nio.file.Path.toUri)
|
|
||||||
// return fromUriJava14(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Java1.4+ code to extract the path from the URI.
|
|
||||||
* @param uri
|
|
||||||
* @return null if a conversion was not possible
|
|
||||||
*/
|
|
||||||
/* currently unused:
|
|
||||||
private static String fromUriJava14(String uri) {
|
|
||||||
// Also check for properly formed URIs. Ant formerly recommended using
|
|
||||||
// nonsense URIs such as "file:./foo.xml" in XML includes. You shouldn't
|
|
||||||
// do that (just "foo.xml" is correct) but for compatibility we special-case
|
|
||||||
// things when the path is not absolute, and fall back to the old parsing behavior.
|
|
||||||
if (uri.startsWith("file:/")) {
|
|
||||||
try {
|
|
||||||
File f = new File(URI.create(encodeURI(uri)));
|
|
||||||
//bug #42227 forgot to decode before returning
|
|
||||||
return decodeUri(f.getAbsolutePath());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// Bad URI, pass this on.
|
|
||||||
// no, this is downgraded to a warning after various
|
|
||||||
// JRE bugs surfaced. Hand off
|
|
||||||
// to our built in code on a failure
|
|
||||||
//throw new IllegalArgumentException(
|
|
||||||
// "Bad URI " + uri + ":" + e.getMessage(), e);
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Unexpected exception? Should not happen.
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param uri uri to expand
|
|
||||||
* @return the decoded URI
|
|
||||||
* @since Ant1.7.1
|
|
||||||
*/
|
|
||||||
private static String fromURIJava13(String uri) {
|
|
||||||
// Fallback method for Java 1.3 or earlier.
|
|
||||||
|
|
||||||
URL url = null;
|
|
||||||
try {
|
|
||||||
url = new URL(uri);
|
|
||||||
} catch (MalformedURLException emYouEarlEx) {
|
|
||||||
// Ignore malformed exception
|
|
||||||
}
|
|
||||||
if (url == null || !("file".equals(url.getProtocol()))) {
|
|
||||||
throw new IllegalArgumentException(ERROR_NOT_FILE_URI + uri);
|
|
||||||
}
|
|
||||||
final StringBuilder buf = new StringBuilder(url.getHost());
|
|
||||||
if (buf.length() > 0) {
|
|
||||||
buf.insert(0, File.separatorChar).insert(0, File.separatorChar);
|
|
||||||
}
|
|
||||||
String file = url.getFile();
|
|
||||||
int queryPos = file.indexOf('?');
|
|
||||||
buf.append((queryPos < 0) ? file : file.substring(0, queryPos));
|
|
||||||
|
|
||||||
uri = buf.toString().replace('/', File.separatorChar);
|
|
||||||
|
|
||||||
if (File.pathSeparatorChar == ';' && uri.startsWith("\\") && uri.length() > 2
|
|
||||||
&& Character.isLetter(uri.charAt(1)) && uri.lastIndexOf(':') > -1) {
|
|
||||||
uri = uri.substring(1);
|
|
||||||
}
|
|
||||||
String path = null;
|
|
||||||
try {
|
|
||||||
path = decodeUri(uri);
|
|
||||||
//consider adding the current directory. This is not done when
|
|
||||||
//the path is a UNC name
|
|
||||||
String cwd = System.getProperty("user.dir");
|
|
||||||
int posi = cwd.indexOf(':');
|
|
||||||
boolean pathStartsWithFileSeparator = path.startsWith(File.separator);
|
|
||||||
boolean pathStartsWithUNC = path.startsWith("" + File.separator + File.separator);
|
|
||||||
if ((posi > 0) && pathStartsWithFileSeparator && !pathStartsWithUNC) {
|
|
||||||
path = cwd.substring(0, posi + 1) + path;
|
|
||||||
}
|
|
||||||
} catch (UnsupportedEncodingException exc) {
|
|
||||||
// not sure whether this is clean, but this method is
|
|
||||||
// declared not to throw exceptions.
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Could not convert URI " + uri + " to path: "
|
|
||||||
+ exc.getMessage());
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crack a JAR URI.
|
|
||||||
* This method is public for testing; we may delete it without any warning -it is not part of Ant's stable API.
|
|
||||||
* @param uri uri to expand; contains jar: somewhere in it
|
|
||||||
* @return the decoded URI
|
|
||||||
* @since Ant1.7.1
|
|
||||||
*/
|
|
||||||
public static String fromJarURI(String uri) {
|
|
||||||
int pling = uri.indexOf("!/");
|
|
||||||
String jarName = uri.substring("jar:".length(), pling);
|
|
||||||
return fromURI(jarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes an Uri with % characters.
|
|
||||||
* The URI is escaped
|
|
||||||
* @param uri String with the uri possibly containing % characters.
|
|
||||||
* @return The decoded Uri
|
|
||||||
* @throws UnsupportedEncodingException if UTF-8 is not available
|
|
||||||
* @since Ant 1.7
|
|
||||||
*/
|
|
||||||
public static String decodeUri(String uri) throws UnsupportedEncodingException {
|
|
||||||
if (uri.indexOf('%') == -1) {
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
ByteArrayOutputStream sb = new ByteArrayOutputStream(uri.length());
|
|
||||||
CharacterIterator iter = new StringCharacterIterator(uri);
|
|
||||||
for (char c = iter.first(); c != CharacterIterator.DONE;
|
|
||||||
c = iter.next()) {
|
|
||||||
if (c == '%') {
|
|
||||||
char c1 = iter.next();
|
|
||||||
if (c1 != CharacterIterator.DONE) {
|
|
||||||
int i1 = Character.digit(c1, WORD);
|
|
||||||
char c2 = iter.next();
|
|
||||||
if (c2 != CharacterIterator.DONE) {
|
|
||||||
int i2 = Character.digit(c2, WORD);
|
|
||||||
sb.write((char) ((i1 << NIBBLE) + i2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (c >= 0x0000 && c < 0x0080) {
|
|
||||||
sb.write(c);
|
|
||||||
} else { // #50543
|
|
||||||
byte[] bytes = String.valueOf(c).getBytes(URI_ENCODING);
|
|
||||||
sb.write(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString(URI_ENCODING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes an Uri with % characters.
|
|
||||||
* The URI is escaped
|
|
||||||
* @param path String to encode.
|
|
||||||
* @return The encoded string, according to URI norms
|
|
||||||
* @throws UnsupportedEncodingException if UTF-8 is not available
|
|
||||||
* @since Ant 1.7
|
|
||||||
*/
|
|
||||||
public static String encodeURI(String path) throws UnsupportedEncodingException {
|
|
||||||
int i = 0;
|
|
||||||
int len = path.length();
|
|
||||||
int ch = 0;
|
|
||||||
StringBuilder sb = null;
|
|
||||||
for (; i < len; i++) {
|
|
||||||
ch = path.charAt(i);
|
|
||||||
// if it's not an ASCII character, break here, and use UTF-8 encoding
|
|
||||||
if (ch >= ASCII_SIZE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (gNeedEscaping[ch]) {
|
|
||||||
if (sb == null) {
|
|
||||||
sb = new StringBuilder(path.substring(0, i));
|
|
||||||
}
|
|
||||||
sb.append('%');
|
|
||||||
sb.append(gAfterEscaping1[ch]);
|
|
||||||
sb.append(gAfterEscaping2[ch]);
|
|
||||||
// record the fact that it's escaped
|
|
||||||
} else if (sb != null) {
|
|
||||||
sb.append((char) ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we saw some non-ascii character
|
|
||||||
if (i < len) {
|
|
||||||
if (sb == null) {
|
|
||||||
sb = new StringBuilder(path.substring(0, i));
|
|
||||||
}
|
|
||||||
// get UTF-8 bytes for the remaining sub-string
|
|
||||||
byte[] bytes = null;
|
|
||||||
byte b;
|
|
||||||
bytes = path.substring(i).getBytes(URI_ENCODING);
|
|
||||||
len = bytes.length;
|
|
||||||
|
|
||||||
// for each byte
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
b = bytes[i];
|
|
||||||
// for non-ascii character: make it positive, then escape
|
|
||||||
if (b < 0) {
|
|
||||||
ch = b + BYTE_SIZE;
|
|
||||||
sb.append('%');
|
|
||||||
sb.append(gHexChs[ch >> NIBBLE]);
|
|
||||||
sb.append(gHexChs[ch & NIBBLE_MASK]);
|
|
||||||
} else if (gNeedEscaping[b]) {
|
|
||||||
sb.append('%');
|
|
||||||
sb.append(gAfterEscaping1[b]);
|
|
||||||
sb.append(gAfterEscaping2[b]);
|
|
||||||
} else {
|
|
||||||
sb.append((char) b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb == null ? path : sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a File to a URL.
|
|
||||||
* File.toURL() does not encode characters like #.
|
|
||||||
* File.toURI() has been introduced in java 1.4, so
|
|
||||||
* Ant cannot use it (except by reflection) <!-- TODO no longer true -->
|
|
||||||
* FileUtils.toURI() cannot be used by Locator.java
|
|
||||||
* Implemented this way.
|
|
||||||
* File.toURL() adds file: and changes '\' to '/' for dos OSes
|
|
||||||
* encodeURI converts characters like ' ' and '#' to %DD
|
|
||||||
* @param file the file to convert
|
|
||||||
* @return URL the converted File
|
|
||||||
* @throws MalformedURLException on error
|
|
||||||
* @deprecated since 1.9, use {@link FileUtils#getFileURL(File)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static URL fileToURL(File file)
|
|
||||||
throws MalformedURLException {
|
|
||||||
return new URL(file.toURI().toASCIIString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the File necessary to load the Sun compiler tools. If the classes
|
|
||||||
* are available to this class, then no additional URL is required and
|
|
||||||
* null is returned. This may be because the classes are explicitly in the
|
|
||||||
* class path or provided by the JVM directly.
|
|
||||||
*
|
|
||||||
* @return the tools jar as a File if required, null otherwise.
|
|
||||||
*/
|
|
||||||
public static File getToolsJar() {
|
|
||||||
// firstly check if the tools jar is already in the classpath
|
|
||||||
boolean toolsJarAvailable = false;
|
|
||||||
try {
|
|
||||||
// just check whether this throws an exception
|
|
||||||
Class.forName("com.sun.tools.javac.Main");
|
|
||||||
toolsJarAvailable = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
Class.forName("sun.tools.javac.Main");
|
|
||||||
toolsJarAvailable = true;
|
|
||||||
} catch (Exception e2) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toolsJarAvailable) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// couldn't find compiler - try to find tools.jar
|
|
||||||
// based on java.home setting
|
|
||||||
String libToolsJar
|
|
||||||
= File.separator + "lib" + File.separator + "tools.jar";
|
|
||||||
String javaHome = System.getProperty("java.home");
|
|
||||||
File toolsJar = new File(javaHome + libToolsJar);
|
|
||||||
if (toolsJar.exists()) {
|
|
||||||
// Found in java.home as given
|
|
||||||
return toolsJar;
|
|
||||||
}
|
|
||||||
if (javaHome.toLowerCase(Locale.ENGLISH).endsWith(File.separator + "jre")) {
|
|
||||||
javaHome = javaHome.substring(
|
|
||||||
0, javaHome.length() - "/jre".length());
|
|
||||||
toolsJar = new File(javaHome + libToolsJar);
|
|
||||||
}
|
|
||||||
if (!toolsJar.exists()) {
|
|
||||||
System.out.println("Unable to locate tools.jar. "
|
|
||||||
+ "Expected to find it in " + toolsJar.getPath());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return toolsJar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an array of URLs representing all of the jar files in the
|
|
||||||
* given location. If the location is a file, it is returned as the only
|
|
||||||
* element of the array. If the location is a directory, it is scanned for
|
|
||||||
* jar files.
|
|
||||||
*
|
|
||||||
* @param location the location to scan for Jars.
|
|
||||||
*
|
|
||||||
* @return an array of URLs for all jars in the given location.
|
|
||||||
*
|
|
||||||
* @exception MalformedURLException if the URLs for the jars cannot be
|
|
||||||
* formed.
|
|
||||||
*/
|
|
||||||
public static URL[] getLocationURLs(File location)
|
|
||||||
throws MalformedURLException {
|
|
||||||
return getLocationURLs(location, new String[]{".jar"});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an array of URLs representing all of the files of a given set of
|
|
||||||
* extensions in the given location. If the location is a file, it is
|
|
||||||
* returned as the only element of the array. If the location is a
|
|
||||||
* directory, it is scanned for matching files.
|
|
||||||
*
|
|
||||||
* @param location the location to scan for files.
|
|
||||||
* @param extensions an array of extension that are to match in the
|
|
||||||
* directory search.
|
|
||||||
*
|
|
||||||
* @return an array of URLs of matching files.
|
|
||||||
* @exception MalformedURLException if the URLs for the files cannot be
|
|
||||||
* formed.
|
|
||||||
*/
|
|
||||||
public static URL[] getLocationURLs(File location,
|
|
||||||
final String[] extensions)
|
|
||||||
throws MalformedURLException {
|
|
||||||
URL[] urls = new URL[0];
|
|
||||||
|
|
||||||
if (!location.exists()) {
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
if (!location.isDirectory()) {
|
|
||||||
urls = new URL[1];
|
|
||||||
String path = location.getPath();
|
|
||||||
String littlePath = path.toLowerCase(Locale.ENGLISH);
|
|
||||||
for (int i = 0; i < extensions.length; ++i) {
|
|
||||||
if (littlePath.endsWith(extensions[i])) {
|
|
||||||
urls[0] = fileToURL(location);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
File[] matches = location.listFiles(
|
|
||||||
new FilenameFilter() {
|
|
||||||
public boolean accept(File dir, String name) {
|
|
||||||
String littleName = name.toLowerCase(Locale.ENGLISH);
|
|
||||||
for (int i = 0; i < extensions.length; ++i) {
|
|
||||||
if (littleName.endsWith(extensions[i])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
urls = new URL[matches.length];
|
|
||||||
for (int i = 0; i < matches.length; ++i) {
|
|
||||||
urls[i] = fileToURL(matches[i]);
|
|
||||||
}
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,695 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.owasp.dependencycheck.org.apache.tools.ant.types.selectors;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.owasp.dependencycheck.org.apache.tools.ant.types.Resource;
|
|
||||||
import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>This is a utility class used by selectors and DirectoryScanner. The
|
|
||||||
* functionality more properly belongs just to selectors, but unfortunately
|
|
||||||
* DirectoryScanner exposed these as protected methods. Thus we have to
|
|
||||||
* support any subclasses of DirectoryScanner that may access these methods.
|
|
||||||
* </p>
|
|
||||||
* <p>This is a Singleton.</p>
|
|
||||||
*
|
|
||||||
* @since 1.5
|
|
||||||
*/
|
|
||||||
public final class SelectorUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pattern that matches an arbitrary number of directories.
|
|
||||||
* @since Ant 1.8.0
|
|
||||||
*/
|
|
||||||
public static final String DEEP_TREE_MATCH = "**";
|
|
||||||
|
|
||||||
private static final SelectorUtils instance = new SelectorUtils();
|
|
||||||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private Constructor
|
|
||||||
*/
|
|
||||||
private SelectorUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the instance of the Singleton.
|
|
||||||
* @return singleton instance
|
|
||||||
*/
|
|
||||||
public static SelectorUtils getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
* <p>
|
|
||||||
* This is not a general purpose test and should only be used if you
|
|
||||||
* can live with false positives. For example, <code>pattern=**\a</code>
|
|
||||||
* and <code>str=b</code> will yield <code>true</code>.
|
|
||||||
*
|
|
||||||
* @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 whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
*/
|
|
||||||
public static boolean matchPatternStart(String pattern, String str) {
|
|
||||||
return matchPatternStart(pattern, str, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
* <p>
|
|
||||||
* This is not a general purpose test and should only be used if you
|
|
||||||
* can live with false positives. For example, <code>pattern=**\a</code>
|
|
||||||
* and <code>str=b</code> will yield <code>true</code>.
|
|
||||||
*
|
|
||||||
* @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 whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
*/
|
|
||||||
public static boolean matchPatternStart(String pattern, String str,
|
|
||||||
boolean isCaseSensitive) {
|
|
||||||
// When str starts with a File.separator, pattern has to start with a
|
|
||||||
// File.separator.
|
|
||||||
// When pattern starts with a File.separator, str has to start with a
|
|
||||||
// File.separator.
|
|
||||||
if (str.startsWith(File.separator)
|
|
||||||
!= pattern.startsWith(File.separator)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] patDirs = tokenizePathAsArray(pattern);
|
|
||||||
String[] strDirs = tokenizePathAsArray(str);
|
|
||||||
return matchPatternStart(patDirs, strDirs, isCaseSensitive);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
* <p>
|
|
||||||
* This is not a general purpose test and should only be used if you
|
|
||||||
* can live with false positives. For example, <code>pattern=**\a</code>
|
|
||||||
* and <code>str=b</code> will yield <code>true</code>.
|
|
||||||
*
|
|
||||||
* @param patDirs The tokenized pattern to match against. Must not be
|
|
||||||
* <code>null</code>.
|
|
||||||
* @param strDirs The tokenized path to match. Must not be
|
|
||||||
* <code>null</code>.
|
|
||||||
* @param isCaseSensitive Whether or not matching should be performed
|
|
||||||
* case sensitively.
|
|
||||||
*
|
|
||||||
* @return whether or not a given path matches the start of a given
|
|
||||||
* pattern up to the first "**".
|
|
||||||
*/
|
|
||||||
static boolean matchPatternStart(String[] patDirs, String[] strDirs,
|
|
||||||
boolean isCaseSensitive) {
|
|
||||||
int patIdxStart = 0;
|
|
||||||
int patIdxEnd = patDirs.length - 1;
|
|
||||||
int strIdxStart = 0;
|
|
||||||
int strIdxEnd = strDirs.length - 1;
|
|
||||||
|
|
||||||
// up to first '**'
|
|
||||||
while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
|
|
||||||
String patDir = patDirs[patIdxStart];
|
|
||||||
if (patDir.equals(DEEP_TREE_MATCH)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
patIdxStart++;
|
|
||||||
strIdxStart++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckStyle:SimplifyBooleanReturnCheck OFF
|
|
||||||
// Check turned off as the code needs the comments for the various
|
|
||||||
// code paths.
|
|
||||||
if (strIdxStart > strIdxEnd) {
|
|
||||||
// String is exhausted
|
|
||||||
return true;
|
|
||||||
} else if (patIdxStart > patIdxEnd) {
|
|
||||||
// String not exhausted, but pattern is. Failure.
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// pattern now holds ** while string is not exhausted
|
|
||||||
// this will generate false positives but we can live with that.
|
|
||||||
return 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 TokenizedPath
|
|
||||||
*
|
|
||||||
* @see 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);
|
|
||||||
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
|
|
||||||
*
|
|
||||||
* @see 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);
|
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
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 (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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>.
|
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
boolean containsStar = false;
|
|
||||||
for (int i = 0; i < patArr.length; i++) {
|
|
||||||
if (patArr[i] == '*') {
|
|
||||||
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++) {
|
|
||||||
ch = patArr[i];
|
|
||||||
if (ch != '?') {
|
|
||||||
if (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) {
|
|
||||||
ch = patArr[patIdxStart];
|
|
||||||
if (ch == '*' || strIdxStart > strIdxEnd) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ch != '?') {
|
|
||||||
if (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) {
|
|
||||||
ch = patArr[patIdxEnd];
|
|
||||||
if (ch == '*' || strIdxStart > strIdxEnd) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ch != '?') {
|
|
||||||
if (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++) {
|
|
||||||
ch = patArr[patIdxStart + j + 1];
|
|
||||||
if (ch != '?') {
|
|
||||||
if (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
|
|
||||||
* <code>File.separator</code>.
|
|
||||||
*
|
|
||||||
* @param path Path to tokenize. Must not be <code>null</code>.
|
|
||||||
*
|
|
||||||
* @return a Vector of path elements from the tokenized path
|
|
||||||
*/
|
|
||||||
public static Vector<String> tokenizePath(String path) {
|
|
||||||
return tokenizePath(path, File.separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Breaks a path up into a Vector of path elements, tokenizing on
|
|
||||||
*
|
|
||||||
* @param path Path to tokenize. Must not be <code>null</code>.
|
|
||||||
* @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<String> tokenizePath(String path, String separator) {
|
|
||||||
Vector<String> ret = new Vector<String>();
|
|
||||||
if (FileUtils.isAbsolutePath(path)) {
|
|
||||||
String[] s = FILE_UTILS.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 (FileUtils.isAbsolutePath(path)) {
|
|
||||||
String[] s = FILE_UTILS.dissect(path);
|
|
||||||
root = s[0];
|
|
||||||
path = s[1];
|
|
||||||
}
|
|
||||||
char sep = 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;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns dependency information on these two files. If src has been
|
|
||||||
* modified later than target, it returns true. If target doesn't exist,
|
|
||||||
* it likewise returns true. Otherwise, target is newer than src and
|
|
||||||
* is not out of date, thus the method returns false. It also returns
|
|
||||||
* false if the src file doesn't even exist, since how could the
|
|
||||||
* target then be out of date.
|
|
||||||
*
|
|
||||||
* @param src the original file
|
|
||||||
* @param target the file being compared against
|
|
||||||
* @param granularity the amount in seconds of slack we will give in
|
|
||||||
* determining out of dateness
|
|
||||||
* @return whether the target is out of date
|
|
||||||
*/
|
|
||||||
public static boolean isOutOfDate(File src, File target, int granularity) {
|
|
||||||
if (!src.exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!target.exists()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((src.lastModified() - granularity) > target.lastModified()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns dependency information on these two resources. If src has been
|
|
||||||
* modified later than target, it returns true. If target doesn't exist,
|
|
||||||
* it likewise returns true. Otherwise, target is newer than src and
|
|
||||||
* is not out of date, thus the method returns false. It also returns
|
|
||||||
* false if the src file doesn't even exist, since how could the
|
|
||||||
* target then be out of date.
|
|
||||||
*
|
|
||||||
* @param src the original resource
|
|
||||||
* @param target the resource being compared against
|
|
||||||
* @param granularity the int amount in seconds of slack we will give in
|
|
||||||
* determining out of dateness
|
|
||||||
* @return whether the target is out of date
|
|
||||||
*/
|
|
||||||
public static boolean isOutOfDate(Resource src, Resource target,
|
|
||||||
int granularity) {
|
|
||||||
return isOutOfDate(src, target, (long) granularity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns dependency information on these two resources. If src has been
|
|
||||||
* modified later than target, it returns true. If target doesn't exist,
|
|
||||||
* it likewise returns true. Otherwise, target is newer than src and
|
|
||||||
* is not out of date, thus the method returns false. It also returns
|
|
||||||
* false if the src file doesn't even exist, since how could the
|
|
||||||
* target then be out of date.
|
|
||||||
*
|
|
||||||
* @param src the original resource
|
|
||||||
* @param target the resource being compared against
|
|
||||||
* @param granularity the long amount in seconds of slack we will give in
|
|
||||||
* determining out of dateness
|
|
||||||
* @return whether the target is out of date
|
|
||||||
*/
|
|
||||||
public static boolean isOutOfDate(Resource src, Resource target, long granularity) {
|
|
||||||
long sourceLastModified = src.getLastModified();
|
|
||||||
long targetLastModified = target.getLastModified();
|
|
||||||
return src.isExists()
|
|
||||||
&& (sourceLastModified == Resource.UNKNOWN_DATETIME
|
|
||||||
|| targetLastModified == Resource.UNKNOWN_DATETIME
|
|
||||||
|| (sourceLastModified - granularity) > targetLastModified);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "Flattens" a string by removing all whitespace (space, tab, linefeed,
|
|
||||||
* carriage return, and formfeed). This uses StringTokenizer and the
|
|
||||||
* default set of tokens as documented in the single argument constructor.
|
|
||||||
*
|
|
||||||
* @param input a String to remove all whitespace.
|
|
||||||
* @return a String that has had all whitespace removed.
|
|
||||||
*/
|
|
||||||
public static String removeWhitespace(String input) {
|
|
||||||
final StringBuilder result = new StringBuilder();
|
|
||||||
if (input != null) {
|
|
||||||
final StringTokenizer st = new StringTokenizer(input);
|
|
||||||
while (st.hasMoreTokens()) {
|
|
||||||
result.append(st.nextToken());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if a string contains stars or question marks
|
|
||||||
* @param input a String which one wants to test for containing wildcard
|
|
||||||
* @return true if the string contains at least a star or a question mark
|
|
||||||
*/
|
|
||||||
public static boolean hasWildcards(String input) {
|
|
||||||
return (input.indexOf('*') != -1 || input.indexOf('?') != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* removes from a pattern all tokens to the right containing wildcards
|
|
||||||
* @param input the input string
|
|
||||||
* @return the leftmost part of the pattern without wildcards
|
|
||||||
*/
|
|
||||||
public static String rtrimWildcardTokens(String input) {
|
|
||||||
return new TokenizedPattern(input).rtrimWildcardTokens().toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user