diff --git a/src/etc/testcases/core/directoryscanner.xml b/src/etc/testcases/core/directoryscanner.xml index 31a5fc884..5417a4ee9 100644 --- a/src/etc/testcases/core/directoryscanner.xml +++ b/src/etc/testcases/core/directoryscanner.xml @@ -1,14 +1,20 @@ + + - + + + + + @@ -19,4 +25,5 @@ - \ No newline at end of file + + diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 0bf8267ad..cea3b1e8d 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -35,6 +35,7 @@ import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.selectors.FileSelector; import org.apache.tools.ant.types.selectors.SelectorUtils; import org.apache.tools.ant.types.selectors.SelectorScanner; +import org.apache.tools.ant.types.resources.FileResource; import org.apache.tools.ant.util.FileUtils; /** @@ -555,11 +556,11 @@ public class DirectoryScanner * File.separatorChar. * * @param basedir The base directory to scan. - * Must not be null. */ public void setBasedir(String basedir) { - setBasedir(new File(basedir.replace('/', File.separatorChar).replace( - '\\', File.separatorChar))); + setBasedir(basedir == null ? (File) null + : new File(basedir.replace('/', File.separatorChar).replace( + '\\', File.separatorChar))); } /** @@ -567,7 +568,6 @@ public class DirectoryScanner * scanned recursively. * * @param basedir The base directory for scanning. - * Should not be null. */ public synchronized void setBasedir(File basedir) { this.basedir = basedir; @@ -577,7 +577,7 @@ public class DirectoryScanner * Return the base directory to be scanned. * This is the directory which is scanned recursively. * - * @return the base directory to be scanned + * @return the base directory to be scanned. */ public synchronized File getBasedir() { return basedir; @@ -741,13 +741,14 @@ public class DirectoryScanner } /** - * Scan the base directory for files which match at least one include - * pattern and don't match any exclude patterns. If there are selectors - * then the files must pass muster there, as well. + * Scan for files which match at least one include pattern and don't match + * any exclude patterns. If there are selectors then the files must pass + * muster there, as well. Scans under basedir, if set; otherwise the + * include patterns without leading wildcards specify the absolute paths of + * the files that may be included. * * @exception IllegalStateException if the base directory was set - * incorrectly (i.e. if it is null, doesn't exist, - * or isn't a directory). + * incorrectly (i.e. if it doesn't exist or isn't a directory). */ public void scan() throws IllegalStateException { synchronized (scanLock) { @@ -778,19 +779,22 @@ public class DirectoryScanner excludes = nullExcludes ? new String[0] : excludes; if (basedir == null) { - illegal = new IllegalStateException("No basedir set"); + // if no basedir and no includes, nothing to do: + if (nullIncludes) { + return; + } } else { if (!basedir.exists()) { illegal = new IllegalStateException("basedir " + basedir - + " does not exist"); + + " does not exist"); } if (!basedir.isDirectory()) { illegal = new IllegalStateException("basedir " + basedir - + " is not a directory"); + + " is not a directory"); + } + if (illegal != null) { + throw illegal; } - } - if (illegal != null) { - throw illegal; } if (isIncluded("")) { if (!isExcluded("")) { @@ -828,10 +832,21 @@ public class DirectoryScanner // put in the newroots vector the include patterns without // wildcard tokens for (int icounter = 0; icounter < includes.length; icounter++) { + if (FileUtils.isAbsolutePath(includes[icounter])) { + //skip abs. paths not under basedir, if set: + if (basedir != null + && !SelectorUtils.matchPatternStart(includes[icounter], + basedir.getAbsolutePath(), isCaseSensitive())) { + continue; + } + } else if (basedir == null) { + //skip non-abs. paths if basedir == null: + continue; + } newroots.put(SelectorUtils.rtrimWildcardTokens( includes[icounter]), includes[icounter]); } - if (newroots.containsKey("")) { + if (newroots.containsKey("") && basedir != null) { // we are going to scan everything anyway scandir(basedir, "", true); } else { @@ -840,13 +855,18 @@ public class DirectoryScanner Enumeration enum2 = newroots.keys(); File canonBase = null; - try { - canonBase = basedir.getCanonicalFile(); - } catch (IOException ex) { - throw new BuildException(ex); + if (basedir != null) { + try { + canonBase = basedir.getCanonicalFile(); + } catch (IOException ex) { + throw new BuildException(ex); + } } while (enum2.hasMoreElements()) { String currentelement = (String) enum2.nextElement(); + if (basedir == null && !FileUtils.isAbsolutePath(currentelement)) { + continue; + } String originalpattern = (String) newroots.get(currentelement); File myfile = new File(basedir, currentelement); @@ -855,15 +875,15 @@ public class DirectoryScanner // the results to show what's really on the disk, so // we need to double check. try { - File canonFile = myfile.getCanonicalFile(); - String path = FILE_UTILS.removeLeadingPath(canonBase, - canonFile); + String path = (basedir == null) + ? myfile.getCanonicalPath() + : FILE_UTILS.removeLeadingPath(canonBase, + myfile.getCanonicalFile()); if (!path.equals(currentelement) || ON_VMS) { myfile = findFile(basedir, currentelement, true); - if (myfile != null) { - currentelement = - FILE_UTILS.removeLeadingPath(basedir, - myfile); + if (myfile != null && basedir != null) { + currentelement = FILE_UTILS.removeLeadingPath( + basedir, myfile); } } } catch (IOException ex) { @@ -875,8 +895,9 @@ public class DirectoryScanner if (f != null && f.exists()) { // adapt currentelement to the case we've // actually found - currentelement = FILE_UTILS.removeLeadingPath(basedir, - f); + currentelement = (basedir == null) + ? f.getAbsolutePath() + : FILE_UTILS.removeLeadingPath(basedir, f); myfile = f; } } @@ -1475,9 +1496,7 @@ public class DirectoryScanner * @since Ant 1.5.2 */ public synchronized Resource getResource(String name) { - File f = FILE_UTILS.resolveFile(basedir, name); - return new Resource(name, f.exists(), f.lastModified(), - f.isDirectory(), f.length()); + return new FileResource(basedir, name); } /** @@ -1510,6 +1529,21 @@ public class DirectoryScanner * @since Ant 1.6.3 */ private File findFile(File base, String path, boolean cs) { + if (FileUtils.isAbsolutePath(path)) { + if (base == null) { + String[] s = FILE_UTILS.dissect(path); + base = new File(s[0]); + path = s[1]; + } else { + File f = FILE_UTILS.normalize(path); + String s = FILE_UTILS.removeLeadingPath(base, f); + if (s.equals(f.getAbsolutePath())) { + //removing base from path yields no change; path not child of base + return null; + } + path = s; + } + } return findFile(base, SelectorUtils.tokenizePath(path), cs); } @@ -1528,6 +1562,10 @@ public class DirectoryScanner if (pathElements.size() == 0) { return base; } + String current = (String) pathElements.remove(0); + if (base == null) { + return findFile(new File(current), pathElements, cs); + } if (!base.isDirectory()) { return null; } @@ -1536,8 +1574,6 @@ public class DirectoryScanner throw new BuildException("IO error scanning directory " + base.getAbsolutePath()); } - String current = (String) pathElements.remove(0); - boolean[] matchCase = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS; for (int i = 0; i < matchCase.length; i++) { for (int j = 0; j < files.length; j++) { diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java index 7483d8bbd..5c022a023 100644 --- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java +++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java @@ -22,6 +22,7 @@ import java.util.StringTokenizer; import java.util.Vector; import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.util.FileUtils; /** *

This is a utility class used by selectors and DirectoryScanner. The @@ -36,6 +37,7 @@ import org.apache.tools.ant.types.Resource; public final class SelectorUtils { private static SelectorUtils instance = new SelectorUtils(); + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); /** * Private Constructor @@ -164,15 +166,6 @@ public final class SelectorUtils { */ public static boolean matchPath(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); @@ -502,6 +495,11 @@ public final class SelectorUtils { */ 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()); @@ -513,6 +511,12 @@ public final class SelectorUtils { * Same as {@link #tokenizePath tokenizePath} but hopefully faster. */ private 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(); @@ -528,8 +532,14 @@ public final class SelectorUtils { if (len != start) { count++; } - String[] l = new String[count]; - count = 0; + 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) { @@ -643,7 +653,7 @@ public final class SelectorUtils { if (hasWildcards((String) v.elementAt(counter))) { break; } - if (counter > 0) { + if (counter > 0 && sb.charAt(sb.length() - 1) != File.separatorChar) { sb.append(File.separator); } sb.append((String) v.elementAt(counter)); diff --git a/src/testcases/org/apache/tools/ant/DirectoryScannerTest.java b/src/testcases/org/apache/tools/ant/DirectoryScannerTest.java index aefd92927..7d0600e64 100644 --- a/src/testcases/org/apache/tools/ant/DirectoryScannerTest.java +++ b/src/testcases/org/apache/tools/ant/DirectoryScannerTest.java @@ -415,6 +415,75 @@ public class DirectoryScannerTest extends BuildFileTest { assertFalse("scanned " + s, set.contains(s)); } + public void testAbsolute1() { + getProject().executeTarget("extended-setup"); + DirectoryScanner ds = new DirectoryScanner(); + String tmpdir = getProject().getBaseDir().getAbsolutePath().replace( + File.separatorChar, '/') + "/tmp"; + ds.setIncludes(new String[] {tmpdir + "/**/*"}); + ds.scan(); + compareFiles(ds, new String[] {tmpdir + "/alpha/beta/beta.xml", + tmpdir + "/alpha/beta/gamma/gamma.xml", + tmpdir + "/delta/delta.xml"}, + new String[] {tmpdir + "/alpha", + tmpdir + "/alpha/beta", + tmpdir + "/alpha/beta/gamma", + tmpdir + "/delta"}); + } + + public void testAbsolute2() { + getProject().executeTarget("setup"); + DirectoryScanner ds = new DirectoryScanner(); + ds.setIncludes(new String[] {"alpha/**", "alpha/beta/gamma/**"}); + ds.scan(); + String[] mt = new String[0]; + compareFiles(ds, mt, mt); + } + + public void testAbsolute3() { + getProject().executeTarget("extended-setup"); + DirectoryScanner ds = new DirectoryScanner(); + String tmpdir = getProject().getBaseDir().getAbsolutePath().replace( + File.separatorChar, '/') + "/tmp"; + ds.setIncludes(new String[] {tmpdir + "/**/*"}); + ds.setExcludes(new String[] {"**/alpha", + "**/delta/*"}); + ds.scan(); + compareFiles(ds, new String[] {tmpdir + "/alpha/beta/beta.xml", + tmpdir + "/alpha/beta/gamma/gamma.xml"}, + new String[] {tmpdir + "/alpha/beta", + tmpdir + "/alpha/beta/gamma", + tmpdir + "/delta"}); + } + + public void testAbsolute4() { + getProject().executeTarget("extended-setup"); + DirectoryScanner ds = new DirectoryScanner(); + String tmpdir = getProject().getBaseDir().getAbsolutePath().replace( + File.separatorChar, '/') + "/tmp"; + ds.setIncludes(new String[] {tmpdir + "/alpha/beta/**/*", + tmpdir + "/delta/*"}); + ds.setExcludes(new String[] {"**/beta.xml"}); + ds.scan(); + compareFiles(ds, new String[] {tmpdir + "/alpha/beta/gamma/gamma.xml", + tmpdir + "/delta/delta.xml"}, + new String[] {tmpdir + "/alpha/beta/gamma"}); + } + + public void testAbsolute5() { + //testing drive letter search from root: + if (!(Os.isFamily("dos") || Os.isFamily("netware"))) { + return; + } + DirectoryScanner ds = new DirectoryScanner(); + String pattern = new File(File.separator).getAbsolutePath().toUpperCase() + "*"; + ds.setIncludes(new String[] {pattern}); + ds.scan(); + //if this is our context we assume there must be something here: + assertTrue("should have at least one resident file", + ds.getIncludedFilesCount() + ds.getIncludedDirsCount() > 0); + } + private void compareFiles(DirectoryScanner ds, String[] expectedFiles, String[] expectedDirectories) { String includedFiles[] = ds.getIncludedFiles();