diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/Location.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/Location.java deleted file mode 100644 index 7015cdcc6..000000000 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/Location.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.owasp.dependencycheck.org.apache.tools.ant; - -import java.io.Serializable; -import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils; -import org.xml.sax.Locator; - -/** - * Stores the location of a piece of text within a file (file name, - * line number and column number). Note that the column number is - * currently ignored. - * - */ -public class Location implements Serializable { - private static final long serialVersionUID = 1L; - - /** Name of the file. */ - private final String fileName; - /** Line number within the file. */ - private final int lineNumber; - /** Column number within the file. */ - private final int columnNumber; - - /** Location to use when one is needed but no information is available */ - public static final Location UNKNOWN_LOCATION = new Location(); - - private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); - - /** - * Creates an "unknown" location. - */ - private Location() { - this(null, 0, 0); - } - - /** - * Creates a location consisting of a file name but no line number or - * column number. - * - * @param fileName The name of the file. May be null, - * 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 null. - * - * @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 null, - * 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 "fileName:lineNumber: " - * if both file name and line number are known, - * "fileName: " 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(); - } -} diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/launch/Locator.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/launch/Locator.java deleted file mode 100644 index e4f91baea..000000000 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/launch/Locator.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.owasp.dependencycheck.org.apache.tools.ant.launch; - -import java.net.MalformedURLException; -import java.net.URL; -import java.io.File; -import java.io.FilenameFilter; -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.text.CharacterIterator; -import java.text.StringCharacterIterator; -import java.util.Locale; - -import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils; - -// CheckStyle:LineLengthCheck OFF - urls are long! -/** - * The Locator is a utility class which is used to find certain items - * in the environment. - * - * It is used at boot time in the launcher, and cannot make use of any of Ant's other classes. - * - * This is a surprisingly brittle piece of code, and has had lots of bugs filed against it. - * {@link running ant off a network share can cause Ant to fail} - * {@link use File.toURI().toURL().toExternalForm()} - * {@link Locator implementation not encoding URI strings properly: spaces in paths} - * It also breaks Eclipse 3.3 Betas - * {@link Exception if installation path has spaces} - * - * 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 file: URI. - * - *

Will be an absolute path if the given URI is absolute.

- * - *

Prior to Java 1.4, - * swallows '%' that are not followed by two characters.

- * - * See dt-sysid - * 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) - * 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; - } -} diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/types/selectors/SelectorUtils.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/types/selectors/SelectorUtils.java deleted file mode 100644 index 7f37eda43..000000000 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/types/selectors/SelectorUtils.java +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.owasp.dependencycheck.org.apache.tools.ant.types.selectors; - -import java.io.File; -import java.util.StringTokenizer; -import java.util.Vector; - -import org.owasp.dependencycheck.org.apache.tools.ant.types.Resource; -import org.owasp.dependencycheck.org.apache.tools.ant.util.FileUtils; - -/** - *

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

- *

This is a Singleton.

- * - * @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 "**". - *

- * This is not a general purpose test and should only be used if you - * can live with false positives. For example, pattern=**\a - * and str=b will yield true. - * - * @param pattern The pattern to match against. Must not be - * null. - * @param str The path to match, as a String. Must not be - * null. - * - * @return 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 "**". - *

- * This is not a general purpose test and should only be used if you - * can live with false positives. For example, pattern=**\a - * and str=b will yield true. - * - * @param pattern The pattern to match against. Must not be - * null. - * @param str The path to match, as a String. Must not be - * null. - * @param isCaseSensitive Whether or not matching should be performed - * case sensitively. - * - * @return 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 "**". - *

- * This is not a general purpose test and should only be used if you - * can live with false positives. For example, pattern=**\a - * and str=b will yield true. - * - * @param patDirs The tokenized pattern to match against. Must not be - * null. - * @param strDirs The tokenized path to match. Must not be - * null. - * @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 - * null. - * @param str The path to match, as a String. Must not be - * null. - * - * @return true if the pattern matches against the string, - * or false otherwise. - */ - public static boolean matchPath(String pattern, String str) { - String[] patDirs = tokenizePathAsArray(pattern); - return matchPath(patDirs, tokenizePathAsArray(str), true); - } - - /** - * Tests whether or not a given path matches a given pattern. - * - * If you need to call this method multiple times with the same - * pattern you should rather use TokenizedPattern - * - * @see TokenizedPattern - * - * @param pattern The pattern to match against. Must not be - * null. - * @param str The path to match, as a String. Must not be - * null. - * @param isCaseSensitive Whether or not matching should be performed - * case sensitively. - * - * @return true if the pattern matches against the string, - * or false otherwise. - */ - public static boolean matchPath(String pattern, String str, - boolean isCaseSensitive) { - String[] patDirs = tokenizePathAsArray(pattern); - return matchPath(patDirs, tokenizePathAsArray(str), isCaseSensitive); - } - - /** - * Core implementation of matchPath. It is isolated so that it - * can be called from TokenizedPattern. - */ - static boolean matchPath(String[] tokenizedPattern, String[] strDirs, - boolean isCaseSensitive) { - int patIdxStart = 0; - int patIdxEnd = tokenizedPattern.length - 1; - int strIdxStart = 0; - int strIdxEnd = strDirs.length - 1; - - // up to first '**' - while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) { - String patDir = tokenizedPattern[patIdxStart]; - if (patDir.equals(DEEP_TREE_MATCH)) { - break; - } - if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) { - return false; - } - patIdxStart++; - strIdxStart++; - } - if (strIdxStart > strIdxEnd) { - // String is exhausted - for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) { - return false; - } - } - return true; - } 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:
- * '*' means zero or more characters
- * '?' means one and only one character - * - * @param pattern The pattern to match against. - * Must not be null. - * @param str The string which must be matched against the pattern. - * Must not be null. - * - * @return true if the string matches against the pattern, - * or false otherwise. - */ - public static boolean match(String pattern, String str) { - return match(pattern, str, true); - } - - /** - * Tests whether or not a string matches against a pattern. - * The pattern may contain two special characters:
- * '*' means zero or more characters
- * '?' means one and only one character - * - * @param pattern The pattern to match against. - * Must not be null. - * @param str The string which must be matched against the pattern. - * Must not be null. - * @param caseSensitive Whether or not matching should be performed - * case sensitively. - * - * - * @return true if the string matches against the pattern, - * or false otherwise. - */ - public static boolean match(String pattern, String str, - boolean caseSensitive) { - char[] patArr = pattern.toCharArray(); - char[] strArr = str.toCharArray(); - int patIdxStart = 0; - int patIdxEnd = patArr.length - 1; - int strIdxStart = 0; - int strIdxEnd = strArr.length - 1; - 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 - * File.separator. - * - * @param path Path to tokenize. Must not be null. - * - * @return a Vector of path elements from the tokenized path - */ - public static Vector tokenizePath(String path) { - return tokenizePath(path, File.separator); - } - - /** - * Breaks a path up into a Vector of path elements, tokenizing on - * - * @param path Path to tokenize. Must not be null. - * @param separator the separator against which to tokenize. - * - * @return a Vector of path elements from the tokenized path - * @since Ant 1.6 - */ - public static Vector tokenizePath(String path, String separator) { - Vector ret = new Vector(); - if (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(); - } -} - diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/util/FileUtils.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/util/FileUtils.java deleted file mode 100644 index 32940225c..000000000 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/org/apache/tools/ant/util/FileUtils.java +++ /dev/null @@ -1,1667 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.owasp.dependencycheck.org.apache.tools.ant.util; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.HttpURLConnection; -import java.net.JarURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.nio.channels.Channel; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.Stack; -import java.util.StringTokenizer; -import java.util.jar.JarFile; -import org.owasp.dependencycheck.org.apache.tools.ant.BuildException; -import org.owasp.dependencycheck.org.apache.tools.ant.PathTokenizer; -import org.owasp.dependencycheck.org.apache.tools.ant.launch.Locator; -import org.owasp.dependencycheck.org.apache.tools.ant.taskdefs.condition.Os; - -/** - * This class also encapsulates methods which allow Files to be referred to using abstract path names which are - * translated to native system file paths at runtime as well as copying files or setting their last modification time. - * - */ -public class FileUtils { - - private static final int DELETE_RETRY_SLEEP_MILLIS = 10; - private static final int EXPAND_SPACE = 50; - private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); - - //get some non-crypto-grade randomness from various places. - private static Random rand = new Random(System.currentTimeMillis() - + Runtime.getRuntime().freeMemory()); - - private static final boolean ON_NETWARE = Os.isFamily("netware"); - private static final boolean ON_DOS = Os.isFamily("dos"); - private static final boolean ON_WIN9X = Os.isFamily("win9x"); - private static final boolean ON_WINDOWS = Os.isFamily("windows"); - - static final int BUF_SIZE = 8192; - - /** - * The granularity of timestamps under FAT. - */ - public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000; - - /** - * The granularity of timestamps under Unix. - */ - public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; - - /** - * The granularity of timestamps under the NT File System. NTFS has a granularity of 100 nanoseconds, which is less - * than 1 millisecond, so we round this up to 1 millisecond. - */ - public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1; - - /** - * A one item cache for fromUri. fromUri is called for each element when parseing ant build files. It is a costly - * operation. This just caches the result of the last call. - */ - private Object cacheFromUriLock = new Object(); - private String cacheFromUriRequest = null; - private String cacheFromUriResponse = null; - - /** - * Factory method. - * - * @return a new instance of FileUtils. - * @deprecated since 1.7. Use getFileUtils instead, FileUtils do not have state. - */ - public static FileUtils newFileUtils() { - return new FileUtils(); - } - - /** - * Method to retrieve The FileUtils, which is shared by all users of this method. - * - * @return an instance of FileUtils. - * @since Ant 1.6.3 - */ - public static FileUtils getFileUtils() { - return PRIMARY_INSTANCE; - } - - /** - * Empty constructor. - */ - protected FileUtils() { - } - - /** - * Get the URL for a file taking into account # characters. - * - * @param file the file whose URL representation is required. - * @return The FileURL value. - * @throws MalformedURLException if the URL representation cannot be formed. - */ - public URL getFileURL(File file) throws MalformedURLException { - return new URL(file.toURI().toASCIIString()); - } - -// /** -// * Convenience method to copy a file from a source to a destination. -// * No filtering is performed. -// * -// * @param sourceFile Name of file to copy from. -// * Must not be null. -// * @param destFile Name of file to copy to. -// * Must not be null. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(String sourceFile, String destFile) throws IOException { -// copyFile(new File(sourceFile), new File(destFile), null, false, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination -// * specifying if token filtering must be used. -// * -// * @param sourceFile Name of file to copy from. -// * Must not be null. -// * @param destFile Name of file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(String sourceFile, String destFile, FilterSetCollection filters) -// throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, false, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination specifying if token -// * filtering must be used and if source files may overwrite newer destination files. -// * -// * @param sourceFile Name of file to copy from. Must not be null. -// * @param destFile Name of file to copy to. Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be overwritten if it already -// * exists. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(String sourceFile, String destFile, FilterSetCollection filters, -// boolean overwrite) throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, overwrite, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination -// * specifying if token -// * filtering must be used, if source files may overwrite newer destination -// * files and the last -// * modified time of destFile file should be made equal to -// * the last modified time -// * of sourceFile. -// * -// * @param sourceFile Name of file to copy from. Must not be null. -// * @param destFile Name of file to copy to. Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file -// * should be set to that of the source file. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(String sourceFile, String destFile, -// FilterSetCollection filters, -// boolean overwrite, boolean preserveLastModified) -// throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, overwrite, -// preserveLastModified); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination specifying if token -// * filtering must be used, if source files may overwrite newer destination files and the last -// * modified time of destFile file should be made equal to the last modified time -// * of sourceFile. -// * -// * @param sourceFile Name of file to copy from. Must not be null. -// * @param destFile Name of file to copy to. Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be overwritten if it already -// * exists. -// * @param preserveLastModified Whether or not the last modified time of the resulting file -// * should be set to that of the source file. -// * @param encoding the encoding used to read and write the files. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.5 -// */ -// public void copyFile(String sourceFile, String destFile, -// FilterSetCollection filters, boolean overwrite, -// boolean preserveLastModified, String encoding) throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, -// overwrite, preserveLastModified, encoding); -// } -// // CheckStyle:ParameterNumberCheck OFF - bc -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * filter chains must be used, if source files may overwrite -// * newer destination files and the last modified time of -// * destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile Name of file to copy from. -// * Must not be null. -// * @param destFile Name of file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * @param encoding the encoding used to read and write the files. -// * @param project the project instance. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.5 -// */ -// public void copyFile(String sourceFile, String destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// String encoding, Project project) throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, filterChains, overwrite, -// preserveLastModified, encoding, project); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination specifying if token -// * filtering must be used, if filter chains must be used, if source files may overwrite newer -// * destination files and the last modified time of destFile file should be made -// * equal to the last modified time of sourceFile. -// * -// * @param sourceFile Name of file to copy from. Must not be null. -// * @param destFile Name of file to copy to. Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be overwritten if it already -// * exists. -// * @param preserveLastModified Whether or not the last modified time of the resulting file -// * should be set to that of the source file. -// * @param inputEncoding the encoding used to read the files. -// * @param outputEncoding the encoding used to write the files. -// * @param project the project instance. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.6 -// */ -// public void copyFile(String sourceFile, String destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// String inputEncoding, String outputEncoding, -// Project project) throws IOException { -// copyFile(new File(sourceFile), new File(destFile), filters, filterChains, overwrite, -// preserveLastModified, inputEncoding, outputEncoding, project); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination. No filtering is performed. -// * -// * @param sourceFile the file to copy from. Must not be null. -// * @param destFile the file to copy to. Must not be null. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(File sourceFile, File destFile) throws IOException { -// copyFile(sourceFile, destFile, null, false, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination -// * specifying if token filtering must be used. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(File sourceFile, File destFile, FilterSetCollection filters) -// throws IOException { -// copyFile(sourceFile, destFile, filters, false, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used and if -// * source files may overwrite newer destination files. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(File sourceFile, File destFile, FilterSetCollection filters, -// boolean overwrite) throws IOException { -// copyFile(sourceFile, destFile, filters, overwrite, false); -// } -// -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * source files may overwrite newer destination files and the -// * last modified time of destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * -// * @throws IOException if the copying fails. -// */ -// public void copyFile(File sourceFile, File destFile, FilterSetCollection filters, -// boolean overwrite, boolean preserveLastModified) throws IOException { -// copyFile(sourceFile, destFile, filters, overwrite, preserveLastModified, null); -// } -// -// /** -// * Convenience method to copy a file from a source to a destination specifying if token -// * filtering must be used, if source files may overwrite newer destination files, the last -// * modified time of destFile file should be made equal to the last modified time -// * of sourceFile and which character encoding to assume. -// * -// * @param sourceFile the file to copy from. Must not be null. -// * @param destFile the file to copy to. Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param overwrite Whether or not the destination file should be overwritten if it already -// * exists. -// * @param preserveLastModified Whether or not the last modified time of the resulting file -// * should be set to that of the source file. -// * @param encoding the encoding used to read and write the files. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.5 -// */ -// public void copyFile(File sourceFile, File destFile, -// FilterSetCollection filters, boolean overwrite, -// boolean preserveLastModified, String encoding) throws IOException { -// copyFile(sourceFile, destFile, filters, null, overwrite, -// preserveLastModified, encoding, null); -// } -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * filter chains must be used, if source files may overwrite -// * newer destination files and the last modified time of -// * destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * @param encoding the encoding used to read and write the files. -// * @param project the project instance. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.5 -// */ -// public void copyFile(File sourceFile, File destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// String encoding, Project project) throws IOException { -// copyFile(sourceFile, destFile, filters, filterChains, -// overwrite, preserveLastModified, encoding, encoding, project); -// } -// -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * filter chains must be used, if source files may overwrite -// * newer destination files and the last modified time of -// * destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * @param inputEncoding the encoding used to read the files. -// * @param outputEncoding the encoding used to write the files. -// * @param project the project instance. -// * -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.6 -// */ -// public void copyFile(File sourceFile, File destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// String inputEncoding, String outputEncoding, -// Project project) throws IOException { -// copyFile(sourceFile, destFile, filters, filterChains, overwrite, preserveLastModified, -// false, inputEncoding, outputEncoding, project); -// } -// -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * filter chains must be used, if source files may overwrite -// * newer destination files and the last modified time of -// * destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * @param append whether to append to the destination file. -// * @param inputEncoding the encoding used to read the files. -// * @param outputEncoding the encoding used to write the files. -// * @param project the project instance. -// * -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.8 -// */ -// public void copyFile(File sourceFile, File destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// boolean append, -// String inputEncoding, String outputEncoding, -// Project project) throws IOException { -// copyFile(sourceFile, destFile, filters, filterChains, overwrite, -// preserveLastModified, append, inputEncoding, outputEncoding, -// project, /* force: */ false); -// } -// -// /** -// * Convenience method to copy a file from a source to a -// * destination specifying if token filtering must be used, if -// * filter chains must be used, if source files may overwrite -// * newer destination files and the last modified time of -// * destFile file should be made equal -// * to the last modified time of sourceFile. -// * -// * @param sourceFile the file to copy from. -// * Must not be null. -// * @param destFile the file to copy to. -// * Must not be null. -// * @param filters the collection of filters to apply to this copy. -// * @param filterChains filterChains to apply during the copy. -// * @param overwrite Whether or not the destination file should be -// * overwritten if it already exists. -// * @param preserveLastModified Whether or not the last modified time of -// * the resulting file should be set to that -// * of the source file. -// * @param append whether to append to the destination file. -// * @param inputEncoding the encoding used to read the files. -// * @param outputEncoding the encoding used to write the files. -// * @param project the project instance. -// * @param force whether to overwrite read-only destination files. -// * -// * @throws IOException if the copying fails. -// * -// * @since Ant 1.8.2 -// */ -// public void copyFile(File sourceFile, File destFile, -// FilterSetCollection filters, Vector filterChains, -// boolean overwrite, boolean preserveLastModified, -// boolean append, -// String inputEncoding, String outputEncoding, -// Project project, boolean force) throws IOException { -// ResourceUtils.copyResource(new FileResource(sourceFile), -// new FileResource(destFile), -// filters, filterChains, overwrite, -// preserveLastModified, append, inputEncoding, -// outputEncoding, project, force); -// } -// -// // CheckStyle:ParameterNumberCheck ON -// -// /** -// * Calls File.setLastModified(long time). Originally written to -// * to dynamically bind to that call on Java1.2+. -// * -// * @param file the file whose modified time is to be set -// * @param time the time to which the last modified time is to be set. -// * if this is -1, the current time is used. -// */ -// public void setFileLastModified(File file, long time) { -// ResourceUtils.setLastModified(new FileResource(file), time); -// } - /** - * Interpret the filename as a file relative to the given file unless the filename already represents an absolute - * filename. Differs from new File(file, filename) in that the resulting File's path will always be a - * normalized, absolute pathname. Also, if it is determined that filename is context-relative, - * file will be discarded and the reference will be resolved using available context/state information - * about the filesystem. - * - * @param file the "reference" file for relative paths. This instance must be an absolute file and must not contain - * "./" or "../" sequences (same for \ instead of /). If it is null, this call is equivalent to - * new java.io.File(filename).getAbsoluteFile(). - * - * @param filename a file name. - * - * @return an absolute file. - * @throws java.lang.NullPointerException if filename is null. - */ - public File resolveFile(File file, String filename) { - if (!isAbsolutePath(filename)) { - char sep = File.separatorChar; - filename = filename.replace('/', sep).replace('\\', sep); - if (isContextRelativePath(filename)) { - file = null; - // on cygwin, our current directory can be a UNC; - // assume user.dir is absolute or all hell breaks loose... - String udir = System.getProperty("user.dir"); - if (filename.charAt(0) == sep && udir.charAt(0) == sep) { - filename = dissect(udir)[0] + filename.substring(1); - } - } - filename = new File(file, filename).getAbsolutePath(); - } - return normalize(filename); - } - - /** - * On DOS and NetWare, the evaluation of certain file specifications is context-dependent. These are filenames - * beginning with a single separator (relative to current root directory) and filenames with a drive specification - * and no intervening separator (relative to current directory of the specified root). - * - * @param filename the filename to evaluate. - * @return true if the filename is relative to system context. - * @throws java.lang.NullPointerException if filename is null. - * @since Ant 1.7 - */ - public static boolean isContextRelativePath(String filename) { - if (!(ON_DOS || ON_NETWARE) || filename.length() == 0) { - return false; - } - char sep = File.separatorChar; - filename = filename.replace('/', sep).replace('\\', sep); - char c = filename.charAt(0); - int len = filename.length(); - return (c == sep && (len == 1 || filename.charAt(1) != sep)) - || (Character.isLetter(c) && len > 1 - && filename.charAt(1) == ':' - && (len == 2 || filename.charAt(2) != sep)); - } - - /** - * Verifies that the specified filename represents an absolute path. Differs from new - * java.io.File("filename").isAbsolute() in that a path beginning with a double file separator--signifying a Windows - * UNC--must at minimum match "\\a\b" to be considered an absolute path. - * - * @param filename the filename to be checked. - * @return true if the filename represents an absolute path. - * @throws java.lang.NullPointerException if filename is null. - * @since Ant 1.6.3 - */ - public static boolean isAbsolutePath(String filename) { - int len = filename.length(); - if (len == 0) { - return false; - } - char sep = File.separatorChar; - filename = filename.replace('/', sep).replace('\\', sep); - char c = filename.charAt(0); - if (!(ON_DOS || ON_NETWARE)) { - return (c == sep); - } - if (c == sep) { - // CheckStyle:MagicNumber OFF - if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) { - return false; - } - // CheckStyle:MagicNumber ON - int nextsep = filename.indexOf(sep, 2); - return nextsep > 2 && nextsep + 1 < len; - } - int colon = filename.indexOf(':'); - return (Character.isLetter(c) && colon == 1 - && filename.length() > 2 && filename.charAt(2) == sep) - || (ON_NETWARE && colon > 0); - } - - /** - * Translate a path into its native (platform specific) format. - *

- * This method uses PathTokenizer to separate the input path into its components. This handles DOS style paths in a - * relatively sensible way. The file separators are then converted to their platform specific versions. - * - * @param toProcess The path to be translated. May be null. - * - * @return the native version of the specified path or an empty string if the path is null or empty. - * - * @since ant 1.7 - * @see PathTokenizer - */ - public static String translatePath(String toProcess) { - if (toProcess == null || toProcess.length() == 0) { - return ""; - } - final StringBuilder path = new StringBuilder(toProcess.length() + EXPAND_SPACE); - final PathTokenizer tokenizer = new PathTokenizer(toProcess); - while (tokenizer.hasMoreTokens()) { - String pathComponent = tokenizer.nextToken(); - pathComponent = pathComponent.replace('/', File.separatorChar); - pathComponent = pathComponent.replace('\\', File.separatorChar); - if (path.length() != 0) { - path.append(File.pathSeparatorChar); - } - path.append(pathComponent); - } - return path.toString(); - } - - /** - * "Normalize" the given absolute path. - * - *

- * This includes: - *

- * Unlike {@link File#getCanonicalPath()} this method specifically does not resolve symbolic links. - * - * @param path the path to be normalized. - * @return the normalized version of the path. - * - * @throws java.lang.NullPointerException if path is null. - */ - public File normalize(final String path) { - Stack s = new Stack(); - String[] dissect = dissect(path); - s.push(dissect[0]); - - StringTokenizer tok = new StringTokenizer(dissect[1], File.separator); - while (tok.hasMoreTokens()) { - String thisToken = tok.nextToken(); - if (".".equals(thisToken)) { - continue; - } - if ("..".equals(thisToken)) { - if (s.size() < 2) { - // Cannot resolve it, so skip it. - return new File(path); - } - s.pop(); - } else { // plain component - s.push(thisToken); - } - } - final StringBuilder sb = new StringBuilder(); - final int size = s.size(); - for (int i = 0; i < size; i++) { - if (i > 1) { - // not before the filesystem root and not after it, since root - // already contains one - sb.append(File.separatorChar); - } - sb.append(s.elementAt(i)); - } - return new File(sb.toString()); - } - - /** - * Dissect the specified absolute path. - * - * @param path the path to dissect. - * @return String[] {root, remaining path}. - * @throws java.lang.NullPointerException if path is null. - * @since Ant 1.7 - */ - public String[] dissect(String path) { - char sep = File.separatorChar; - path = path.replace('/', sep).replace('\\', sep); - - // make sure we are dealing with an absolute path - if (!isAbsolutePath(path)) { - throw new BuildException(path + " is not an absolute path"); - } - String root = null; - int colon = path.indexOf(':'); - if (colon > 0 && (ON_DOS || ON_NETWARE)) { - - int next = colon + 1; - root = path.substring(0, next); - char[] ca = path.toCharArray(); - root += sep; - //remove the initial separator; the root has it. - next = (ca[next] == sep) ? next + 1 : next; - - final StringBuilder sbPath = new StringBuilder(); - // Eliminate consecutive slashes after the drive spec: - for (int i = next; i < ca.length; i++) { - if (ca[i] != sep || ca[i - 1] != sep) { - sbPath.append(ca[i]); - } - } - path = sbPath.toString(); - } else if (path.length() > 1 && path.charAt(1) == sep) { - // UNC drive - int nextsep = path.indexOf(sep, 2); - nextsep = path.indexOf(sep, nextsep + 1); - root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path; - path = path.substring(root.length()); - } else { - root = File.separator; - path = path.substring(1); - } - return new String[]{root, path}; - } - - /** - * Returns a VMS String representation of a File object. This is useful since the JVM by default - * internally converts VMS paths to Unix style. The returned String is always an absolute path. - * - * @param f The File to get the VMS path for. - * @return The absolute VMS path to f. - */ - public String toVMSPath(File f) { - // format: "DEVICE:[DIR.SUBDIR]FILE" - String osPath; - String path = normalize(f.getAbsolutePath()).getPath(); - String name = f.getName(); - boolean isAbsolute = path.charAt(0) == File.separatorChar; - // treat directories specified using .DIR syntax as files - // CheckStyle:MagicNumber OFF - boolean isDirectory = f.isDirectory() - && !name.regionMatches(true, name.length() - 4, ".DIR", 0, 4); - // CheckStyle:MagicNumber ON - String device = null; - StringBuilder directory = null; - String file = null; - - int index = 0; - - if (isAbsolute) { - index = path.indexOf(File.separatorChar, 1); - if (index == -1) { - return path.substring(1) + ":[000000]"; - } - device = path.substring(1, index++); - } - if (isDirectory) { - directory = new StringBuilder(path.substring(index).replace(File.separatorChar, '.')); - } else { - int dirEnd = path.lastIndexOf(File.separatorChar, path.length()); - if (dirEnd == -1 || dirEnd < index) { - file = path.substring(index); - } else { - directory = new StringBuilder(path.substring(index, dirEnd). - replace(File.separatorChar, '.')); - index = dirEnd + 1; - if (path.length() > index) { - file = path.substring(index); - } - } - } - if (!isAbsolute && directory != null) { - directory.insert(0, '.'); - } - osPath = ((device != null) ? device + ":" : "") - + ((directory != null) ? "[" + directory + "]" : "") - + ((file != null) ? file : ""); - return osPath; - } - - /** - * Create a File object for a temporary file in a given directory. Without actually creating the file. - * - *

- * The file denoted by the returned abstract pathname did not exist before this method was invoked, any subsequent - * invocation of this method will yield a different file name. - *

- *

- * The filename is prefixNNNNNsuffix where NNNN is a random number. - *

- * - * @param prefix prefix before the random number. - * @param suffix file extension; include the '.'. - * @param parentDir Directory to create the temporary file in; java.io.tmpdir used if not specified. - * - * @deprecated since ant 1.7.1 use createTempFile(String, String, File, boolean, boolean) instead. - * @return a File reference to the new, nonexistent temporary file. - */ - public File createTempFile(String prefix, String suffix, File parentDir) { - return createTempFile(prefix, suffix, parentDir, false, false); - } - - private static final String NULL_PLACEHOLDER = "null"; - - /** - * Create a temporary file in a given directory. - * - *

- * The file denoted by the returned abstract pathname did not exist before this method was invoked, any subsequent - * invocation of this method will yield a different file name.

- * - * @param prefix prefix before the random number. - * @param suffix file extension; include the '.'. - * @param parentDir Directory to create the temporary file in; java.io.tmpdir used if not specified. - * @param deleteOnExit whether to set the tempfile for deletion on normal VM exit. - * @param createFile true if the file must actually be created. If false chances exist that a file with the same - * name is created in the time between invoking this method and the moment the file is actually created. If possible - * set to true. - * - * @return a File reference to the new temporary file. - * @since Ant 1.7.1 - */ - public File createTempFile(String prefix, String suffix, File parentDir, - boolean deleteOnExit, boolean createFile) { - File result = null; - String parent = (parentDir == null) - ? System.getProperty("java.io.tmpdir") - : parentDir.getPath(); - if (prefix == null) { - prefix = NULL_PLACEHOLDER; - } - if (suffix == null) { - suffix = NULL_PLACEHOLDER; - } - - if (createFile) { - try { - result = File.createTempFile(prefix, suffix, new File(parent)); - } catch (IOException e) { - throw new BuildException("Could not create tempfile in " - + parent, e); - } - } else { - DecimalFormat fmt = new DecimalFormat("#####"); - synchronized (rand) { - do { - result = new File(parent, prefix - + fmt.format(rand.nextInt(Integer.MAX_VALUE)) + suffix); - } while (result.exists()); - } - } - - if (deleteOnExit) { - result.deleteOnExit(); - } - return result; - } - - /** - * Create a File object for a temporary file in a given directory. Without actually creating the file. - * - *

- * The file denoted by the returned abstract pathname did not exist before this method was invoked, any subsequent - * invocation of this method will yield a different file name. - *

- *

- * The filename is prefixNNNNNsuffix where NNNN is a random number. - *

- * - * @param prefix prefix before the random number. - * @param suffix file extension; include the '.'. - * @param parentDir Directory to create the temporary file in; java.io.tmpdir used if not specified. - * @param deleteOnExit whether to set the tempfile for deletion on normal VM exit. - * - * @deprecated since ant 1.7.1 use createTempFile(String, String, File, boolean, boolean) instead. - * @return a File reference to the new, nonexistent temporary file. - */ - public File createTempFile(String prefix, String suffix, - File parentDir, boolean deleteOnExit) { - return createTempFile(prefix, suffix, parentDir, deleteOnExit, false); - } - -// /** -// * Compares the contents of two files. -// * -// * @param f1 the file whose content is to be compared. -// * @param f2 the other file whose content is to be compared. -// * -// * @return true if the content of the files is the same. -// * -// * @throws IOException if the files cannot be read. -// */ -// public boolean contentEquals(File f1, File f2) throws IOException { -// return contentEquals(f1, f2, false); -// } -// -// /** -// * Compares the contents of two files. -// * -// * @param f1 the file whose content is to be compared. -// * @param f2 the other file whose content is to be compared. -// * @param textfile true if the file is to be treated as a text file and -// * differences in kind of line break are to be ignored. -// * -// * @return true if the content of the files is the same. -// * -// * @throws IOException if the files cannot be read. -// * @since Ant 1.6.3 -// */ -// public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { -// return ResourceUtils.contentEquals(new FileResource(f1), new FileResource(f2), textfile); -// } - /** - * This was originally an emulation of {@link File#getParentFile} for JDK 1.1, but it is now implemented using that - * method (Ant 1.6.3 onwards). - * - * @param f the file whose parent is required. - * @return the given file's parent, or null if the file does not have a parent. - * @since 1.10 - * @deprecated since 1.7. Just use {@link File#getParentFile} directly. - */ - public File getParentFile(File f) { - return (f == null) ? null : f.getParentFile(); - } - - /** - * Read from reader till EOF. - * - * @param rdr the reader from which to read. - * @return the contents read out of the given reader. - * - * @throws IOException if the contents could not be read out from the reader. - */ - public static String readFully(Reader rdr) throws IOException { - return readFully(rdr, BUF_SIZE); - } - - /** - * Read from reader till EOF. - * - * @param rdr the reader from which to read. - * @param bufferSize the buffer size to use when reading. - * - * @return the contents read out of the given reader. - * - * @throws IOException if the contents could not be read out from the reader. - */ - public static String readFully(Reader rdr, int bufferSize) - throws IOException { - if (bufferSize <= 0) { - throw new IllegalArgumentException("Buffer size must be greater " - + "than 0"); - } - final char[] buffer = new char[bufferSize]; - int bufferLength = 0; - StringBuilder textBuffer = null; - while (bufferLength != -1) { - bufferLength = rdr.read(buffer); - if (bufferLength > 0) { - textBuffer = (textBuffer == null) ? new StringBuilder() : textBuffer; - textBuffer.append(new String(buffer, 0, bufferLength)); - } - } - return (textBuffer == null) ? null : textBuffer.toString(); - } - - /** - * Safe read fully - do not return a null for an empty reader. - * - * @param reader the input to read from. - * @return the string. - * @throws IOException if unable to read from reader. - * @since Ant 1.7.1 - */ - public static String safeReadFully(Reader reader) throws IOException { - String ret = readFully(reader); - return ret == null ? "" : ret; - } - - /** - * This was originally an emulation of File.createNewFile for JDK 1.1, but it is now implemented using that method - * (Ant 1.6.3 onwards). - * - *

- * This method has historically not guaranteed that the operation was atomic. In its current - * implementation it is. - * - * @param f the file to be created. - * @return true if the file did not exist already. - * @throws IOException on error. - * @since Ant 1.5 - */ - public boolean createNewFile(File f) throws IOException { - return f.createNewFile(); - } - - /** - * Create a new file, optionally creating parent directories. - * - * @param f the file to be created. - * @param mkdirs boolean whether to create parent directories. - * @return true if the file did not exist already. - * @throws IOException on error. - * @since Ant 1.6.3 - */ - public boolean createNewFile(File f, boolean mkdirs) throws IOException { - File parent = f.getParentFile(); - if (mkdirs && !(parent.exists())) { - parent.mkdirs(); - } - return f.createNewFile(); - } - - /** - * Checks whether a given file is a symbolic link. - * - *

- * It doesn't really test for symbolic links but whether the canonical and absolute paths of the file are - * identical--this may lead to false positives on some platforms.

- * - * @param parent the parent directory of the file to test - * @param name the name of the file to test. - * - * @return true if the file is a symbolic link. - * @throws IOException on error. - * @since Ant 1.5 - * @deprecated use SymbolicLinkUtils instead - */ - public boolean isSymbolicLink(File parent, String name) - throws IOException { - SymbolicLinkUtils u = SymbolicLinkUtils.getSymbolicLinkUtils(); - if (parent == null) { - return u.isSymbolicLink(name); - } - return u.isSymbolicLink(parent, name); - } - - /** - * Removes a leading path from a second path. - * - * @param leading The leading path, must not be null, must be absolute. - * @param path The path to remove from, must not be null, must be absolute. - * - * @return path's normalized absolute if it doesn't start with leading; path's path with leading's path removed - * otherwise. - * - * @since Ant 1.5 - */ - public String removeLeadingPath(File leading, File path) { - String l = normalize(leading.getAbsolutePath()).getAbsolutePath(); - String p = normalize(path.getAbsolutePath()).getAbsolutePath(); - if (l.equals(p)) { - return ""; - } - // ensure that l ends with a / - // so we never think /foo was a parent directory of /foobar - if (!l.endsWith(File.separator)) { - l += File.separator; - } - return (p.startsWith(l)) ? p.substring(l.length()) : p; - } - - /** - * Learn whether one path "leads" another. - * - * @param leading The leading path, must not be null, must be absolute. - * @param path The path to remove from, must not be null, must be absolute. - * @return true if path starts with leading; false otherwise. - * @since Ant 1.7 - */ - public boolean isLeadingPath(File leading, File path) { - String l = normalize(leading.getAbsolutePath()).getAbsolutePath(); - String p = normalize(path.getAbsolutePath()).getAbsolutePath(); - if (l.equals(p)) { - return true; - } - // ensure that l ends with a / - // so we never think /foo was a parent directory of /foobar - if (!l.endsWith(File.separator)) { - l += File.separator; - } - return p.startsWith(l); - } - - /** - * Constructs a file: URI that represents the external form of the given pathname. - * - *

- * Will be an absolute URI if the given path is absolute.

- * - *

- * This code encodes non ASCII characters too.

- * - *

- * The coding of the output is the same as what File.toURI().toASCIIString() produces

- * - * See dt-sysid - * which makes some mention of how characters not supported by URI Reference syntax should be escaped. - * - * @param path the path in the local file system. - * @return the URI version of the local path. - * @since Ant 1.6 - */ - public String toURI(String path) { - return new File(path).toURI().toASCIIString(); - } - - /** - * Constructs a file path from a file: URI. - * - *

- * Will be an absolute path if the given URI is absolute.

- * - *

- * Swallows '%' that are not followed by two characters, doesn't deal with non-ASCII characters.

- * - * @param uri the URI designating a file in the local filesystem. - * @return the local file system path for the file. - * @since Ant 1.6 - */ - public String fromURI(String uri) { - synchronized (cacheFromUriLock) { - if (uri.equals(cacheFromUriRequest)) { - return cacheFromUriResponse; - } - String path = Locator.fromURI(uri); - String ret = isAbsolutePath(path) ? normalize(path).getAbsolutePath() : path; - cacheFromUriRequest = uri; - cacheFromUriResponse = ret; - return ret; - } - } - - /** - * Compares two filenames. - * - *

- * Unlike java.io.File#equals this method will try to compare the absolute paths and "normalize" the - * filenames before comparing them.

- * - * @param f1 the file whose name is to be compared. - * @param f2 the other file whose name is to be compared. - * - * @return true if the file are for the same file. - * - * @since Ant 1.5.3 - */ - public boolean fileNameEquals(File f1, File f2) { - return normalize(f1.getAbsolutePath()).getAbsolutePath().equals( - normalize(f2.getAbsolutePath()).getAbsolutePath()); - } - - /** - * Are the two File instances pointing to the same object on the file system? - * - * @since Ant 1.8.2 - */ - public boolean areSame(File f1, File f2) throws IOException { - if (f1 == null && f2 == null) { - return true; - } - if (f1 == null || f2 == null) { - return false; - } - File f1Normalized = normalize(f1.getAbsolutePath()); - File f2Normalized = normalize(f2.getAbsolutePath()); - return f1Normalized.equals(f2Normalized) - || f1Normalized.getCanonicalFile().equals(f2Normalized - .getCanonicalFile()); - } -// -// /** -// * Renames a file, even if that involves crossing file system boundaries. -// * -// *

-// * This will remove to (if it exists), ensure that to's parent directory exists and move -// * from, which involves deleting from as well.

-// * -// * @param from the file to move. -// * @param to the new file name. -// * -// * @throws IOException if anything bad happens during this process. Note that to may have been deleted -// * already when this happens. -// * -// * @since Ant 1.6 -// */ -// public void rename(File from, File to) throws IOException { -// // identical logic lives in Move.renameFile(): -// from = normalize(from.getAbsolutePath()).getCanonicalFile(); -// to = normalize(to.getAbsolutePath()); -// if (!from.exists()) { -// System.err.println("Cannot rename nonexistent file " + from); -// return; -// } -// if (from.getAbsolutePath().equals(to.getAbsolutePath())) { -// System.err.println("Rename of " + from + " to " + to + " is a no-op."); -// return; -// } -// if (to.exists() && !(areSame(from, to) || tryHardToDelete(to))) { -// throw new IOException("Failed to delete " + to + " while trying to rename " + from); -// } -// File parent = to.getParentFile(); -// if (parent != null && !parent.isDirectory() -// && !(parent.mkdirs() || parent.isDirectory())) { -// throw new IOException("Failed to create directory " + parent -// + " while trying to rename " + from); -// } -// if (!from.renameTo(to)) { -// copyFile(from, to); -// if (!tryHardToDelete(from)) { -// throw new IOException("Failed to delete " + from + " while trying to rename it."); -// } -// } -// } - - /** - * Get the granularity of file timestamps. The choice is made based on OS, which is incorrect--it should really be - * by filesystem. We do not have an easy way to probe for file systems, however, so this heuristic gives us a decent - * default. - * - * @return the difference, in milliseconds, which two file timestamps must have in order for the two files to be - * considered to have different timestamps. - */ - public long getFileTimestampGranularity() { - if (ON_WIN9X) { - return FAT_FILE_TIMESTAMP_GRANULARITY; - } - if (ON_WINDOWS) { - return NTFS_FILE_TIMESTAMP_GRANULARITY; - } - if (ON_DOS) { - return FAT_FILE_TIMESTAMP_GRANULARITY; - } - return UNIX_FILE_TIMESTAMP_GRANULARITY; - } - - /** - * test whether a file or directory exists, with an error in the upper/lower case spelling of the name. Using this - * method is only interesting on case insensitive file systems (Windows).
- * It will return true only if 3 conditions are met : - *
- * - *
- * the purpose is to identify files or directories on case-insensitive filesystems whose case is not what is - * expected.
- * Possibly to rename them afterwards to the desired upper/lowercase combination. - *
- * - * @param localFile file to test - * @return true if the file exists and the case of the actual file is not the case of the parameter - * @since Ant 1.7.1 - */ - public boolean hasErrorInCase(File localFile) { - localFile = normalize(localFile.getAbsolutePath()); - if (!localFile.exists()) { - return false; - } - final String localFileName = localFile.getName(); - FilenameFilter ff = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.equalsIgnoreCase(localFileName) && (!name.equals(localFileName)); - } - }; - String[] names = localFile.getParentFile().list(ff); - return names != null && names.length == 1; - } - - /** - * Returns true if the source is older than the dest. If the dest file does not exist, then the test returns false; - * it is implicitly not up do date. - * - * @param source source file (should be the older). - * @param dest dest file (should be the newer). - * @param granularity an offset added to the source time. - * @return true if the source is older than the dest after accounting for granularity. - * @since Ant 1.6.3 - */ - public boolean isUpToDate(File source, File dest, long granularity) { - //do a check for the destination file existing - if (!dest.exists()) { - //if it does not, then the file is not up to date. - return false; - } - long sourceTime = source.lastModified(); - long destTime = dest.lastModified(); - return isUpToDate(sourceTime, destTime, granularity); - } - - /** - * Returns true if the source is older than the dest. - * - * @param source source file (should be the older). - * @param dest dest file (should be the newer). - * @return true if the source is older than the dest, taking the granularity into account. - * @since Ant 1.6.3 - */ - public boolean isUpToDate(File source, File dest) { - return isUpToDate(source, dest, getFileTimestampGranularity()); - } - - /** - * Compare two timestamps for being up to date using the specified granularity. - * - * @param sourceTime timestamp of source file. - * @param destTime timestamp of dest file. - * @param granularity os/filesys granularity. - * @return true if the dest file is considered up to date. - */ - public boolean isUpToDate(long sourceTime, long destTime, long granularity) { - return destTime != -1 && destTime >= sourceTime + granularity; - } - - /** - * Compare two timestamps for being up to date using the current granularity. - * - * @param sourceTime timestamp of source file. - * @param destTime timestamp of dest file. - * @return true if the dest file is considered up to date. - */ - public boolean isUpToDate(long sourceTime, long destTime) { - return isUpToDate(sourceTime, destTime, getFileTimestampGranularity()); - } - - /** - * Close a Writer without throwing any exception if something went wrong. Do not attempt to close it if the argument - * is null. - * - * @param device output writer, can be null. - */ - public static void close(Writer device) { - if (null != device) { - try { - device.close(); - } catch (IOException e) { - //ignore - } - } - } - - /** - * Close a Reader without throwing any exception if something went wrong. Do not attempt to close it if the argument - * is null. - * - * @param device Reader, can be null. - */ - public static void close(Reader device) { - if (null != device) { - try { - device.close(); - } catch (IOException e) { - //ignore - } - } - } - - /** - * Close a stream without throwing any exception if something went wrong. Do not attempt to close it if the argument - * is null. - * - * @param device stream, can be null. - */ - public static void close(OutputStream device) { - if (null != device) { - try { - device.close(); - } catch (IOException e) { - //ignore - } - } - } - - /** - * Close a stream without throwing any exception if something went wrong. Do not attempt to close it if the argument - * is null. - * - * @param device stream, can be null. - */ - public static void close(InputStream device) { - if (null != device) { - try { - device.close(); - } catch (IOException e) { - //ignore - } - } - } - - /** - * Close a Channel without throwing any exception if something went wrong. Do not attempt to close it if the - * argument is null. - * - * @param device channel, can be null. - * @since Ant 1.8.0 - */ - public static void close(Channel device) { - if (null != device) { - try { - device.close(); - } catch (IOException e) { - //ignore - } - } - } - - /** - * Closes an URLConnection if its concrete implementation provides a way to close it that Ant knows of. - * - * @param conn connection, can be null - * @since Ant 1.8.0 - */ - public static void close(URLConnection conn) { - if (conn != null) { - try { - if (conn instanceof JarURLConnection) { - JarURLConnection juc = (JarURLConnection) conn; - JarFile jf = juc.getJarFile(); - jf.close(); - jf = null; - } else if (conn instanceof HttpURLConnection) { - ((HttpURLConnection) conn).disconnect(); - } - } catch (IOException exc) { - //ignore - } - } - } - - /** - * Delete the file with {@link File#delete()} if the argument is not null. Do nothing on a null argument. - * - * @param file file to delete. - */ - public static void delete(File file) { - if (file != null) { - file.delete(); - } - } - - /** - * Accommodate Windows bug encountered in both Sun and IBM JDKs. Others possible. If the delete does not work, call - * System.gc(), wait a little and try again. - * - * @return whether deletion was successful - * @since Ant 1.8.0 - */ - public boolean tryHardToDelete(File f) { - return tryHardToDelete(f, ON_WINDOWS); - } - - /** - * If delete does not work, call System.gc() if asked to, wait a little and try again. - * - * @return whether deletion was successful - * @since Ant 1.8.3 - */ - public boolean tryHardToDelete(File f, boolean runGC) { - if (!f.delete()) { - if (runGC) { - System.gc(); - } - try { - Thread.sleep(DELETE_RETRY_SLEEP_MILLIS); - } catch (InterruptedException ex) { - // Ignore Exception - } - return f.delete(); - } - return true; - } - - /** - * Calculates the relative path between two files. - *

- * Implementation note:
This function may throw an IOException if an I/O error occurs because its use of the - * canonical pathname may require filesystem queries. - *

- * - * @param fromFile the File to calculate the path from - * @param toFile the File to calculate the path to - * @return the relative path between the files - * @throws Exception for undocumented reasons - * @see File#getCanonicalPath() - * - * @since Ant 1.7 - */ - public static String getRelativePath(File fromFile, File toFile) throws Exception { - String fromPath = fromFile.getCanonicalPath(); - String toPath = toFile.getCanonicalPath(); - - // build the path stack info to compare - String[] fromPathStack = getPathStack(fromPath); - String[] toPathStack = getPathStack(toPath); - - if (0 < toPathStack.length && 0 < fromPathStack.length) { - if (!fromPathStack[0].equals(toPathStack[0])) { - // not the same device (would be "" on Linux/Unix) - - return getPath(Arrays.asList(toPathStack)); - } - } else { - // no comparison possible - return getPath(Arrays.asList(toPathStack)); - } - - int minLength = Math.min(fromPathStack.length, toPathStack.length); - int same = 1; // Used outside the for loop - - // get index of parts which are equal - for (; - same < minLength && fromPathStack[same].equals(toPathStack[same]); - same++) { - // Do nothing - } - - List relativePathStack = new ArrayList(); - - // if "from" part is longer, fill it up with ".." - // to reach path which is equal to both paths - for (int i = same; i < fromPathStack.length; i++) { - relativePathStack.add(".."); - } - - // fill it up path with parts which were not equal - for (int i = same; i < toPathStack.length; i++) { - relativePathStack.add(toPathStack[i]); - } - - return getPath(relativePathStack); - } - - /** - * Gets all names of the path as an array of Strings. - * - * @param path to get names from - * @return Strings, never null - * - * @since Ant 1.7 - */ - public static String[] getPathStack(String path) { - String normalizedPath = path.replace(File.separatorChar, '/'); - - return normalizedPath.split("/"); - } - - /** - * Gets path from a List of Strings. - * - * @param pathStack List of Strings to be concatenated as a path. - * @return String, never null - * - * @since Ant 1.7 - */ - public static String getPath(List pathStack) { - // can safely use '/' because Windows understands '/' as separator - return getPath(pathStack, '/'); - } - - /** - * Gets path from a List of Strings. - * - * @param pathStack List of Strings to be concated as a path. - * @param separatorChar char to be used as separator between names in path - * @return String, never null - * - * @since Ant 1.7 - */ - public static String getPath(final List pathStack, final char separatorChar) { - final StringBuilder buffer = new StringBuilder(); - - final Iterator iter = pathStack.iterator(); - if (iter.hasNext()) { - buffer.append(iter.next()); - } - while (iter.hasNext()) { - buffer.append(separatorChar); - buffer.append(iter.next()); - } - return buffer.toString(); - } - - /** - * Get the default encoding. This is done by opening an InputStreamReader on a dummy InputStream and getting the - * encoding. Could use System.getProperty("file.encoding"), but cannot see where this is documented. - * - * @return the default file encoding. - */ - public String getDefaultEncoding() { - InputStreamReader is = new InputStreamReader( - new InputStream() { - public int read() { - return -1; - } - }); - try { - return is.getEncoding(); - } finally { - close(is); - } - } -}