diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java
index cc506b983..eb46a7762 100644
--- a/src/main/org/apache/tools/ant/DirectoryScanner.java
+++ b/src/main/org/apache/tools/ant/DirectoryScanner.java
@@ -133,14 +133,14 @@ import java.util.*;
*
* @author Arnout J. Kuiper ajkuiper@wxs.nl
*/
-public class DirectoryScanner {
+public class DirectoryScanner implements FileScanner {
/**
* Patterns that should be excluded by default.
*
* @see #addDefaultExcludes()
*/
- private final static String[] DEFAULTEXCLUDES = {
+ protected final static String[] DEFAULTEXCLUDES = {
"**/*~",
"**/#*#",
"**/%*%",
@@ -152,56 +152,56 @@ public class DirectoryScanner {
/**
* The base directory which should be scanned.
*/
- private File basedir;
+ protected File basedir;
/**
* The patterns for the files that should be included.
*/
- private String[] includes;
+ protected String[] includes;
/**
* The patterns for the files that should be excluded.
*/
- private String[] excludes;
+ protected String[] excludes;
/**
* The files that where found and matched at least one includes, and matched
* no excludes.
*/
- private Vector filesIncluded;
+ protected Vector filesIncluded;
/**
* The files that where found and did not match any includes.
*/
- private Vector filesNotIncluded;
+ protected Vector filesNotIncluded;
/**
* The files that where found and matched at least one includes, and also
* matched at least one excludes.
*/
- private Vector filesExcluded;
+ protected Vector filesExcluded;
/**
* The directories that where found and matched at least one includes, and
* matched no excludes.
*/
- private Vector dirsIncluded;
+ protected Vector dirsIncluded;
/**
* The directories that where found and did not match any includes.
*/
- private Vector dirsNotIncluded;
+ protected Vector dirsNotIncluded;
/**
* The files that where found and matched at least one includes, and also
* matched at least one excludes.
*/
- private Vector dirsExcluded;
+ protected Vector dirsExcluded;
/**
* Have the Vectors holding our results been built by a slow scan?
*/
- private boolean haveSlowResults = false;
+ protected boolean haveSlowResults = false;
/**
* Constructor.
@@ -221,7 +221,7 @@ public class DirectoryScanner {
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
*/
- private static boolean matchPatternStart(String pattern, String str) {
+ protected static boolean matchPatternStart(String pattern, String str) {
// 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
@@ -283,7 +283,7 @@ public class DirectoryScanner {
* @return true
when the pattern matches against the string.
* false
otherwise.
*/
- private static boolean matchPath(String pattern, String str) {
+ protected static boolean matchPath(String pattern, String str) {
// 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
@@ -423,7 +423,7 @@ strLoop:
* @return true
when the string matches against the pattern,
* false
otherwise.
*/
- private static boolean match(String pattern, String str) {
+ protected static boolean match(String pattern, String str) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
int patIdxStart = 0;
@@ -682,7 +682,7 @@ strLoop:
*
*
Returns immediately if a slow scan has already been requested.
*/
- private void slowScan() {
+ protected void slowScan() {
if (haveSlowResults) {
return;
}
@@ -725,7 +725,7 @@ strLoop:
* @see #dirsNotIncluded
* @see #dirsExcluded
*/
- private void scandir(File dir, String vpath, boolean fast) {
+ protected void scandir(File dir, String vpath, boolean fast) {
String[] newfiles = dir.list();
if (newfiles == null) {
@@ -785,7 +785,7 @@ strLoop:
* @return true
when the name matches against at least one
* include pattern, false
otherwise.
*/
- private boolean isIncluded(String name) {
+ protected boolean isIncluded(String name) {
for (int i = 0; i < includes.length; i++) {
if (matchPath(includes[i],name)) {
return true;
@@ -801,7 +801,7 @@ strLoop:
* @return true
when the name matches against at least one
* include pattern, false
otherwise.
*/
- private boolean couldHoldIncluded(String name) {
+ protected boolean couldHoldIncluded(String name) {
for (int i = 0; i < includes.length; i++) {
if (matchPatternStart(includes[i],name)) {
return true;
@@ -817,7 +817,7 @@ strLoop:
* @return true
when the name matches against at least one
* exclude pattern, false
otherwise.
*/
- private boolean isExcluded(String name) {
+ protected boolean isExcluded(String name) {
for (int i = 0; i < excludes.length; i++) {
if (matchPath(excludes[i],name)) {
return true;
diff --git a/src/main/org/apache/tools/ant/FileScanner.java b/src/main/org/apache/tools/ant/FileScanner.java
new file mode 100644
index 000000000..faa80af11
--- /dev/null
+++ b/src/main/org/apache/tools/ant/FileScanner.java
@@ -0,0 +1,102 @@
+package org.apache.tools.ant;
+
+import java.io.*;
+
+/**
+ * An interface used to describe the actions required by any type of
+ * directory scanner.
+ */
+public interface FileScanner {
+ /**
+ * Adds an array with default exclusions to the current exclusions set.
+ *
+ */
+ public void addDefaultExcludes();
+ /**
+ * Gets the basedir that is used for scanning. This is the directory that
+ * is scanned recursively.
+ *
+ * @return the basedir that is used for scanning
+ */
+ public File getBasedir();
+ /**
+ * Get the names of the directories that matched at least one of the include
+ * patterns, an matched also at least one of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+ public String[] getExcludedDirectories();
+ /**
+ * Get the names of the files that matched at least one of the include
+ * patterns, an matched also at least one of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+ public String[] getExcludedFiles();
+ /**
+ * Get the names of the directories that matched at least one of the include
+ * patterns, an matched none of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+ public String[] getIncludedDirectories();
+ /**
+ * Get the names of the files that matched at least one of the include
+ * patterns, an matched none of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+ public String[] getIncludedFiles();
+ /**
+ * Get the names of the directories that matched at none of the include
+ * patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+ public String[] getNotIncludedDirectories();
+ /**
+ * Get the names of the files that matched at none of the include patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+ public String[] getNotIncludedFiles();
+ /**
+ * Scans the base directory for files that match at least one include
+ * pattern, and don't match any exclude patterns.
+ *
+ * @exception IllegalStateException when basedir was set incorrecly
+ */
+ public void scan();
+ /**
+ * Sets the basedir for scanning. This is the directory that is scanned
+ * recursively.
+ *
+ * @param basedir the (non-null) basedir for scanning
+ */
+ public void setBasedir(String basedir);
+ /**
+ * Sets the basedir for scanning. This is the directory that is scanned
+ * recursively.
+ *
+ * @param basedir the basedir for scanning
+ */
+ public void setBasedir(File basedir);
+ /**
+ * Sets the set of exclude patterns to use.
+ *
+ * @param excludes list of exclude patterns
+ */
+ public void setExcludes(String[] excludes);
+ /**
+ * Sets the set of include patterns to use.
+ *
+ * @param includes list of include patterns
+ */
+ public void setIncludes(String[] includes);
+}
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/FTP.java b/src/main/org/apache/tools/ant/taskdefs/optional/FTP.java
index 17c44e982..e5724f199 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/FTP.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/FTP.java
@@ -62,21 +62,31 @@ import java.util.*;
import com.oroinc.net.ftp.*;
/**
- * Sends files to an FTP server. Also intended to retrieve remote files,
- * but this has not yet been implemented
+ * Basic FTP client that performs the following actions:
+ *
filename
may contain a relative path specification.
+ * The file will then be retreived using the entire relative path spec -
+ * no attempt is made to change directories. It is anticipated that this may
+ * eventually cause problems with some FTP servers, but it simplifies
+ * the coding.
+ */
+ protected void getFile(FTPClient ftp, String dir, String filename)
+ throws IOException, BuildException
+ {
+ OutputStream outstream = null;
+ try
+ {
+ File file = project.resolveFile(new File(dir, filename).getPath());
+
+ if (newerOnly && isUpToDate(ftp, file, resolveFile(filename)))
+ return;
+
+ if (verbose)
+ {
+ log("transferring " + filename + " to " + file.getAbsolutePath());
+ }
+
+
+ File pdir = new File(file.getParent()); // stay 1.1 compatible
+ if (!pdir.exists()) {
+ pdir.mkdirs();
+ }
+ outstream = new BufferedOutputStream(new FileOutputStream(file));
+ ftp.retrieveFile(resolveFile(filename), outstream);
+
+ if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
+ {
+ throw new BuildException(
+"could not transfer file: " +
+ ftp.getReplyString());
+ }
+
+ log("File " + file.getAbsolutePath() + " copied from " + server,
+ Project.MSG_VERBOSE);
+
+ transferred++;
+ }
+ finally
+ {
+ if (outstream != null)
+ {
+ try
+ {
+ outstream.close();
+ }
+ catch(IOException ex)
+ {
+ // ignore it
+ }
+ }
+ }
+ }
+
+ /**
+ * List information about a single file from the remote host.
+ * filename
may contain a relative path specification.
+ * The file listing will then be retrieved using the entire relative path spec
+ * - no attempt is made to change directories. It is anticipated that this may
+ * eventually cause problems with some FTP servers, but it simplifies
+ * the coding.
+ */
+ protected void listFile(FTPClient ftp, BufferedWriter bw, String filename)
+ throws IOException, BuildException
+ {
+ if (verbose) {
+ log("listing " + filename);
+ }
+
+ FTPFile ftpfile = ftp.listFiles(resolveFile(filename))[0];
+ bw.write(ftpfile.toString());
+ bw.newLine();
+
+ transferred++;
+ }
+
/**
* Runs the task.
*/
@@ -499,16 +794,9 @@ public class FTP
}
}
- log("transferring files");
+ log(ACTION_STRS[action] + " files");
+ transferFiles(ftp);
- if (action == SEND_FILES)
- {
- sendFiles(ftp);
- }
- else
- {
- throw new BuildException("getting files is not yet supported");
- }
}
catch(IOException ex)
{
diff --git a/src/main/org/apache/tools/ant/types/FileSet.java b/src/main/org/apache/tools/ant/types/FileSet.java
index a1c610cb6..a543e8ddf 100644
--- a/src/main/org/apache/tools/ant/types/FileSet.java
+++ b/src/main/org/apache/tools/ant/types/FileSet.java
@@ -55,6 +55,7 @@
package org.apache.tools.ant.types;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
@@ -198,6 +199,16 @@ public class FileSet {
}
DirectoryScanner ds = new DirectoryScanner();
+ setupDirectoryScanner(ds, p);
+ ds.scan();
+ return ds;
+ }
+
+ public void setupDirectoryScanner(FileScanner ds, Project p) {
+ if (ds == null) {
+ throw new IllegalArgumentException("ds cannot be null");
+ }
+
ds.setBasedir(dir);
for (int i=0; i