mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-15 00:03:43 +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.
|
||||
*/
|
||||
private StringBuffer currentText;
|
||||
private StringBuilder currentText;
|
||||
|
||||
/**
|
||||
* Handles the start element event.
|
||||
@@ -100,7 +100,7 @@ public class SuppressionHandler extends DefaultHandler {
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
currentAttributes = attributes;
|
||||
currentText = new StringBuffer();
|
||||
currentText = new StringBuilder();
|
||||
if (SUPPRESS.equals(qName)) {
|
||||
rule = new SuppressionRule();
|
||||
final String base = currentAttributes.getValue("base");
|
||||
|
||||
@@ -100,7 +100,7 @@ public class PomHandler extends DefaultHandler {
|
||||
/**
|
||||
* The current node text being extracted from the element.
|
||||
*/
|
||||
private StringBuffer currentText;
|
||||
private StringBuilder currentText;
|
||||
|
||||
/**
|
||||
* Handles the start element event.
|
||||
@@ -113,7 +113,7 @@ public class PomHandler extends DefaultHandler {
|
||||
*/
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
currentText = new StringBuffer();
|
||||
currentText = new StringBuilder();
|
||||
stack.push(qName);
|
||||
if (LICENSE.equals(qName)) {
|
||||
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.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user