mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-24 18:11:47 +01:00
Merge branch 'awhitford-StringB'
This commit is contained in:
@@ -86,7 +86,7 @@ public class SuppressionHandler extends DefaultHandler {
|
|||||||
/**
|
/**
|
||||||
* The current node text being extracted from the element.
|
* The current node text being extracted from the element.
|
||||||
*/
|
*/
|
||||||
private StringBuffer currentText;
|
private StringBuilder currentText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the start element event.
|
* Handles the start element event.
|
||||||
@@ -100,7 +100,7 @@ public class SuppressionHandler extends DefaultHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
currentAttributes = attributes;
|
currentAttributes = attributes;
|
||||||
currentText = new StringBuffer();
|
currentText = new StringBuilder();
|
||||||
if (SUPPRESS.equals(qName)) {
|
if (SUPPRESS.equals(qName)) {
|
||||||
rule = new SuppressionRule();
|
rule = new SuppressionRule();
|
||||||
final String base = currentAttributes.getValue("base");
|
final String base = currentAttributes.getValue("base");
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class PomHandler extends DefaultHandler {
|
|||||||
/**
|
/**
|
||||||
* The current node text being extracted from the element.
|
* The current node text being extracted from the element.
|
||||||
*/
|
*/
|
||||||
private StringBuffer currentText;
|
private StringBuilder currentText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the start element event.
|
* Handles the start element event.
|
||||||
@@ -113,7 +113,7 @@ public class PomHandler extends DefaultHandler {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
currentText = new StringBuffer();
|
currentText = new StringBuilder();
|
||||||
stack.push(qName);
|
stack.push(qName);
|
||||||
if (LICENSE.equals(qName)) {
|
if (LICENSE.equals(qName)) {
|
||||||
license = new License();
|
license = new License();
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,530 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,695 @@
|
|||||||
|
/*
|
||||||
|
* 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
@@ -22,8 +22,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user