Browse Source

Add ignoreNoncriticalErrors and skipFailedTransfers attributes to

<ftp>

ignoreNoncrtiticalErrors makes the task ignore all error messages when
creating a directory (some servers return strange codes if the
directory in question already exists).

skipFailedTransfers warns about failed file transfers but keeps going
on - transfering everything that works.

Submitted by:	Steve Loughran <steve_l@iseran.com>

Add a "mkdir" action to <ftp>, make <ftp> take a missing remote file a
"the file is not uptodate" when sending files.

Submitted by:	Larry V. Streepy, Jr. <streepy@healthlanguage.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269403 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 24 years ago
parent
commit
fffe72edb5
2 changed files with 188 additions and 72 deletions
  1. +14
    -0
      docs/manual/OptionalTasks/ftp.html
  2. +174
    -72
      src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java

+ 14
- 0
docs/manual/OptionalTasks/ftp.html View File

@@ -106,6 +106,20 @@ write patterns.</p>
Required for the &quot;list&quot; action, ignored otherwise.</td> Required for the &quot;list&quot; action, ignored otherwise.</td>
<td valign="top" align="center">No</td> <td valign="top" align="center">No</td>
</tr> </tr>
<tr>
<td valign="top">ignoreNoncriticalErrors</td>
<td valign="top">flag which permits the task to ignore some non-fatal error
codes sent by some servers during directory creation: wu-ftp in particular.
Default: false</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">skipFailedTransfers</td>
<td valign="top">flag which enables unsuccessful file put, delete
and get operations to be skipped with a warning and the
remainder of the files still transferred. Default: false</td>
<td valign="top" align="center">No</td>
</tr>
</table> </table>
<h3>Sending Files</h3> <h3>Sending Files</h3>
<p>The easiest way to describe how to send files is with a couple of examples:</p> <p>The easiest way to describe how to send files is with a couple of examples:</p>


+ 174
- 72
src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java View File

