Return-Path: Optional tasks
Copies files from the local system to a remote ftp server.
+The fileset
syntax must be used for specifying the local
+files to copy. All filesets will be copied into the single remote directory
+specified by remotedir.
The ftp task makes no attempt to determine what file system syntax is +required by the remote server, and defaults to Unix standards. +remotedir must be specified in the exact syntax required by the ftp +server. If the usual Unix conventions are not supported by the server, +separator can be used to set the file separator that should be used +instead.
+See the section on directory based +tasks, on how the inclusion/exclusion of files works, and how to +write patterns.
+Attribute | +Description | +Required | +
server | +the address of the remote ftp server. | +Yes | +
port | +the port number of the remote ftp server. + Defaults to port 21. | +No | +
userid | +the login id to use on the ftp server. | +Yes | +
password | +the login password to use on the ftp server. | +Yes | +
remotedir | +the directory to which to upload files on the + ftp server. | +No | +
action | +the ftp action to perform. + Current only supports"put" | +No | +
binary | +selects binary-mode ("yes") or text-mode + ("no") transfers. + Defaults to "yes" | +No | +
verbose | +displays information on each file transferred if set + to "yes". Defaults to "no". | +No | +
depends | +transfers only new or changed files if set to + "yes". Defaults to "no". | +No | +
newer | +a synonym for depends. | +No | +
separator | +sets the file separator used on the ftp server. + Defaults to "/". | +No | +
<ftp server="ftp.apache.org" + userid="anonymous" + password="me@myorg.com" + > + <fileset dir="htdocs/manual" /> + </ftp>+
Logs in to ftp.apache.org
as anonymous
and
+uploads all files in the htdocs/manual
directory
+to the default directory for that user.
<ftp server="ftp.apache.org" + remotedir="incoming" + userid="anonymous" + password="me@myorg.com" + depends="yes" + > + <fileset dir="htdocs/manual" /> + </ftp>+
Logs in to ftp.apache.org
as anonymous
and
+uploads all new or changed files in the htdocs/manual
directory
+to the incoming
directory relative to the default directory
+for anonymous
.
<ftp server="ftp.apache.org" + port="2121" + remotedir="/pub/incoming" + userid="coder" + password="java1" + depends="yes" + binary="no" + > + <fileset dir="htdocs/manual"> + <include name="**/*.html" /> + </fileset> + </ftp>+
Logs in to ftp.apache.org
at port 2121
as
+coder
with password java1
and uploads all new or
+changed HTML files in the htdocs/manual
directory to the
+/pub/incoming
directory. The files are transferred in text
+mode.
<ftp server="ftp.nt.org" + remotedir="c:\uploads" + userid="coder" + password="java1" + separator="\" + verbose="yes" + > + <fileset dir="htdocs/manual"> + <include name="**/*.html" /> + </fileset> + </ftp>+
Logs in to the Windows-based ftp.nt.org
as
+coder
with password java1
and uploads all
+HTML files in the htdocs/manual
directory to the
+c:\uploads
directory. Progress messages are displayed as each
+file is uploaded.
separator
task parameter. No
* attempt is made to determine what syntax is appropriate for the
* remote host.
*/
protected String resolveFile(String file)
{
return file.replace(System.getProperty("file.separator").charAt(0),
remoteFileSep.charAt(0));
}
/**
* Creates all parent directories specified in a complete relative
* pathname. Attempts to create existing directories will not cause
* errors.
*/
protected void createParents(FTPClient ftp, String filename)
throws IOException, BuildException
{
Vector parents = new Vector();
File dir = new File(filename);
String dirname;
while ((dirname = dir.getParent()) != null)
{
dir = new File(dirname);
parents.addElement(dir);
}
for (int i = parents.size() - 1; i >= 0; i--)
{
dir = (File)parents.elementAt(i);
if (!dirCache.contains(dir))
{
log("creating remote directory " + resolveFile(dir.getPath()),
Project.MSG_VERBOSE);
ftp.makeDirectory(resolveFile(dir.getPath()));
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()) &&
(ftp.getReplyCode() != 550))
{
throw new BuildException(
"could not create directory: " +
ftp.getReplyString());
}
dirCache.addElement(dir);
}
}
}
/**
* Checks to see if the remote file is current as compared with the
* local file. Returns true if the remote file is up to date.
*/
protected boolean isUpToDate(FTPClient ftp, File localFile, String remoteFile)
throws IOException, BuildException
{
log("checking date for " + remoteFile, Project.MSG_VERBOSE);
FTPFile[] files = ftp.listFiles(remoteFile);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException(
"could not date test remote file: " +
ftp.getReplyString());
}
if (files == null)
{
return false;
}
return files[0].getTimestamp().getTime().getTime() >
localFile.lastModified();
}
/**
* Sends a single file to the remote host.
* filename
may contain a relative path specification.
* When this is the case, sendFile
will attempt to create
* any necessary parent directories before sending the file. The file
* will then be sent 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 sendFile(FTPClient ftp, String dir, String filename)
throws IOException, BuildException
{
InputStream instream = null;
try
{
File file = project.resolveFile(new File(dir, filename).getPath());
if (newerOnly && isUpToDate(ftp, file, resolveFile(filename)))
return;
if (verbose)
{
log("transferring " + file.getAbsolutePath());
}
instream = new BufferedInputStream(new FileInputStream(file));
createParents(ftp, filename);
ftp.storeFile(resolveFile(filename), instream);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException(
"could not transfer file: " +
ftp.getReplyString());
}
log("File " + file.getAbsolutePath() + " copied to " + server,
Project.MSG_VERBOSE);
transferred++;
}
finally
{
if (instream != null)
{
try
{
instream.close();
}
catch(IOException ex)
{
// ignore it
}
}
}
}
/**
* Runs the task.
*/
public void execute()
throws BuildException
{
checkConfiguration();
FTPClient ftp = null;
try
{
log("Opening FTP connection to " + server, Project.MSG_VERBOSE);
ftp = new FTPClient();
ftp.connect(server, port);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException("FTP connection failed: " + ftp.getReplyString());
}
log("connected", Project.MSG_VERBOSE);
log("logging in to FTP server", Project.MSG_VERBOSE);
if (!ftp.login(userid, password))
{
throw new BuildException("Could not login to FTP server");
}
log("login succeeded", Project.MSG_VERBOSE);
if (binary)
{
ftp.setFileType(com.oroinc.net.ftp.FTP.IMAGE_FILE_TYPE);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode()))
{
throw new BuildException(
"could not set transfer type: " +
ftp.getReplyString());
}
}
if (remotedir != null)
{
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("transferring files");
if (action == SEND_FILES)
{
sendFiles(ftp);
}
else
{
throw new BuildException("getting files is not yet supported");
}
}
catch(IOException ex)
{
throw new BuildException("error during FTP transfer: " + ex);
}
finally
{
/*
if (ftp != null && ftp.isConnected())
{
try
{
// this hangs - I don't know why.
ftp.disconnect();
}
catch(IOException ex)
{
// ignore it
}
}
*/
}
}
}