diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java
index 638b61512..491192717 100644
--- a/src/main/org/apache/tools/ant/DirectoryScanner.java
+++ b/src/main/org/apache/tools/ant/DirectoryScanner.java
@@ -325,6 +325,41 @@ public class DirectoryScanner
*/
private boolean areNonPatternSetsReady = false;
+ /**
+ * Scanning flag.
+ *
+ * @since Ant 1.7
+ */
+ private boolean scanning = false;
+
+ /**
+ * Scanning lock.
+ *
+ * @since Ant 1.7
+ */
+ private Object scanLock = new Object();
+
+ /**
+ * Slow scanning flag.
+ *
+ * @since Ant 1.7
+ */
+ private boolean slowScanning = false;
+
+ /**
+ * Slow scanning lock.
+ *
+ * @since Ant 1.7
+ */
+ private Object slowScanLock = new Object();
+
+ /**
+ * Exception thrown during scan.
+ *
+ * @since Ant 1.7
+ */
+ private IllegalStateException illegal = null;
+
/**
* Sole constructor.
*/
@@ -528,7 +563,7 @@ public class DirectoryScanner
* @param basedir The base directory for scanning.
* Should not be null
.
*/
- public void setBasedir(File basedir) {
+ public synchronized void setBasedir(File basedir) {
this.basedir = basedir;
}
@@ -538,7 +573,7 @@ public class DirectoryScanner
*
* @return the base directory to be scanned
*/
- public File getBasedir() {
+ public synchronized File getBasedir() {
return basedir;
}
@@ -548,9 +583,10 @@ public class DirectoryScanner
* @return whether or not the scanning is case sensitive.
* @since Ant 1.6
*/
- public boolean isCaseSensitive() {
+ public synchronized boolean isCaseSensitive() {
return isCaseSensitive;
}
+
/**
* Set whether or not include and exclude patterns are matched
* in a case sensitive way.
@@ -558,7 +594,7 @@ public class DirectoryScanner
* @param isCaseSensitive whether or not the file system should be
* regarded as a case sensitive one.
*/
- public void setCaseSensitive(boolean isCaseSensitive) {
+ public synchronized void setCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive;
}
@@ -569,7 +605,7 @@ public class DirectoryScanner
*
* @since Ant 1.6
*/
- public boolean isFollowSymlinks() {
+ public synchronized boolean isFollowSymlinks() {
return followSymlinks;
}
@@ -578,7 +614,7 @@ public class DirectoryScanner
*
* @param followSymlinks whether or not symbolic links should be followed.
*/
- public void setFollowSymlinks(boolean followSymlinks) {
+ public synchronized void setFollowSymlinks(boolean followSymlinks) {
this.followSymlinks = followSymlinks;
}
@@ -595,7 +631,7 @@ public class DirectoryScanner
* list is given, all elements must be
* non-null
.
*/
- public void setIncludes(String[] includes) {
+ public synchronized void setIncludes(String[] includes) {
if (includes == null) {
this.includes = null;
} else {
@@ -618,7 +654,7 @@ public class DirectoryScanner
* should be excluded. If a non-null
list is
* given, all elements must be non-null
.
*/
- public void setExcludes(String[] excludes) {
+ public synchronized void setExcludes(String[] excludes) {
if (excludes == null) {
this.excludes = null;
} else {
@@ -642,9 +678,9 @@ public class DirectoryScanner
*
* @since Ant 1.7
*/
- public void addExcludes(String[] excludes) {
- if (excludes != null) {
- if (this.excludes != null) {
+ public synchronized void addExcludes(String[] excludes) {
+ if (excludes != null && excludes.length > 0) {
+ if (this.excludes != null && this.excludes.length > 0) {
String[] tmp = new String[excludes.length
+ this.excludes.length];
System.arraycopy(this.excludes, 0, tmp, 0,
@@ -683,7 +719,7 @@ public class DirectoryScanner
*
* @param selectors specifies the selectors to be invoked on a scan.
*/
- public void setSelectors(FileSelector[] selectors) {
+ public synchronized void setSelectors(FileSelector[] selectors) {
this.selectors = selectors;
}
@@ -694,7 +730,7 @@ public class DirectoryScanner
* @return true
if all files and directories which have
* been found so far have been included.
*/
- public boolean isEverythingIncluded() {
+ public synchronized boolean isEverythingIncluded() {
return everythingIncluded;
}
@@ -708,51 +744,68 @@ public class DirectoryScanner
* or isn't a directory).
*/
public void scan() throws IllegalStateException {
- if (basedir == null) {
- throw new IllegalStateException("No basedir set");
- }
- if (!basedir.exists()) {
- throw new IllegalStateException("basedir " + basedir
- + " does not exist");
- }
- if (!basedir.isDirectory()) {
- throw new IllegalStateException("basedir " + basedir
- + " is not a directory");
- }
-
- if (includes == null) {
- // No includes supplied, so set it to 'matches all'
- includes = new String[1];
- includes[0] = "**";
- }
- if (excludes == null) {
- excludes = new String[0];
+ synchronized (scanLock) {
+ if (scanning) {
+ while (scanning) {
+ try {
+ scanLock.wait();
+ } catch (InterruptedException e) {
+ continue;
+ }
+ }
+ if (illegal != null) {
+ throw illegal;
+ }
+ return;
+ }
+ scanning = true;
}
-
- filesIncluded = new Vector();
- filesNotIncluded = new Vector();
- filesExcluded = new Vector();
- filesDeselected = new Vector();
- dirsIncluded = new Vector();
- dirsNotIncluded = new Vector();
- dirsExcluded = new Vector();
- dirsDeselected = new Vector();
-
- if (isIncluded("")) {
- if (!isExcluded("")) {
- if (isSelected("", basedir)) {
- dirsIncluded.addElement("");
+ try {
+ synchronized (this) {
+ illegal = null;
+ clearResults();
+
+ // set in/excludes to reasonable defaults if needed:
+ boolean nullIncludes = (includes == null);
+ includes = nullIncludes ? new String[] {"**"} : includes;
+ boolean nullExcludes = (excludes == null);
+ excludes = nullExcludes ? new String[0] : excludes;
+
+ if (basedir == null) {
+ throw new IllegalStateException("No basedir set");
+ }
+ if (!basedir.exists()) {
+ throw new IllegalStateException("basedir " + basedir
+ + " does not exist");
+ }
+ if (!basedir.isDirectory()) {
+ throw new IllegalStateException("basedir " + basedir
+ + " is not a directory");
+ }
+ if (isIncluded("")) {
+ if (!isExcluded("")) {
+ if (isSelected("", basedir)) {
+ dirsIncluded.addElement("");
+ } else {
+ dirsDeselected.addElement("");
+ }
+ } else {
+ dirsExcluded.addElement("");
+ }
} else {
- dirsDeselected.addElement("");
+ dirsNotIncluded.addElement("");
}
- } else {
- dirsExcluded.addElement("");
+ checkIncludePatterns();
+ clearCaches();
+ includes = nullIncludes ? null : includes;
+ excludes = nullExcludes ? null : excludes;
+ }
+ } finally {
+ synchronized (scanLock) {
+ scanning = false;
+ scanLock.notifyAll();
}
- } else {
- dirsNotIncluded.addElement("");
}
- checkIncludePatterns();
- clearCaches();
}
/**
@@ -858,6 +911,21 @@ public class DirectoryScanner
}
}
+ /**
+ * Clear the result caches for a scan.
+ */
+ protected synchronized void clearResults() {
+ filesIncluded = new Vector();
+ filesNotIncluded = new Vector();
+ filesExcluded = new Vector();
+ filesDeselected = new Vector();
+ dirsIncluded = new Vector();
+ dirsNotIncluded = new Vector();
+ dirsExcluded = new Vector();
+ dirsDeselected = new Vector();
+ everythingIncluded = (basedir != null);
+ }
+
/**
* Top level invocation for a slow scan. A slow scan builds up a full
* list of excluded/included files/directories, whereas a fast scan
@@ -867,31 +935,50 @@ public class DirectoryScanner
* Returns immediately if a slow scan has already been completed.
*/
protected void slowScan() {
- if (haveSlowResults) {
- return;
- }
-
- String[] excl = new String[dirsExcluded.size()];
- dirsExcluded.copyInto(excl);
-
- String[] notIncl = new String[dirsNotIncluded.size()];
- dirsNotIncluded.copyInto(notIncl);
-
- for (int i = 0; i < excl.length; i++) {
- if (!couldHoldIncluded(excl[i])) {
- scandir(new File(basedir, excl[i]),
- excl[i] + File.separator, false);
+ synchronized (slowScanLock) {
+ if (haveSlowResults) {
+ return;
}
+ if (slowScanning) {
+ while (slowScanning) {
+ try {
+ slowScanLock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ return;
+ }
+ slowScanning = true;
}
-
- for (int i = 0; i < notIncl.length; i++) {
- if (!couldHoldIncluded(notIncl[i])) {
- scandir(new File(basedir, notIncl[i]),
- notIncl[i] + File.separator, false);
+ try {
+ synchronized (this) {
+
+ String[] excl = new String[dirsExcluded.size()];
+ dirsExcluded.copyInto(excl);
+
+ String[] notIncl = new String[dirsNotIncluded.size()];
+ dirsNotIncluded.copyInto(notIncl);
+
+ for (int i = 0; i < excl.length; i++) {
+ if (!couldHoldIncluded(excl[i])) {
+ scandir(new File(basedir, excl[i]),
+ excl[i] + File.separator, false);
+ }
+ }
+ for (int i = 0; i < notIncl.length; i++) {
+ if (!couldHoldIncluded(notIncl[i])) {
+ scandir(new File(basedir, notIncl[i]),
+ notIncl[i] + File.separator, false);
+ }
+ }
+ }
+ } finally {
+ synchronized (slowScanLock) {
+ haveSlowResults = true;
+ slowScanning = false;
+ slowScanLock.notifyAll();
}
}
-
- haveSlowResults = true;
}
/**
@@ -1179,7 +1266,7 @@ public class DirectoryScanner
* @return the names of the files which matched at least one of the
* include patterns and none of the exclude patterns.
*/
- public String[] getIncludedFiles() {
+ public synchronized String[] getIncludedFiles() {
if (filesIncluded == null) {
throw new IllegalStateException();
}
@@ -1194,7 +1281,7 @@ public class DirectoryScanner
* @return int
.
* @since Ant 1.6.3
*/
- public int getIncludedFilesCount() {
+ public synchronized int getIncludedFilesCount() {
if (filesIncluded == null) {
throw new IllegalStateException();
}
@@ -1211,7 +1298,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getNotIncludedFiles() {
+ public synchronized String[] getNotIncludedFiles() {
slowScan();
String[] files = new String[filesNotIncluded.size()];
filesNotIncluded.copyInto(files);
@@ -1229,7 +1316,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getExcludedFiles() {
+ public synchronized String[] getExcludedFiles() {
slowScan();
String[] files = new String[filesExcluded.size()];
filesExcluded.copyInto(files);
@@ -1247,7 +1334,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getDeselectedFiles() {
+ public synchronized String[] getDeselectedFiles() {
slowScan();
String[] files = new String[filesDeselected.size()];
filesDeselected.copyInto(files);
@@ -1262,7 +1349,7 @@ public class DirectoryScanner
* @return the names of the directories which matched at least one of the
* include patterns and none of the exclude patterns.
*/
- public String[] getIncludedDirectories() {
+ public synchronized String[] getIncludedDirectories() {
if (dirsIncluded == null) {
throw new IllegalStateException();
}
@@ -1277,7 +1364,7 @@ public class DirectoryScanner
* @return int
.
* @since Ant 1.6.3
*/
- public int getIncludedDirsCount() {
+ public synchronized int getIncludedDirsCount() {
if (dirsIncluded == null) {
throw new IllegalStateException();
}
@@ -1294,7 +1381,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getNotIncludedDirectories() {
+ public synchronized String[] getNotIncludedDirectories() {
slowScan();
String[] directories = new String[dirsNotIncluded.size()];
dirsNotIncluded.copyInto(directories);
@@ -1312,7 +1399,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getExcludedDirectories() {
+ public synchronized String[] getExcludedDirectories() {
slowScan();
String[] directories = new String[dirsExcluded.size()];
dirsExcluded.copyInto(directories);
@@ -1330,7 +1417,7 @@ public class DirectoryScanner
*
* @see #slowScan
*/
- public String[] getDeselectedDirectories() {
+ public synchronized String[] getDeselectedDirectories() {
slowScan();
String[] directories = new String[dirsDeselected.size()];
dirsDeselected.copyInto(directories);
@@ -1340,7 +1427,7 @@ public class DirectoryScanner
/**
* Add default exclusions to the current exclusions set.
*/
- public void addDefaultExcludes() {
+ public synchronized void addDefaultExcludes() {
int excludesLength = excludes == null ? 0 : excludes.length;
String[] newExcludes;
newExcludes = new String[excludesLength + defaultExcludes.size()];
@@ -1363,7 +1450,7 @@ public class DirectoryScanner
* @return the resource with the given name.
* @since Ant 1.5.2
*/
- public Resource getResource(String name) {
+ 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());