Browse Source

fix behavior on case insensitive file systems

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274892 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
1eafac93d3
1 changed files with 106 additions and 17 deletions
  1. +106
    -17
      src/main/org/apache/tools/ant/DirectoryScanner.java

+ 106
- 17
src/main/org/apache/tools/ant/DirectoryScanner.java View File

@@ -56,9 +56,11 @@ package org.apache.tools.ant;


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;


import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.ResourceFactory;
@@ -701,27 +703,40 @@ public class DirectoryScanner
} }


Enumeration enum2 = newroots.keys(); Enumeration enum2 = newroots.keys();

File canonBase = null;
try {
canonBase = basedir.getCanonicalFile();
} catch (IOException ex) {
throw new BuildException(ex);
}

while (enum2.hasMoreElements()) { while (enum2.hasMoreElements()) {
String currentelement = (String) enum2.nextElement(); String currentelement = (String) enum2.nextElement();
String originalpattern = (String) newroots.get(currentelement); String originalpattern = (String) newroots.get(currentelement);
File myfile = new File(basedir, currentelement); File myfile = new File(basedir, currentelement);
// we need to call getCanonicalFile here for DOS systems
// the reason being that otherwise File will be influenced
// by the case of currentelement, which we want to avoid
if (Os.isFamily("dos") && myfile.exists()) {

if (myfile.exists()) {
// may be on a case insensitive file system. We want
// the results to show what's really on the disk, so
// we need to double check.
try { try {
// getAbsoluteFile() is not enough here unfortunately
myfile = myfile.getCanonicalFile();
}
catch (Exception ex) {
File canonFile = myfile.getCanonicalFile();
String path = fileUtils.removeLeadingPath(canonBase,
canonFile);
if (!path.equals(currentelement)) {
myfile = findFile(basedir, currentelement);
if (myfile != null) {
currentelement =
fileUtils.removeLeadingPath(basedir, myfile);
}
}
} catch (IOException ex) {
throw new BuildException(ex); throw new BuildException(ex);
} }
// the variable currentelement is actually telling what
// the scan results will contain
currentelement = fileUtils.removeLeadingPath(basedir,
myfile);
} }
if (!myfile.exists() && !isCaseSensitive) {
if ((myfile == null || !myfile.exists()) && !isCaseSensitive) {
File f = findFileCaseInsensitive(basedir, currentelement); File f = findFileCaseInsensitive(basedir, currentelement);
if (f.exists()) { if (f.exists()) {
// adapt currentelement to the case we've actually found // adapt currentelement to the case we've actually found
@@ -731,7 +746,7 @@ public class DirectoryScanner
} }
} }


if (myfile.exists()) {
if (myfile != null && myfile.exists()) {
if (!followSymlinks && isSymlink(basedir, currentelement)) { if (!followSymlinks && isSymlink(basedir, currentelement)) {
continue; continue;
} }
@@ -762,6 +777,7 @@ public class DirectoryScanner
} }
} }
} }
fileListMap.clear();
} }


/** /**
@@ -1175,6 +1191,30 @@ public class DirectoryScanner
f.isDirectory()); f.isDirectory());
} }


/**
* temporary table to speed up the various scanning methods below
*
* @since Ant 1.6
*/
private Map fileListMap = new HashMap();

/**
* Returns a cached result of list performed on file, if
* available. Invokes the method and caches the result otherwise.
*
* @since Ant 1.6
*/
private String[] list(File file) {
String[] files = (String[]) fileListMap.get(file);
if (files == null) {
files = file.list();
if (files != null) {
fileListMap.put(file, files);
}
}
return files;
}

/** /**
* From <code>base</code> traverse the filesystem in a case * From <code>base</code> traverse the filesystem in a case
* insensitive manner in order to find a file that matches the * insensitive manner in order to find a file that matches the
@@ -1208,12 +1248,18 @@ public class DirectoryScanner
if (!base.isDirectory()) { if (!base.isDirectory()) {
return null; return null;
} }
String[] files = base.list();
String[] files = list(base);
if (files == null) { if (files == null) {
throw new BuildException("IO error scanning directory " throw new BuildException("IO error scanning directory "
+ base.getAbsolutePath()); + base.getAbsolutePath());
} }
String current = (String) pathElements.remove(0); String current = (String) pathElements.remove(0);
for (int i = 0; i < files.length; i++) {
if (files[i].equals(current)) {
base = new File(base, files[i]);
return findFileCaseInsensitive(base, pathElements);
}
}
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase(current)) { if (files[i].equalsIgnoreCase(current)) {
base = new File(base, files[i]); base = new File(base, files[i]);
@@ -1224,6 +1270,49 @@ public class DirectoryScanner
return null; return null;
} }


/**
* From <code>base</code> traverse the filesystem in order to find
* a file that matches the given name.
*
* @return File object that points to the file in question or null.
*
* @since Ant 1.6
*/
private File findFile(File base, String path) {
return findFile(base, SelectorUtils.tokenizePath(path));
}

/**
* From <code>base</code> traverse the filesystem in order to find
* a file that matches the given stack of names.
*
* @return File object that points to the file in question or null.
*
* @since Ant 1.6
*/
private File findFile(File base, Vector pathElements) {
if (pathElements.size() == 0) {
return base;
} else {
if (!base.isDirectory()) {
return null;
}
String[] files = list(base);
if (files == null) {
throw new BuildException("IO error scanning directory "
+ base.getAbsolutePath());
}
String current = (String) pathElements.remove(0);
for (int i = 0; i < files.length; i++) {
if (files[i].equals(current)) {
base = new File(base, files[i]);
return findFile(base, pathElements);
}
}
}
return null;
}

/** /**
* Do we have to traverse a symlink when trying to reach path from * Do we have to traverse a symlink when trying to reach path from
* basedir? * basedir?


Loading…
Cancel
Save