@@ -87,9 +87,10 @@ public class FTP
{ {
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 DEL_FILES = 2;
protected final static int LIST_FILES = 3; protected final static int LIST_FILES = 3;
protected final static int MK_DIR = 4;

private String remotedir; private String remotedir;
private String server; private String server;
private String userid; private String userid;
@@ -105,24 +106,29 @@ public class FTP
private int transferred = 0; private int transferred = 0;
private String remoteFileSep = "/"; private String remoteFileSep = "/";
private int port = 21; private int port = 21;
private boolean skipFailedTransfers=false;
private int skipped=0;
private boolean ignoreNoncriticalErrors=false;


protected final static String[] ACTION_STRS = { protected final static String[] ACTION_STRS = {
"sending", "sending",
"getting", "getting",
"deleting", "deleting",
"listing"
"listing",
"making directory"
}; };


protected final static String[] COMPLETED_ACTION_STRS = { protected final static String[] COMPLETED_ACTION_STRS = {
"sent", "sent",
"retrieved", "retrieved",
"deleted", "deleted",
"listed"
};
"listed",
"created directory"
};

protected class FTPDirectoryScanner extends DirectoryScanner { protected class FTPDirectoryScanner extends DirectoryScanner {
protected FTPClient ftp = null; protected FTPClient ftp = null;
public FTPDirectoryScanner(FTPClient ftp) { public FTPDirectoryScanner(FTPClient ftp) {
super(); super();
this.ftp = ftp; this.ftp = ftp;
@@ -344,20 +350,39 @@ public class FTP
{ {
this.action = LIST_FILES; this.action = LIST_FILES;
} }
else if (action.toLowerCase().equals("mkdir"))
{
this.action = MK_DIR;
}
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 * The output file for the "list" action. This attribute is ignored for
* any other actions. * any other actions.
*/ */
public void setListing(File listing) throws BuildException { public void setListing(File listing) throws BuildException {
this.listing = listing; this.listing = listing;
}
}


/**
* set the failed transfer flag
*/
public void setSkipFailedTransfers(boolean skipFailedTransfers) {
this.skipFailedTransfers=skipFailedTransfers;
}

/**
* set the flag to skip errors on dir creation (and maybe later other
* server specific errors)
*/
public void setIgnoreNoncriticalErrors(boolean ignoreNoncriticalErrors) {
this.ignoreNoncriticalErrors=ignoreNoncriticalErrors;
}


/** /**
* Checks to see that all required parameters are set. * Checks to see that all required parameters are set.
@@ -376,11 +401,15 @@ 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)) if ((action == LIST_FILES) && (listing == null))
{ {
throw new BuildException("listing attribute must be set for list action!"); throw new BuildException("listing attribute must be set for list action!");
} }

if( action == MK_DIR && remotedir == null ) {
throw new BuildException("remotedir attribute must be set for mkdir action!");
}
} }


/** /**
@@ -398,8 +427,8 @@ public class FTP
ds = new FTPDirectoryScanner(ftp); ds = new FTPDirectoryScanner(ftp);
fs.setupDirectoryScanner(ds, project); fs.setupDirectoryScanner(ds, project);
ds.scan(); ds.scan();
}
}
String[] dsfiles = ds.getIncludedFiles(); String[] dsfiles = ds.getIncludedFiles();
String dir = null; String dir = null;
if ((ds.getBasedir() == null) && ((action == SEND_FILES) || (action == GET_FILES))) { if ((ds.getBasedir() == null) && ((action == SEND_FILES) || (action == GET_FILES))) {
@@ -464,7 +493,8 @@ public class FTP
throws IOException, BuildException throws IOException, BuildException
{ {
transferred = 0; transferred = 0;
skipped=0;

if (filesets.size() == 0) if (filesets.size() == 0)
{ {
throw new BuildException("at least one fileset must be specified."); throw new BuildException("at least one fileset must be specified.");
@@ -483,6 +513,9 @@ public class FTP
} }


log(transferred + " files " + COMPLETED_ACTION_STRS[action]); log(transferred + " files " + COMPLETED_ACTION_STRS[action]);
if(skipped!=0) {
log(skipped + " files were not successfully "+ COMPLETED_ACTION_STRS[action]);
}
} }


/** /**
@@ -528,8 +561,10 @@ public class FTP
// Both codes 550 and 553 can be produced by FTP Servers // Both codes 550 and 553 can be produced by FTP Servers
// to indicate that an attempt to create a directory has // to indicate that an attempt to create a directory has
// failed because the directory already exists. // failed because the directory already exists.
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()) &&
(ftp.getReplyCode() != 550) && (ftp.getReplyCode() != 553))
int result=ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(result) &&
(result != 550) && (result!= 553) &&
!ignoreNoncriticalErrors)
{ {
throw new BuildException( throw new BuildException(
"could not create directory: " + "could not create directory: " +
@@ -548,18 +583,22 @@ public class FTP
throws IOException, BuildException throws IOException, BuildException
{ {
log("checking date for " + remoteFile, Project.MSG_VERBOSE); log("checking date for " + remoteFile, Project.MSG_VERBOSE);
FTPFile[] files = ftp.listFiles(remoteFile); FTPFile[] files = ftp.listFiles(remoteFile);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException(
"could not date test remote file: " +
ftp.getReplyString());
}


if (files == null) if (files == null)
{ {
return false;
// If we are sending files, then assume out of date.
// If we are getting files, then throw an error

if( action == SEND_FILES ) {
log("Could not date test remote file: " + remoteFile
+ "assuming out of date.", Project.MSG_VERBOSE);
return false;
} else {
throw new BuildException("could not date test remote file: " +
ftp.getReplyString());
}
} }


long remoteTimestamp = files[0].getTimestamp().getTime().getTime(); long remoteTimestamp = files[0].getTimestamp().getTime().getTime();
@@ -596,27 +635,35 @@ public class FTP
{ {
log("transferring " + file.getAbsolutePath()); log("transferring " + file.getAbsolutePath());
} }
instream = new BufferedInputStream(new FileInputStream(file)); instream = new BufferedInputStream(new FileInputStream(file));
createParents(ftp, filename); createParents(ftp, filename);
ftp.storeFile(resolveFile(filename), instream); ftp.storeFile(resolveFile(filename), instream);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
boolean success=FTPReply.isPositiveCompletion(ftp.getReplyCode());
if (!success)
{ {
throw new BuildException(
"could not transfer file: " +
ftp.getReplyString());
String s="could not put file: " + ftp.getReplyString();
if(skipFailedTransfers==true) {
log(s,Project.MSG_WARN);
skipped++;
}
else {
throw new BuildException(s);
}

} }
log("File " + file.getAbsolutePath() + " copied to " + server,
Project.MSG_VERBOSE);
else {


transferred++;
log("File " + file.getAbsolutePath() +
" copied to " + server,
Project.MSG_VERBOSE);
transferred++;
}
} }
finally finally
{
{
if (instream != null) if (instream != null)
{ {
try try
@@ -641,18 +688,25 @@ public class FTP
} }


if (!ftp.deleteFile(resolveFile(filename))) { if (!ftp.deleteFile(resolveFile(filename))) {
throw new BuildException("could not delete file: " + ftp.getReplyString());
String s="could not delete file: " + ftp.getReplyString();
if(skipFailedTransfers==true) {
log(s,Project.MSG_WARN);
skipped++;
}
else {
throw new BuildException(s);
}
}
else {
log("File " + filename + " deleted from " + server, Project.MSG_VERBOSE);
transferred++;
} }

log("File " + filename + " deleted from " + server, Project.MSG_VERBOSE);

transferred++;
} }


/** /**
* Retrieve a single file to the remote host. * Retrieve a single file to the remote host.
* <code>filename</code> may contain a relative path specification. * <code>filename</code> may contain a relative path specification.
* The file will then be retreived using the entire relative path spec -
* 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 * no attempt is made to change directories. It is anticipated that this may
* eventually cause problems with some FTP servers, but it simplifies * eventually cause problems with some FTP servers, but it simplifies
* the coding. * the coding.
@@ -673,28 +727,34 @@ public class FTP
log("transferring " + filename + " to " + file.getAbsolutePath()); log("transferring " + filename + " to " + file.getAbsolutePath());
} }


File pdir = new File(file.getParent()); // stay 1.1 compatible File pdir = new File(file.getParent()); // stay 1.1 compatible
if (!pdir.exists()) { if (!pdir.exists()) {
pdir.mkdirs(); pdir.mkdirs();
}
}
outstream = new BufferedOutputStream(new FileOutputStream(file)); outstream = new BufferedOutputStream(new FileOutputStream(file));
ftp.retrieveFile(resolveFile(filename), outstream); ftp.retrieveFile(resolveFile(filename), outstream);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{ {
throw new BuildException(
"could not transfer file: " +
ftp.getReplyString());
}
log("File " + file.getAbsolutePath() + " copied from " + server,
Project.MSG_VERBOSE);
String s="could not get file: " + ftp.getReplyString();
if(skipFailedTransfers==true) {
log(s,Project.MSG_WARN);
skipped++;
}
else {
throw new BuildException(s);
}


transferred++;
}
else {
log("File " + file.getAbsolutePath() + " copied from " + server,
Project.MSG_VERBOSE);
transferred++;
}
} }
finally finally
{
{
if (outstream != null) if (outstream != null)
{ {
try try
@@ -712,13 +772,13 @@ public class FTP
/** /**
* List information about a single file from the remote host. * List information about a single file from the remote host.
* <code>filename</code> may contain a relative path specification. * <code>filename</code> may contain a relative path specification.
* The file listing will then be retrieved using the entire relative path spec
* 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 * - no attempt is made to change directories. It is anticipated that this may
* eventually cause problems with some FTP servers, but it simplifies * eventually cause problems with some FTP servers, but it simplifies
* the coding. * the coding.
*/ */
protected void listFile(FTPClient ftp, BufferedWriter bw, String filename) protected void listFile(FTPClient ftp, BufferedWriter bw, String filename)
throws IOException, BuildException
throws IOException, BuildException
{ {
if (verbose) { if (verbose) {
log("listing " + filename); log("listing " + filename);
@@ -731,6 +791,39 @@ public class FTP
transferred++; transferred++;
} }


/**
* Create the specified directory on the remote host.
* @param ftp The FTP client connection
* @param dir The directory to create (format must be correct for host type)
*/
protected void makeRemoteDir( FTPClient ftp, String dir )
throws IOException, BuildException
{
if (verbose) {
log("creating directory: " + dir);
}

if( ! ftp.makeDirectory( dir ) ) {
// Both codes 550 and 553 can be produced by FTP Servers
// to indicate that an attempt to create a directory has
// failed because the directory already exists.

int rc = ftp.getReplyCode();
if( rc != 550 && rc != 553 && !ignoreNoncriticalErrors) {
throw new BuildException( "could not create directory: " +
ftp.getReplyString() );
}

if( verbose ) {
log( "directory already exists" );
}
} else {
if( verbose ) {
log( "directory created OK" );
}
}
}

/** /**
* Runs the task. * Runs the task.
*/ */
@@ -738,7 +831,7 @@ public class FTP
throws BuildException throws BuildException
{ {
checkConfiguration(); checkConfiguration();
FTPClient ftp = null; FTPClient ftp = null;


try try
@@ -746,7 +839,7 @@ public class FTP
log("Opening FTP connection to " + server, Project.MSG_VERBOSE); log("Opening FTP connection to " + server, Project.MSG_VERBOSE);


ftp = new FTPClient(); ftp = new FTPClient();
ftp.connect(server, port); ftp.connect(server, port);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{ {
@@ -762,7 +855,7 @@ public class FTP
} }


log("login succeeded", Project.MSG_VERBOSE); log("login succeeded", Project.MSG_VERBOSE);
if (binary) if (binary)
{ {
ftp.setFileType(com.oroinc.net.ftp.FTP.IMAGE_FILE_TYPE); ftp.setFileType(com.oroinc.net.ftp.FTP.IMAGE_FILE_TYPE);
@@ -773,7 +866,7 @@ public class FTP
ftp.getReplyString()); ftp.getReplyString());
} }
} }
if (passive) if (passive)
{ {
log("entering passive mode", Project.MSG_VERBOSE); log("entering passive mode", Project.MSG_VERBOSE);
@@ -786,21 +879,30 @@ public class FTP
} }
} }


if (remotedir != null)
{
log("changing the remote directory", Project.MSG_VERBOSE);
ftp.changeWorkingDirectory(remotedir);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
// If the action is MK_DIR, then the specified remote directory is the
// directory to create.

if( action == MK_DIR ) {

makeRemoteDir( ftp, remotedir );

} else {
if (remotedir != null)
{ {
throw new BuildException(
"could not change remote directory: " +
ftp.getReplyString());
log("changing the remote directory", Project.MSG_VERBOSE);
ftp.changeWorkingDirectory(remotedir);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException(
"could not change remote directory: " +
ftp.getReplyString());
}

log(ACTION_STRS[action] + " files");
transferFiles(ftp);
} }
} }


log(ACTION_STRS[action] + " files");
transferFiles(ftp);

} }
catch(IOException ex) catch(IOException ex)
{ {


Loading…
Cancel
Save