Browse Source

Synchronize scanning so that a scan initiated before the end of another scan

will block and the two will share results.  Likewise for slow scans.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277633 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 20 years ago
parent
commit
6c7f485943
1 changed files with 173 additions and 86 deletions
  1. +173
    -86
      src/main/org/apache/tools/ant/DirectoryScanner.java

+ 173
- 86
src/main/org/apache/tools/ant/DirectoryScanner.java View File

@@ -325,6 +325,41 @@ public class DirectoryScanner
*/ */
private boolean areNonPatternSetsReady = false; 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. * Sole constructor.
*/ */
@@ -528,7 +563,7 @@ public class DirectoryScanner
* @param basedir The base directory for scanning. * @param basedir The base directory for scanning.
* Should not be <code>null</code>. * Should not be <code>null</code>.
*/ */
public void setBasedir(File basedir) {
public synchronized void setBasedir(File basedir) {
this.basedir = basedir; this.basedir = basedir;
} }


@@ -538,7 +573,7 @@ public class DirectoryScanner
* *
* @return the base directory to be scanned * @return the base directory to be scanned
*/ */
public File getBasedir() {
public synchronized File getBasedir() {
return basedir; return basedir;
} }


@@ -548,9 +583,10 @@ public class DirectoryScanner
* @return whether or not the scanning is case sensitive. * @return whether or not the scanning is case sensitive.
* @since Ant 1.6 * @since Ant 1.6
*/ */
public boolean isCaseSensitive() {
public synchronized boolean isCaseSensitive() {
return isCaseSensitive; return isCaseSensitive;
} }

/** /**
* Set whether or not include and exclude patterns are matched * Set whether or not include and exclude patterns are matched
* in a case sensitive way. * in a case sensitive way.
@@ -558,7 +594,7 @@ public class DirectoryScanner
* @param isCaseSensitive whether or not the file system should be * @param isCaseSensitive whether or not the file system should be
* regarded as a case sensitive one. * regarded as a case sensitive one.
*/ */
public void setCaseSensitive(boolean isCaseSensitive) {
public synchronized void setCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive; this.isCaseSensitive = isCaseSensitive;
} }


@@ -569,7 +605,7 @@ public class DirectoryScanner
* *
* @since Ant 1.6 * @since Ant 1.6
*/ */
public boolean isFollowSymlinks() {
public synchronized boolean isFollowSymlinks() {
return followSymlinks; return followSymlinks;
} }


@@ -578,7 +614,7 @@ public class DirectoryScanner
* *
* @param followSymlinks whether or not symbolic links should be followed. * @param followSymlinks whether or not symbolic links should be followed.
*/ */
public void setFollowSymlinks(boolean followSymlinks) {
public synchronized void setFollowSymlinks(boolean followSymlinks) {
this.followSymlinks = followSymlinks; this.followSymlinks = followSymlinks;
} }


