Allow DirectoryScanner to work with remote directories. Submitted by: Glenn McAllister <glennm@ca.ibm.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267934 13f79535-47bb-0310-9956-ffa450edef68master
@@ -133,14 +133,14 @@ import java.util.*; | |||||
* | * | ||||
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> | * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> | ||||
*/ | */ | ||||
public class DirectoryScanner { | |||||
public class DirectoryScanner implements FileScanner { | |||||
/** | /** | ||||
* Patterns that should be excluded by default. | * Patterns that should be excluded by default. | ||||
* | * | ||||
* @see #addDefaultExcludes() | * @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. | * The base directory which should be scanned. | ||||
*/ | */ | ||||
private File basedir; | |||||
protected File basedir; | |||||
/** | /** | ||||
* The patterns for the files that should be included. | * The patterns for the files that should be included. | ||||
*/ | */ | ||||
private String[] includes; | |||||
protected String[] includes; | |||||
/** | /** | ||||
* The patterns for the files that should be excluded. | * 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 | * The files that where found and matched at least one includes, and matched | ||||
* no excludes. | * no excludes. | ||||
*/ | */ | ||||
private Vector filesIncluded; | |||||
protected Vector filesIncluded; | |||||
/** | /** | ||||
* The files that where found and did not match any includes. | * 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 | * The files that where found and matched at least one includes, and also | ||||
* matched at least one excludes. | * matched at least one excludes. | ||||
*/ | */ | ||||
private Vector filesExcluded; | |||||
protected Vector filesExcluded; | |||||
/** | /** | ||||
* The directories that where found and matched at least one includes, and | * The directories that where found and matched at least one includes, and | ||||
* matched no excludes. | * matched no excludes. | ||||
*/ | */ | ||||
private Vector dirsIncluded; | |||||
protected Vector dirsIncluded; | |||||
/** | /** | ||||
* The directories that where found and did not match any includes. | * 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 | * The files that where found and matched at least one includes, and also | ||||
* matched at least one excludes. | * matched at least one excludes. | ||||
*/ | */ | ||||
private Vector dirsExcluded; | |||||
protected Vector dirsExcluded; | |||||
/** | /** | ||||
* Have the Vectors holding our results been built by a slow scan? | * Have the Vectors holding our results been built by a slow scan? | ||||
*/ | */ | ||||
private boolean haveSlowResults = false; | |||||
protected boolean haveSlowResults = false; | |||||
/** | /** | ||||
* Constructor. | * Constructor. | ||||
@@ -221,7 +221,7 @@ public class DirectoryScanner { | |||||
* @param pattern the (non-null) pattern to match against | * @param pattern the (non-null) pattern to match against | ||||
* @param str the (non-null) string (path) to match | * @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 | // When str starts with a File.separator, pattern has to start with a | ||||
// File.separator. | // File.separator. | ||||
// When pattern starts with a File.separator, str has to start with a | // When pattern starts with a File.separator, str has to start with a | ||||
@@ -283,7 +283,7 @@ public class DirectoryScanner { | |||||
* @return <code>true</code> when the pattern matches against the string. | * @return <code>true</code> when the pattern matches against the string. | ||||
* <code>false</code> otherwise. | * <code>false</code> 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 | // When str starts with a File.separator, pattern has to start with a | ||||
// File.separator. | // File.separator. | ||||
// When pattern starts with a File.separator, str has to start with a | // When pattern starts with a File.separator, str has to start with a | ||||
@@ -423,7 +423,7 @@ strLoop: | |||||
* @return <code>true</code> when the string matches against the pattern, | * @return <code>true</code> when the string matches against the pattern, | ||||
* <code>false</code> otherwise. | * <code>false</code> otherwise. | ||||
*/ | */ | ||||
private static boolean match(String pattern, String str) { | |||||
protected static boolean match(String pattern, String str) { | |||||
char[] patArr = pattern.toCharArray(); | char[] patArr = pattern.toCharArray(); | ||||
char[] strArr = str.toCharArray(); | char[] strArr = str.toCharArray(); | ||||
int patIdxStart = 0; | int patIdxStart = 0; | ||||
@@ -682,7 +682,7 @@ strLoop: | |||||
* | * | ||||
* <p>Returns immediately if a slow scan has already been requested. | * <p>Returns immediately if a slow scan has already been requested. | ||||
*/ | */ | ||||
private void slowScan() { | |||||
protected void slowScan() { | |||||
if (haveSlowResults) { | if (haveSlowResults) { | ||||
return; | return; | ||||
} | } | ||||
@@ -725,7 +725,7 @@ strLoop: | |||||
* @see #dirsNotIncluded | * @see #dirsNotIncluded | ||||
* @see #dirsExcluded | * @see #dirsExcluded | ||||
*/ | */ | ||||
private void scandir(File dir, String vpath, boolean fast) { | |||||
protected void scandir(File dir, String vpath, boolean fast) { | |||||
String[] newfiles = dir.list(); | String[] newfiles = dir.list(); | ||||
if (newfiles == null) { | if (newfiles == null) { | ||||
@@ -785,7 +785,7 @@ strLoop: | |||||
* @return <code>true</code> when the name matches against at least one | * @return <code>true</code> when the name matches against at least one | ||||
* include pattern, <code>false</code> otherwise. | * include pattern, <code>false</code> otherwise. | ||||
*/ | */ | ||||
private boolean isIncluded(String name) { | |||||
protected boolean isIncluded(String name) { | |||||
for (int i = 0; i < includes.length; i++) { | for (int i = 0; i < includes.length; i++) { | ||||
if (matchPath(includes[i],name)) { | if (matchPath(includes[i],name)) { | ||||
return true; | return true; | ||||
@@ -801,7 +801,7 @@ strLoop: | |||||
* @return <code>true</code> when the name matches against at least one | * @return <code>true</code> when the name matches against at least one | ||||
* include pattern, <code>false</code> otherwise. | * include pattern, <code>false</code> otherwise. | ||||
*/ | */ | ||||
private boolean couldHoldIncluded(String name) { | |||||
protected boolean couldHoldIncluded(String name) { | |||||
for (int i = 0; i < includes.length; i++) { | for (int i = 0; i < includes.length; i++) { | ||||
if (matchPatternStart(includes[i],name)) { | if (matchPatternStart(includes[i],name)) { | ||||
return true; | return true; | ||||
@@ -817,7 +817,7 @@ strLoop: | |||||
* @return <code>true</code> when the name matches against at least one | * @return <code>true</code> when the name matches against at least one | ||||
* exclude pattern, <code>false</code> otherwise. | * exclude pattern, <code>false</code> otherwise. | ||||
*/ | */ | ||||
private boolean isExcluded(String name) { | |||||
protected boolean isExcluded(String name) { | |||||
for (int i = 0; i < excludes.length; i++) { | for (int i = 0; i < excludes.length; i++) { | ||||
if (matchPath(excludes[i],name)) { | if (matchPath(excludes[i],name)) { | ||||
return true; | return true; | ||||
@@ -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); | |||||
} |
@@ -62,21 +62,31 @@ import java.util.*; | |||||
import com.oroinc.net.ftp.*; | 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: | |||||
* <ul> | |||||
* <li><strong>send</strong> - send files to a remote server. This is the | |||||
* default action.</li> | |||||
* <li><strong>get</strong> - retrive files from a remote server.</li> | |||||
* <li><strong>del</strong> - delete files from a remote server.</li> | |||||
* <li><strong>list</strong> - create a file listing.</li> | |||||
* </ul> | |||||
* | * | ||||
* @author Roger Vaughn <a href="mailto:rvaughn@seaconinc.com">rvaughn@seaconinc.com</a> | * @author Roger Vaughn <a href="mailto:rvaughn@seaconinc.com">rvaughn@seaconinc.com</a> | ||||
* @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||||
*/ | */ | ||||
public class FTP | public class FTP | ||||
extends Task | extends Task | ||||
{ | { | ||||
protected final static int SEND_FILES = 0; | protected final static int SEND_FILES = 0; | ||||
protected final static int GET_FILES = 1; | protected final static int GET_FILES = 1; | ||||
protected final static int DEL_FILES = 2; | |||||
protected final static int LIST_FILES = 3; | |||||
private String remotedir; | private String remotedir; | ||||
private String server; | private String server; | ||||
private String userid; | private String userid; | ||||
private String password; | private String password; | ||||
private File listing; | |||||
private boolean binary = true; | private boolean binary = true; | ||||
private boolean verbose = false; | private boolean verbose = false; | ||||
private boolean newerOnly = false; | private boolean newerOnly = false; | ||||
@@ -87,6 +97,107 @@ public class FTP | |||||
private String remoteFileSep = "/"; | private String remoteFileSep = "/"; | ||||
private int port = 21; | private int port = 21; | ||||
protected final static String[] ACTION_STRS = { | |||||
"sending", | |||||
"getting", | |||||
"deleting", | |||||
"listing" | |||||
}; | |||||
protected final static String[] COMPLETED_ACTION_STRS = { | |||||
"sent", | |||||
"retrieved", | |||||
"deleted", | |||||
"listed" | |||||
}; | |||||
protected class FTPDirectoryScanner extends DirectoryScanner { | |||||
protected FTPClient ftp = null; | |||||
public FTPDirectoryScanner(FTPClient ftp) { | |||||
super(); | |||||
this.ftp = ftp; | |||||
} | |||||
public void scan() { | |||||
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]; | |||||
} | |||||
filesIncluded = new Vector(); | |||||
filesNotIncluded = new Vector(); | |||||
filesExcluded = new Vector(); | |||||
dirsIncluded = new Vector(); | |||||
dirsNotIncluded = new Vector(); | |||||
dirsExcluded = new Vector(); | |||||
try { | |||||
String cwd = ftp.printWorkingDirectory(); | |||||
scandir(".", "", true); // always start from the current ftp working dir | |||||
ftp.changeWorkingDirectory(cwd); | |||||
} catch (IOException e) { | |||||
throw new BuildException("Unable to scan FTP server: ", e); | |||||
} | |||||
} | |||||
protected void scandir(String dir, String vpath, boolean fast) { | |||||
try { | |||||
if (!ftp.changeWorkingDirectory(dir)) { | |||||
return; | |||||
} | |||||
FTPFile[] newfiles = ftp.listFiles(); | |||||
if (newfiles == null) { | |||||
return; // no files in directory. | |||||
} | |||||
for (int i = 0; i < newfiles.length; i++) { | |||||
FTPFile file = newfiles[i]; | |||||
String name = vpath + file.getName(); | |||||
if (file.isDirectory()) { | |||||
if (isIncluded(name)) { | |||||
if (!isExcluded(name)) { | |||||
dirsIncluded.addElement(name); | |||||
if (fast) { | |||||
scandir(name, name + File.separator, fast); | |||||
} | |||||
} else { | |||||
dirsExcluded.addElement(name); | |||||
} | |||||
} else { | |||||
dirsNotIncluded.addElement(name); | |||||
if (fast && couldHoldIncluded(name)) { | |||||
scandir(name, name + File.separator, fast); | |||||
} | |||||
} | |||||
if (!fast) { | |||||
scandir(name, name + File.separator, fast); | |||||
} | |||||
} else { | |||||
if (file.isFile()) { | |||||
if (isIncluded(name)) { | |||||
if (!isExcluded(name)) { | |||||
filesIncluded.addElement(name); | |||||
} else { | |||||
filesExcluded.addElement(name); | |||||
} | |||||
} else { | |||||
filesNotIncluded.addElement(name); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} catch (IOException e) { | |||||
throw new BuildException("Error while communicating with FTP server: ", e); | |||||
} | |||||
} | |||||
} | |||||
/** | /** | ||||
* Sets the remote directory where files will be placed. This may | * Sets the remote directory where files will be placed. This may | ||||
* be a relative or absolute path, and must be in the path syntax | * be a relative or absolute path, and must be in the path syntax | ||||
@@ -192,8 +303,8 @@ public class FTP | |||||
} | } | ||||
/** | /** | ||||
* Sets the FTP action to be taken. Currently accepts "put" and "get". | |||||
* "get" tasks are not yet supported and will effectively perform a noop. | |||||
* Sets the FTP action to be taken. Currently accepts "put", "get", | |||||
* "del", and "list". | |||||
*/ | */ | ||||
public void setAction(String action) throws BuildException | public void setAction(String action) throws BuildException | ||||
{ | { | ||||
@@ -207,11 +318,29 @@ public class FTP | |||||
{ | { | ||||
this.action = GET_FILES; | this.action = GET_FILES; | ||||
} | } | ||||
else if (action.toLowerCase().equals("del") || | |||||
action.toLowerCase().equals("delete" )) | |||||
{ | |||||
this.action = DEL_FILES; | |||||
} | |||||
else if (action.toLowerCase().equals("list")) | |||||
{ | |||||
this.action = LIST_FILES; | |||||
} | |||||
else | else | ||||
{ | { | ||||
throw new BuildException("action " + action + " is not supported"); | throw new BuildException("action " + action + " is not supported"); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* The output file for the "list" action. This attribute is ignored for | |||||
* any other actions. | |||||
*/ | |||||
public void setListing(File listing) throws BuildException { | |||||
this.listing = listing; | |||||
} | |||||
/** | /** | ||||
* Checks to see that all required parameters are set. | * Checks to see that all required parameters are set. | ||||
@@ -230,20 +359,81 @@ public class FTP | |||||
{ | { | ||||
throw new BuildException("password attribute must be set!"); | throw new BuildException("password attribute must be set!"); | ||||
} | } | ||||
if ((action == LIST_FILES) && (listing == null)) | |||||
{ | |||||
throw new BuildException("listing attribute must be set for list action!"); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
* Append all files found by a directory scanner to a vector. | |||||
* For each file in the fileset, do the appropriate action: send, get, delete, | |||||
* or list. | |||||
*/ | */ | ||||
protected int sendFiles(FTPClient ftp, DirectoryScanner ds) | |||||
protected int transferFiles(FTPClient ftp, FileSet fs) | |||||
throws IOException, BuildException | throws IOException, BuildException | ||||
{ | { | ||||
FileScanner ds; | |||||
if (action == SEND_FILES) { | |||||
ds = fs.getDirectoryScanner(project); | |||||
} else { | |||||
ds = new FTPDirectoryScanner(ftp); | |||||
fs.setupDirectoryScanner(ds, project); | |||||
ds.scan(); | |||||
} | |||||
String[] dsfiles = ds.getIncludedFiles(); | String[] dsfiles = ds.getIncludedFiles(); | ||||
String dir = ds.getBasedir().getAbsolutePath(); | |||||
String dir = null; | |||||
if ((ds.getBasedir() == null) && ((action == SEND_FILES) || (action == GET_FILES))) { | |||||
throw new BuildException( "the dir attribute must be set for send and get actions" ); | |||||
} else { | |||||
if ((action == SEND_FILES) || (action == GET_FILES)) { | |||||
dir = ds.getBasedir().getAbsolutePath(); | |||||
} | |||||
} | |||||
// If we are doing a listing, we need the output stream created now. | |||||
BufferedWriter bw = null; | |||||
if (action == LIST_FILES) { | |||||
File pd = new File(listing.getParent()); | |||||
if (!pd.exists()) { | |||||
pd.mkdirs(); | |||||
} | |||||
bw = new BufferedWriter(new FileWriter(listing)); | |||||
} | |||||
for (int i = 0; i < dsfiles.length; i++) | for (int i = 0; i < dsfiles.length; i++) | ||||
{ | { | ||||
sendFile(ftp, dir, dsfiles[i]); | |||||
switch (action) { | |||||
case SEND_FILES: { | |||||
sendFile(ftp, dir, dsfiles[i]); | |||||
break; | |||||
} | |||||
case GET_FILES: { | |||||
getFile(ftp, dir, dsfiles[i]); | |||||
break; | |||||
} | |||||
case DEL_FILES: { | |||||
delFile(ftp, dsfiles[i]); | |||||
break; | |||||
} | |||||
case LIST_FILES: { | |||||
listFile(ftp, bw, dsfiles[i]); | |||||
break; | |||||
} | |||||
default: { | |||||
throw new BuildException("unknown ftp action " + action ); | |||||
} | |||||
} | |||||
} | |||||
if (action == LIST_FILES) { | |||||
bw.close(); | |||||
} | } | ||||
return dsfiles.length; | return dsfiles.length; | ||||
@@ -253,7 +443,7 @@ public class FTP | |||||
* Sends all files specified by the configured filesets to the remote | * Sends all files specified by the configured filesets to the remote | ||||
* server. | * server. | ||||
*/ | */ | ||||
protected void sendFiles(FTPClient ftp) | |||||
protected void transferFiles(FTPClient ftp) | |||||
throws IOException, BuildException | throws IOException, BuildException | ||||
{ | { | ||||
transferred = 0; | transferred = 0; | ||||
@@ -298,12 +488,12 @@ public class FTP | |||||
if (fs != null) | if (fs != null) | ||||
{ | { | ||||
sendFiles(ftp, fs.getDirectoryScanner(project)); | |||||
transferFiles(ftp, fs); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
log(transferred + " files transferred"); | |||||
log(transferred + " files " + COMPLETED_ACTION_STRS[action]); | |||||
} | } | ||||
/** | /** | ||||
@@ -380,8 +570,13 @@ public class FTP | |||||
return false; | return false; | ||||
} | } | ||||
return files[0].getTimestamp().getTime().getTime() > | |||||
localFile.lastModified(); | |||||
long remoteTimestamp = files[0].getTimestamp().getTime().getTime(); | |||||
long localTimestamp = localFile.lastModified(); | |||||
if (this.action == SEND_FILES) { | |||||
return remoteTimestamp > localTimestamp; | |||||
} else { | |||||
return localTimestamp > remoteTimestamp; | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -444,6 +639,106 @@ public class FTP | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Delete a file from the remote host. | |||||
*/ | |||||
protected void delFile(FTPClient ftp, String filename) | |||||
throws IOException, BuildException { | |||||
if (verbose) { | |||||
log("deleting " + filename); | |||||
} | |||||
if (!ftp.deleteFile(resolveFile(filename))) { | |||||
throw new BuildException("could not delete file: " + ftp.getReplyString()); | |||||
} | |||||
log("File " + filename + " deleted from " + server, Project.MSG_VERBOSE); | |||||
transferred++; | |||||
} | |||||
/** | |||||
* Retrieve a single file to the remote host. | |||||
* <code>filename</code> 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. | |||||
* <code>filename</code> 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. | * 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) | catch(IOException ex) | ||||
{ | { | ||||
@@ -55,6 +55,7 @@ | |||||
package org.apache.tools.ant.types; | package org.apache.tools.ant.types; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.FileScanner; | |||||
import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
@@ -198,6 +199,16 @@ public class FileSet { | |||||
} | } | ||||
DirectoryScanner ds = new DirectoryScanner(); | 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); | ds.setBasedir(dir); | ||||
for (int i=0; i<additionalPatterns.size(); i++) { | for (int i=0; i<additionalPatterns.size(); i++) { | ||||
@@ -219,8 +230,5 @@ public class FileSet { | |||||
ds.setIncludes(defaultPatterns.getIncludePatterns(p)); | ds.setIncludes(defaultPatterns.getIncludePatterns(p)); | ||||
ds.setExcludes(defaultPatterns.getExcludePatterns(p)); | ds.setExcludes(defaultPatterns.getExcludePatterns(p)); | ||||
if (useDefaultExcludes) ds.addDefaultExcludes(); | if (useDefaultExcludes) ds.addDefaultExcludes(); | ||||
ds.scan(); | |||||
return ds; | |||||
} | } | ||||
} | } |