@@ -595,7 +631,7 @@ public class DirectoryScanner
* list is given, all elements must be * list is given, all elements must be
* non-<code>null</code>. * non-<code>null</code>.
*/ */
public void setIncludes(String[] includes) {
public synchronized void setIncludes(String[] includes) {
if (includes == null) { if (includes == null) {
this.includes = null; this.includes = null;
} else { } else {
@@ -618,7 +654,7 @@ public class DirectoryScanner
* should be excluded. If a non-<code>null</code> list is * should be excluded. If a non-<code>null</code> list is
* given, all elements must be non-<code>null</code>. * given, all elements must be non-<code>null</code>.
*/ */
public void setExcludes(String[] excludes) {
public synchronized void setExcludes(String[] excludes) {
if (excludes == null) { if (excludes == null) {
this.excludes = null; this.excludes = null;
} else { } else {
@@ -642,9 +678,9 @@ public class DirectoryScanner
* *
* @since Ant 1.7 * @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 String[] tmp = new String[excludes.length
+ this.excludes.length]; + this.excludes.length];
System.arraycopy(this.excludes, 0, tmp, 0, 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. * @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; this.selectors = selectors;
} }


@@ -694,7 +730,7 @@ public class DirectoryScanner
* @return <code>true</code> if all files and directories which have * @return <code>true</code> if all files and directories which have
* been found so far have been included. * been found so far have been included.
*/ */
public boolean isEverythingIncluded() {
public synchronized boolean isEverythingIncluded() {
return everythingIncluded; return everythingIncluded;
} }


@@ -708,51 +744,68 @@ public class DirectoryScanner
* or isn't a directory). * or isn't a directory).
*/ */
public void scan() throws IllegalStateException { 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 { } 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 * Top level invocation for a slow scan. A slow scan builds up a full
* list of excluded/included files/directories, whereas a fast scan * 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. * Returns immediately if a slow scan has already been completed.
*/ */
protected void slowScan() { 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 * @return the names of the files which matched at least one of the
* include patterns and none of the exclude patterns. * include patterns and none of the exclude patterns.
*/ */
public String[] getIncludedFiles() {
public synchronized String[] getIncludedFiles() {
if (filesIncluded == null) { if (filesIncluded == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -1194,7 +1281,7 @@ public class DirectoryScanner
* @return <code>int</code>. * @return <code>int</code>.
* @since Ant 1.6.3 * @since Ant 1.6.3
*/ */
public int getIncludedFilesCount() {
public synchronized int getIncludedFilesCount() {
if (filesIncluded == null) { if (filesIncluded == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -1211,7 +1298,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getNotIncludedFiles() {
public synchronized String[] getNotIncludedFiles() {
slowScan(); slowScan();
String[] files = new String[filesNotIncluded.size()]; String[] files = new String[filesNotIncluded.size()];
filesNotIncluded.copyInto(files); filesNotIncluded.copyInto(files);
@@ -1229,7 +1316,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getExcludedFiles() {
public synchronized String[] getExcludedFiles() {
slowScan(); slowScan();
String[] files = new String[filesExcluded.size()]; String[] files = new String[filesExcluded.size()];
filesExcluded.copyInto(files); filesExcluded.copyInto(files);
@@ -1247,7 +1334,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getDeselectedFiles() {
public synchronized String[] getDeselectedFiles() {
slowScan(); slowScan();
String[] files = new String[filesDeselected.size()]; String[] files = new String[filesDeselected.size()];
filesDeselected.copyInto(files); filesDeselected.copyInto(files);
@@ -1262,7 +1349,7 @@ public class DirectoryScanner
* @return the names of the directories which matched at least one of the * @return the names of the directories which matched at least one of the
* include patterns and none of the exclude patterns. * include patterns and none of the exclude patterns.
*/ */
public String[] getIncludedDirectories() {
public synchronized String[] getIncludedDirectories() {
if (dirsIncluded == null) { if (dirsIncluded == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -1277,7 +1364,7 @@ public class DirectoryScanner
* @return <code>int</code>. * @return <code>int</code>.
* @since Ant 1.6.3 * @since Ant 1.6.3
*/ */
public int getIncludedDirsCount() {
public synchronized int getIncludedDirsCount() {
if (dirsIncluded == null) { if (dirsIncluded == null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -1294,7 +1381,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getNotIncludedDirectories() {
public synchronized String[] getNotIncludedDirectories() {
slowScan(); slowScan();
String[] directories = new String[dirsNotIncluded.size()]; String[] directories = new String[dirsNotIncluded.size()];
dirsNotIncluded.copyInto(directories); dirsNotIncluded.copyInto(directories);
@@ -1312,7 +1399,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getExcludedDirectories() {
public synchronized String[] getExcludedDirectories() {
slowScan(); slowScan();
String[] directories = new String[dirsExcluded.size()]; String[] directories = new String[dirsExcluded.size()];
dirsExcluded.copyInto(directories); dirsExcluded.copyInto(directories);
@@ -1330,7 +1417,7 @@ public class DirectoryScanner
* *
* @see #slowScan * @see #slowScan
*/ */
public String[] getDeselectedDirectories() {
public synchronized String[] getDeselectedDirectories() {
slowScan(); slowScan();
String[] directories = new String[dirsDeselected.size()]; String[] directories = new String[dirsDeselected.size()];
dirsDeselected.copyInto(directories); dirsDeselected.copyInto(directories);
@@ -1340,7 +1427,7 @@ public class DirectoryScanner
/** /**
* Add default exclusions to the current exclusions set. * Add default exclusions to the current exclusions set.
*/ */
public void addDefaultExcludes() {
public synchronized void addDefaultExcludes() {
int excludesLength = excludes == null ? 0 : excludes.length; int excludesLength = excludes == null ? 0 : excludes.length;
String[] newExcludes; String[] newExcludes;
newExcludes = new String[excludesLength + defaultExcludes.size()]; newExcludes = new String[excludesLength + defaultExcludes.size()];
@@ -1363,7 +1450,7 @@ public class DirectoryScanner
* @return the resource with the given name. * @return the resource with the given name.
* @since Ant 1.5.2 * @since Ant 1.5.2
*/ */
public Resource getResource(String name) {
public synchronized Resource getResource(String name) {
File f = FILE_UTILS.resolveFile(basedir, name); File f = FILE_UTILS.resolveFile(basedir, name);
return new Resource(name, f.exists(), f.lastModified(), return new Resource(name, f.exists(), f.lastModified(),
f.isDirectory(), f.length()); f.isDirectory(), f.length());


Loading…
Cancel
Save