|
|
@@ -0,0 +1,969 @@ |
|
|
|
/* |
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
|
|
* contributor license agreements. See the NOTICE file distributed with |
|
|
|
* this work for additional information regarding copyright ownership. |
|
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
|
|
* (the "License"); you may not use this file except in compliance with |
|
|
|
* the License. You may obtain a copy of the License at |
|
|
|
* |
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
|
|
* |
|
|
|
* Unless required by applicable law or agreed to in writing, software |
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
|
|
* See the License for the specific language governing permissions and |
|
|
|
* limitations under the License. |
|
|
|
* |
|
|
|
*/ |
|
|
|
package org.apache.tools.ant.taskdefs.optional.net; |
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
import java.util.Collection; |
|
|
|
import java.util.Iterator; |
|
|
|
import java.util.Locale; |
|
|
|
import java.util.Vector; |
|
|
|
|
|
|
|
import org.apache.tools.ant.BuildException; |
|
|
|
import org.apache.tools.ant.Task; |
|
|
|
import org.apache.tools.ant.types.EnumeratedAttribute; |
|
|
|
import org.apache.tools.ant.types.FileSet; |
|
|
|
import org.apache.tools.ant.types.Path; |
|
|
|
import org.apache.tools.ant.util.LoaderUtils; |
|
|
|
import org.apache.tools.ant.util.Retryable; |
|
|
|
import org.apache.tools.ant.util.SplitClassLoader; |
|
|
|
|
|
|
|
/** |
|
|
|
* Basic FTP client. 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> - retrieve 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> |
|
|
|
* <li> <strong>chmod</strong> - change unix file permissions.</li> |
|
|
|
* <li> <strong>rmdir</strong> - remove directories, if empty, from a |
|
|
|
* remote server.</li> |
|
|
|
* </ul> |
|
|
|
* <strong>Note:</strong> Some FTP servers - notably the Solaris server - seem |
|
|
|
* to hold data ports open after a "retr" operation, allowing them to timeout |
|
|
|
* instead of shutting them down cleanly. This happens in active or passive |
|
|
|
* mode, and the ports will remain open even after ending the FTP session. FTP |
|
|
|
* "send" operations seem to close ports immediately. This behavior may cause |
|
|
|
* problems on some systems when downloading large sets of files. |
|
|
|
* |
|
|
|
* @since Ant 1.3 |
|
|
|
*/ |
|
|
|
public class FTPTask extends Task implements FTPTaskConfig { |
|
|
|
static final int SEND_FILES = 0; |
|
|
|
static final int GET_FILES = 1; |
|
|
|
static final int DEL_FILES = 2; |
|
|
|
static final int LIST_FILES = 3; |
|
|
|
static final int MK_DIR = 4; |
|
|
|
static final int CHMOD = 5; |
|
|
|
static final int RM_DIR = 6; |
|
|
|
static final int SITE_CMD = 7; |
|
|
|
|
|
|
|
/** adjust uptodate calculations where server timestamps are HH:mm and client's |
|
|
|
* are HH:mm:ss */ |
|
|
|
private static final long GRANULARITY_MINUTE = 60000L; |
|
|
|
|
|
|
|
/** Default port for FTP */ |
|
|
|
public static final int DEFAULT_FTP_PORT = 21; |
|
|
|
|
|
|
|
private String remotedir; |
|
|
|
private String server; |
|
|
|
private String userid; |
|
|
|
private String password; |
|
|
|
private String account; |
|
|
|
private File listing; |
|
|
|
private boolean binary = true; |
|
|
|
private boolean passive = false; |
|
|
|
private boolean verbose = false; |
|
|
|
private boolean newerOnly = false; |
|
|
|
private long timeDiffMillis = 0; |
|
|
|
private long granularityMillis = 0L; |
|
|
|
private boolean timeDiffAuto = false; |
|
|
|
private int action = SEND_FILES; |
|
|
|
private Vector filesets = new Vector(); |
|
|
|
private String remoteFileSep = "/"; |
|
|
|
private int port = DEFAULT_FTP_PORT; |
|
|
|
private boolean skipFailedTransfers = false; |
|
|
|
private boolean ignoreNoncriticalErrors = false; |
|
|
|
private boolean preserveLastModified = false; |
|
|
|
private String chmod = null; |
|
|
|
private String umask = null; |
|
|
|
private FTPSystemType systemTypeKey = FTPSystemType.getDefault(); |
|
|
|
private String defaultDateFormatConfig = null; |
|
|
|
private String recentDateFormatConfig = null; |
|
|
|
private String serverLanguageCodeConfig = null; |
|
|
|
private String serverTimeZoneConfig = null; |
|
|
|
private String shortMonthNamesConfig = null; |
|
|
|
private Granularity timestampGranularity = Granularity.getDefault(); |
|
|
|
private boolean isConfigurationSet = false; |
|
|
|
private int retriesAllowed = 0; |
|
|
|
private String siteCommand = null; |
|
|
|
private String initialSiteCommand = null; |
|
|
|
private boolean enableRemoteVerification = true; |
|
|
|
|
|
|
|
private Path classpath; |
|
|
|
private ClassLoader mirrorLoader; |
|
|
|
private FTPTaskMirror delegate = null; |
|
|
|
|
|
|
|
static final String[] ACTION_STRS = { |
|
|
|
"sending", |
|
|
|
"getting", |
|
|
|
"deleting", |
|
|
|
"listing", |
|
|
|
"making directory", |
|
|
|
"chmod", |
|
|
|
"removing", |
|
|
|
"site" |
|
|
|
}; |
|
|
|
|
|
|
|
static final String[] COMPLETED_ACTION_STRS = { |
|
|
|
"sent", |
|
|
|
"retrieved", |
|
|
|
"deleted", |
|
|
|
"listed", |
|
|
|
"created directory", |
|
|
|
"mode changed", |
|
|
|
"removed", |
|
|
|
"site command executed" |
|
|
|
}; |
|
|
|
|
|
|
|
static final String[] ACTION_TARGET_STRS = { |
|
|
|
"files", |
|
|
|
"files", |
|
|
|
"files", |
|
|
|
"files", |
|
|
|
"directory", |
|
|
|
"files", |
|
|
|
"directories", |
|
|
|
"site command" |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the remote directory where files will be placed. This may be a |
|
|
|
* relative or absolute path, and must be in the path syntax expected by |
|
|
|
* the remote server. No correction of path syntax will be performed. |
|
|
|
* |
|
|
|
* @param dir the remote directory name. |
|
|
|
*/ |
|
|
|
public void setRemotedir(String dir) { |
|
|
|
this.remotedir = dir; |
|
|
|
} |
|
|
|
|
|
|
|
public String getRemotedir() { |
|
|
|
return remotedir; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the FTP server to send files to. |
|
|
|
* |
|
|
|
* @param server the remote server name. |
|
|
|
*/ |
|
|
|
public void setServer(String server) { |
|
|
|
this.server = server; |
|
|
|
} |
|
|
|
|
|
|
|
public String getServer() { |
|
|
|
return server; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the FTP port used by the remote server. |
|
|
|
* |
|
|
|
* @param port the port on which the remote server is listening. |
|
|
|
*/ |
|
|
|
public void setPort(int port) { |
|
|
|
this.port = port; |
|
|
|
} |
|
|
|
|
|
|
|
public int getPort() { |
|
|
|
return port; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the login user id to use on the specified server. |
|
|
|
* |
|
|
|
* @param userid remote system userid. |
|
|
|
*/ |
|
|
|
public void setUserid(String userid) { |
|
|
|
this.userid = userid; |
|
|
|
} |
|
|
|
|
|
|
|
public String getUserid() { |
|
|
|
return userid; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the login password for the given user id. |
|
|
|
* |
|
|
|
* @param password the password on the remote system. |
|
|
|
*/ |
|
|
|
public void setPassword(String password) { |
|
|
|
this.password = password; |
|
|
|
} |
|
|
|
|
|
|
|
public String getPassword() { |
|
|
|
return password; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the login account to use on the specified server. |
|
|
|
* |
|
|
|
* @param pAccount the account name on remote system |
|
|
|
* @since Ant 1.7 |
|
|
|
*/ |
|
|
|
public void setAccount(String pAccount) { |
|
|
|
this.account = pAccount; |
|
|
|
} |
|
|
|
|
|
|
|
public String getAccount() { |
|
|
|
return account; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* If true, uses binary mode, otherwise text mode (default is binary). |
|
|
|
* |
|
|
|
* @param binary if true use binary mode in transfers. |
|
|
|
*/ |
|
|
|
public void setBinary(boolean binary) { |
|
|
|
this.binary = binary; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isBinary() { |
|
|
|
return binary; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Specifies whether to use passive mode. Set to true if you are behind a |
|
|
|
* firewall and cannot connect without it. Passive mode is disabled by |
|
|
|
* default. |
|
|
|
* |
|
|
|
* @param passive true is passive mode should be used. |
|
|
|
*/ |
|
|
|
public void setPassive(boolean passive) { |
|
|
|
this.passive = passive; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isPassive() { |
|
|
|
return passive; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Set to true to receive notification about each file as it is |
|
|
|
* transferred. |
|
|
|
* |
|
|
|
* @param verbose true if verbose notifications are required. |
|
|
|
*/ |
|
|
|
public void setVerbose(boolean verbose) { |
|
|
|
this.verbose = verbose; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isVerbose() { |
|
|
|
return verbose; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* A synonym for <tt>depends</tt>. Set to true to transmit only new |
|
|
|
* or changed files. |
|
|
|
* |
|
|
|
* See the related attributes timediffmillis and timediffauto. |
|
|
|
* |
|
|
|
* @param newer if true only transfer newer files. |
|
|
|
*/ |
|
|
|
public void setNewer(boolean newer) { |
|
|
|
this.newerOnly = newer; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isNewer() { |
|
|
|
return newerOnly; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* number of milliseconds to add to the time on the remote machine |
|
|
|
* to get the time on the local machine. |
|
|
|
* |
|
|
|
* use in conjunction with <code>newer</code> |
|
|
|
* |
|
|
|
* @param timeDiffMillis number of milliseconds |
|
|
|
* |
|
|
|
* @since ant 1.6 |
|
|
|
*/ |
|
|
|
public void setTimeDiffMillis(long timeDiffMillis) { |
|
|
|
this.timeDiffMillis = timeDiffMillis; |
|
|
|
} |
|
|
|
|
|
|
|
public long getTimeDiffMillis() { |
|
|
|
return timeDiffMillis; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* "true" to find out automatically the time difference |
|
|
|
* between local and remote machine. |
|
|
|
* |
|
|
|
* This requires right to create |
|
|
|
* and delete a temporary file in the remote directory. |
|
|
|
* |
|
|
|
* @param timeDiffAuto true = find automatically the time diff |
|
|
|
* |
|
|
|
* @since ant 1.6 |
|
|
|
*/ |
|
|
|
public void setTimeDiffAuto(boolean timeDiffAuto) { |
|
|
|
this.timeDiffAuto = timeDiffAuto; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isTimeDiffAuto() { |
|
|
|
return timeDiffAuto; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Set to true to preserve modification times for "gotten" files. |
|
|
|
* |
|
|
|
* @param preserveLastModified if true preserver modification times. |
|
|
|
*/ |
|
|
|
public void setPreserveLastModified(boolean preserveLastModified) { |
|
|
|
this.preserveLastModified = preserveLastModified; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isPreserveLastModified() { |
|
|
|
return preserveLastModified; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Set to true to transmit only files that are new or changed from their |
|
|
|
* remote counterparts. The default is to transmit all files. |
|
|
|
* |
|
|
|
* @param depends if true only transfer newer files. |
|
|
|
*/ |
|
|
|
public void setDepends(boolean depends) { |
|
|
|
this.newerOnly = depends; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the remote file separator character. This normally defaults to the |
|
|
|
* Unix standard forward slash, but can be manually overridden using this |
|
|
|
* call if the remote server requires some other separator. Only the first |
|
|
|
* character of the string is used. |
|
|
|
* |
|
|
|
* @param separator the file separator on the remote system. |
|
|
|
*/ |
|
|
|
public void setSeparator(String separator) { |
|
|
|
remoteFileSep = separator; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String getSeparator() { |
|
|
|
return remoteFileSep; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the file permission mode (Unix only) for files sent to the |
|
|
|
* server. |
|
|
|
* |
|
|
|
* @param theMode unix style file mode for the files sent to the remote |
|
|
|
* system. |
|
|
|
*/ |
|
|
|
public void setChmod(String theMode) { |
|
|
|
this.chmod = theMode; |
|
|
|
} |
|
|
|
|
|
|
|
public String getChmod() { |
|
|
|
return chmod; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the default mask for file creation on a unix server. |
|
|
|
* |
|
|
|
* @param theUmask unix style umask for files created on the remote server. |
|
|
|
*/ |
|
|
|
public void setUmask(String theUmask) { |
|
|
|
this.umask = theUmask; |
|
|
|
} |
|
|
|
|
|
|
|
public String getUmask() { |
|
|
|
return umask; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* A set of files to upload or download |
|
|
|
* |
|
|
|
* @param set the set of files to be added to the list of files to be |
|
|
|
* transferred. |
|
|
|
*/ |
|
|
|
public void addFileset(FileSet set) { |
|
|
|
filesets.addElement(set); |
|
|
|
} |
|
|
|
|
|
|
|
public Vector getFilesets() { |
|
|
|
return filesets; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the FTP action to be taken. Currently accepts "put", "get", "del", |
|
|
|
* "mkdir", "chmod", "list", and "site". |
|
|
|
* |
|
|
|
* @deprecated since 1.5.x. |
|
|
|
* setAction(String) is deprecated and is replaced with |
|
|
|
* setAction(FTP.Action) to make Ant's Introspection mechanism do the |
|
|
|
* work and also to encapsulate operations on the type in its own |
|
|
|
* class. |
|
|
|
* @ant.attribute ignore="true" |
|
|
|
* |
|
|
|
* @param action the FTP action to be performed. |
|
|
|
* |
|
|
|
* @throws BuildException if the action is not a valid action. |
|
|
|
*/ |
|
|
|
public void setAction(String action) throws BuildException { |
|
|
|
log("DEPRECATED - The setAction(String) method has been deprecated." |
|
|
|
+ " Use setAction(FTP.Action) instead."); |
|
|
|
|
|
|
|
Action a = new Action(); |
|
|
|
|
|
|
|
a.setValue(action); |
|
|
|
this.action = a.getAction(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the FTP action to be taken. Currently accepts "put", "get", "del", |
|
|
|
* "mkdir", "chmod", "list", and "site". |
|
|
|
* |
|
|
|
* @param action the FTP action to be performed. |
|
|
|
* |
|
|
|
* @throws BuildException if the action is not a valid action. |
|
|
|
*/ |
|
|
|
public void setAction(Action action) throws BuildException { |
|
|
|
this.action = action.getAction(); |
|
|
|
} |
|
|
|
|
|
|
|
public int getAction() { |
|
|
|
return this.action; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* The output file for the "list" action. This attribute is ignored for |
|
|
|
* any other actions. |
|
|
|
* |
|
|
|
* @param listing file in which to store the listing. |
|
|
|
*/ |
|
|
|
public void setListing(File listing) { |
|
|
|
this.listing = listing; |
|
|
|
} |
|
|
|
|
|
|
|
public File getListing() { |
|
|
|
return listing; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* If true, enables unsuccessful file put, delete and get |
|
|
|
* operations to be skipped with a warning and the remainder |
|
|
|
* of the files still transferred. |
|
|
|
* |
|
|
|
* @param skipFailedTransfers true if failures in transfers are ignored. |
|
|
|
*/ |
|
|
|
public void setSkipFailedTransfers(boolean skipFailedTransfers) { |
|
|
|
this.skipFailedTransfers = skipFailedTransfers; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isSkipFailedTransfers() { |
|
|
|
return skipFailedTransfers; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* set the flag to skip errors on directory creation. |
|
|
|
* (and maybe later other server specific errors) |
|
|
|
* |
|
|
|
* @param ignoreNoncriticalErrors true if non-critical errors should not |
|
|
|
* cause a failure. |
|
|
|
*/ |
|
|
|
public void setIgnoreNoncriticalErrors(boolean ignoreNoncriticalErrors) { |
|
|
|
this.ignoreNoncriticalErrors = ignoreNoncriticalErrors; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isIgnoreNoncriticalErrors() { |
|
|
|
return ignoreNoncriticalErrors; |
|
|
|
} |
|
|
|
|
|
|
|
private void configurationHasBeenSet() { |
|
|
|
this.isConfigurationSet = true; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean isConfigurationSet() { |
|
|
|
return this.isConfigurationSet; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the systemTypeKey attribute. |
|
|
|
* Method for setting <code>FTPClientConfig</code> remote system key. |
|
|
|
* |
|
|
|
* @param systemKey the key to be set - BUT if blank |
|
|
|
* the default value of null (which signifies "autodetect") will be kept. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setSystemTypeKey(FTPSystemType systemKey) { |
|
|
|
if (systemKey != null && !systemKey.getValue().equals("")) { |
|
|
|
this.systemTypeKey = systemKey; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the defaultDateFormatConfig attribute. |
|
|
|
* @param defaultDateFormat configuration to be set, unless it is |
|
|
|
* null or empty string, in which case ignored. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setDefaultDateFormatConfig(String defaultDateFormat) { |
|
|
|
if (defaultDateFormat != null && !defaultDateFormat.equals("")) { |
|
|
|
this.defaultDateFormatConfig = defaultDateFormat; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the recentDateFormatConfig attribute. |
|
|
|
* @param recentDateFormat configuration to be set, unless it is |
|
|
|
* null or empty string, in which case ignored. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setRecentDateFormatConfig(String recentDateFormat) { |
|
|
|
if (recentDateFormat != null && !recentDateFormat.equals("")) { |
|
|
|
this.recentDateFormatConfig = recentDateFormat; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the serverLanguageCode attribute. |
|
|
|
* @param serverLanguageCode configuration to be set, unless it is |
|
|
|
* null or empty string, in which case ignored. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setServerLanguageCodeConfig(String serverLanguageCode) { |
|
|
|
if (serverLanguageCode != null && !"".equals(serverLanguageCode)) { |
|
|
|
this.serverLanguageCodeConfig = serverLanguageCode; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the serverTimeZoneConfig attribute. |
|
|
|
* @param serverTimeZoneId configuration to be set, unless it is |
|
|
|
* null or empty string, in which case ignored. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setServerTimeZoneConfig(String serverTimeZoneId) { |
|
|
|
if (serverTimeZoneId != null && !serverTimeZoneId.equals("")) { |
|
|
|
this.serverTimeZoneConfig = serverTimeZoneId; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the shortMonthNamesConfig attribute |
|
|
|
* |
|
|
|
* @param shortMonthNames configuration to be set, unless it is |
|
|
|
* null or empty string, in which case ignored. |
|
|
|
* @see org.apache.commons.net.ftp.FTPClientConfig |
|
|
|
*/ |
|
|
|
public void setShortMonthNamesConfig(String shortMonthNames) { |
|
|
|
if (shortMonthNames != null && !shortMonthNames.equals("")) { |
|
|
|
this.shortMonthNamesConfig = shortMonthNames; |
|
|
|
configurationHasBeenSet(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Defines how many times to retry executing FTP command before giving up. |
|
|
|
* Default is 0 - try once and if failure then give up. |
|
|
|
* |
|
|
|
* @param retriesAllowed number of retries to allow. -1 means |
|
|
|
* keep trying forever. "forever" may also be specified as a |
|
|
|
* synonym for -1. |
|
|
|
*/ |
|
|
|
public void setRetriesAllowed(String retriesAllowed) { |
|
|
|
if ("FOREVER".equalsIgnoreCase(retriesAllowed)) { |
|
|
|
this.retriesAllowed = Retryable.RETRY_FOREVER; |
|
|
|
} else { |
|
|
|
try { |
|
|
|
int retries = Integer.parseInt(retriesAllowed); |
|
|
|
if (retries < Retryable.RETRY_FOREVER) { |
|
|
|
throw new BuildException( |
|
|
|
"Invalid value for retriesAllowed attribute: " |
|
|
|
+ retriesAllowed); |
|
|
|
|
|
|
|
} |
|
|
|
this.retriesAllowed = retries; |
|
|
|
} catch (NumberFormatException px) { |
|
|
|
throw new BuildException( |
|
|
|
"Invalid value for retriesAllowed attribute: " |
|
|
|
+ retriesAllowed); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public int getRetriesAllowed() { |
|
|
|
return retriesAllowed; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @return Returns the systemTypeKey. |
|
|
|
*/ |
|
|
|
public String getSystemTypeKey() { |
|
|
|
return systemTypeKey.getValue(); |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the defaultDateFormatConfig. |
|
|
|
*/ |
|
|
|
public String getDefaultDateFormatConfig() { |
|
|
|
return defaultDateFormatConfig; |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the recentDateFormatConfig. |
|
|
|
*/ |
|
|
|
public String getRecentDateFormatConfig() { |
|
|
|
return recentDateFormatConfig; |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the serverLanguageCodeConfig. |
|
|
|
*/ |
|
|
|
public String getServerLanguageCodeConfig() { |
|
|
|
return serverLanguageCodeConfig; |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the serverTimeZoneConfig. |
|
|
|
*/ |
|
|
|
public String getServerTimeZoneConfig() { |
|
|
|
return serverTimeZoneConfig; |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the shortMonthNamesConfig. |
|
|
|
*/ |
|
|
|
public String getShortMonthNamesConfig() { |
|
|
|
return shortMonthNamesConfig; |
|
|
|
} |
|
|
|
/** |
|
|
|
* @return Returns the timestampGranularity. |
|
|
|
*/ |
|
|
|
Granularity getTimestampGranularity() { |
|
|
|
return timestampGranularity; |
|
|
|
} |
|
|
|
/** |
|
|
|
* Sets the timestampGranularity attribute |
|
|
|
* @param timestampGranularity The timestampGranularity to set. |
|
|
|
*/ |
|
|
|
public void setTimestampGranularity(Granularity timestampGranularity) { |
|
|
|
if (null == timestampGranularity || "".equals(timestampGranularity.getValue())) { |
|
|
|
return; |
|
|
|
} |
|
|
|
this.timestampGranularity = timestampGranularity; |
|
|
|
} |
|
|
|
/** |
|
|
|
* Sets the siteCommand attribute. This attribute |
|
|
|
* names the command that will be executed if the action |
|
|
|
* is "site". |
|
|
|
* @param siteCommand The siteCommand to set. |
|
|
|
*/ |
|
|
|
public void setSiteCommand(String siteCommand) { |
|
|
|
this.siteCommand = siteCommand; |
|
|
|
} |
|
|
|
|
|
|
|
public String getSiteCommand() { |
|
|
|
return siteCommand; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the initialSiteCommand attribute. This attribute |
|
|
|
* names a site command that will be executed immediately |
|
|
|
* after connection. |
|
|
|
* @param initialCommand The initialSiteCommand to set. |
|
|
|
*/ |
|
|
|
public void setInitialSiteCommand(String initialCommand) { |
|
|
|
this.initialSiteCommand = initialCommand; |
|
|
|
} |
|
|
|
|
|
|
|
public String getInitialSiteCommand() { |
|
|
|
return initialSiteCommand; |
|
|
|
} |
|
|
|
|
|
|
|
public long getGranularityMillis() { |
|
|
|
return this.granularityMillis; |
|
|
|
} |
|
|
|
|
|
|
|
public void setGranularityMillis(long granularity) { |
|
|
|
this.granularityMillis = granularity; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Whether to verify that data and control connections are |
|
|
|
* connected to the same remote host. |
|
|
|
* |
|
|
|
* @since Ant 1.8.0 |
|
|
|
*/ |
|
|
|
public void setEnableRemoteVerification(boolean b) { |
|
|
|
enableRemoteVerification = b; |
|
|
|
} |
|
|
|
|
|
|
|
public boolean getEnableRemoteVerification() { |
|
|
|
return enableRemoteVerification; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Checks to see that all required parameters are set. |
|
|
|
* |
|
|
|
* @throws BuildException if the configuration is not valid. |
|
|
|
*/ |
|
|
|
protected void checkAttributes() throws BuildException { |
|
|
|
if (server == null) { |
|
|
|
throw new BuildException("server attribute must be set!"); |
|
|
|
} |
|
|
|
if (userid == null) { |
|
|
|
throw new BuildException("userid attribute must be set!"); |
|
|
|
} |
|
|
|
if (password == null) { |
|
|
|
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!"); |
|
|
|
} |
|
|
|
|
|
|
|
if (action == MK_DIR && remotedir == null) { |
|
|
|
throw new BuildException("remotedir attribute must be set for " |
|
|
|
+ "mkdir action!"); |
|
|
|
} |
|
|
|
|
|
|
|
if (action == CHMOD && chmod == null) { |
|
|
|
throw new BuildException("chmod attribute must be set for chmod " |
|
|
|
+ "action!"); |
|
|
|
} |
|
|
|
if (action == SITE_CMD && siteCommand == null) { |
|
|
|
throw new BuildException("sitecommand attribute must be set for site " |
|
|
|
+ "action!"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (this.isConfigurationSet) { |
|
|
|
try { |
|
|
|
Class.forName("org.apache.commons.net.ftp.FTPClientConfig"); |
|
|
|
} catch (ClassNotFoundException e) { |
|
|
|
throw new BuildException( |
|
|
|
"commons-net.jar >= 1.4.0 is required for at least one" |
|
|
|
+ " of the attributes specified."); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Runs the task. |
|
|
|
* |
|
|
|
* @throws BuildException if the task fails or is not configured |
|
|
|
* correctly. |
|
|
|
*/ |
|
|
|
public void execute() throws BuildException { |
|
|
|
checkAttributes(); |
|
|
|
try { |
|
|
|
setupFTPDelegate(); |
|
|
|
delegate.doFTP(); |
|
|
|
} finally { |
|
|
|
if (mirrorLoader instanceof SplitClassLoader) { |
|
|
|
((SplitClassLoader) mirrorLoader).cleanup(); |
|
|
|
} |
|
|
|
mirrorLoader = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public Path createClasspath() { |
|
|
|
if (classpath == null) { |
|
|
|
classpath = new Path(getProject()); |
|
|
|
} |
|
|
|
return classpath; |
|
|
|
} |
|
|
|
|
|
|
|
protected void setupFTPDelegate() { |
|
|
|
ClassLoader myLoader = FTPTask.class.getClassLoader(); |
|
|
|
if (mustSplit()) { |
|
|
|
mirrorLoader = |
|
|
|
new SplitClassLoader(myLoader, classpath, getProject(), |
|
|
|
new String[] { |
|
|
|
"FTPTaskMirrorImpl", |
|
|
|
"FTPConfigurator" |
|
|
|
}); |
|
|
|
} else { |
|
|
|
mirrorLoader = myLoader; |
|
|
|
} |
|
|
|
delegate = createMirror(this, mirrorLoader); |
|
|
|
} |
|
|
|
|
|
|
|
private static boolean mustSplit() { |
|
|
|
return LoaderUtils.getResourceSource(FTPTask.class.getClassLoader(), |
|
|
|
"/org/apache/commons/net/" |
|
|
|
+ "ftp/FTP.class") |
|
|
|
== null; |
|
|
|
} |
|
|
|
|
|
|
|
private static FTPTaskMirror createMirror(FTPTask task, |
|
|
|
ClassLoader loader) { |
|
|
|
try { |
|
|
|
loader.loadClass("org.apache.commons.net.ftp.FTP"); // sanity check |
|
|
|
} catch (ClassNotFoundException e) { |
|
|
|
throw new BuildException("The <classpath> for <ftp> must include" |
|
|
|
+ " commons-net.jar if not in Ant's own " |
|
|
|
+ " classpath", e, task.getLocation()); |
|
|
|
} |
|
|
|
try { |
|
|
|
Class c = loader.loadClass(FTPTaskMirror.class.getName() + "Impl"); |
|
|
|
if (c.getClassLoader() != loader) { |
|
|
|
throw new BuildException("Overdelegating loader", |
|
|
|
task.getLocation()); |
|
|
|
} |
|
|
|
Constructor cons = c.getConstructor(new Class[] {FTPTask.class}); |
|
|
|
return (FTPTaskMirror) cons.newInstance(new Object[] {task}); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new BuildException(e, task.getLocation()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* an action to perform, one of |
|
|
|
* "send", "put", "recv", "get", "del", "delete", "list", "mkdir", "chmod", |
|
|
|
* "rmdir" |
|
|
|
*/ |
|
|
|
public static class Action extends EnumeratedAttribute { |
|
|
|
|
|
|
|
private static final String[] VALID_ACTIONS = { |
|
|
|
"send", "put", "recv", "get", "del", "delete", "list", "mkdir", |
|
|
|
"chmod", "rmdir", "site" |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get the valid values |
|
|
|
* |
|
|
|
* @return an array of the valid FTP actions. |
|
|
|
*/ |
|
|
|
public String[] getValues() { |
|
|
|
return VALID_ACTIONS; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get the symbolic equivalent of the action value. |
|
|
|
* |
|
|
|
* @return the SYMBOL representing the given action. |
|
|
|
*/ |
|
|
|
public int getAction() { |
|
|
|
String actionL = getValue().toLowerCase(Locale.US); |
|
|
|
|
|
|
|
if (actionL.equals("send") || actionL.equals("put")) { |
|
|
|
return SEND_FILES; |
|
|
|
} else if (actionL.equals("recv") || actionL.equals("get")) { |
|
|
|
return GET_FILES; |
|
|
|
} else if (actionL.equals("del") || actionL.equals("delete")) { |
|
|
|
return DEL_FILES; |
|
|
|
} else if (actionL.equals("list")) { |
|
|
|
return LIST_FILES; |
|
|
|
} else if (actionL.equals("chmod")) { |
|
|
|
return CHMOD; |
|
|
|
} else if (actionL.equals("mkdir")) { |
|
|
|
return MK_DIR; |
|
|
|
} else if (actionL.equals("rmdir")) { |
|
|
|
return RM_DIR; |
|
|
|
} else if (actionL.equals("site")) { |
|
|
|
return SITE_CMD; |
|
|
|
} |
|
|
|
return SEND_FILES; |
|
|
|
} |
|
|
|
} |
|
|
|
/** |
|
|
|
* represents one of the valid timestamp adjustment values |
|
|
|
* recognized by the <code>timestampGranularity</code> attribute.<p> |
|
|
|
|
|
|
|
* A timestamp adjustment may be used in file transfers for checking |
|
|
|
* uptodateness. MINUTE means to add one minute to the server |
|
|
|
* timestamp. This is done because FTP servers typically list |
|
|
|
* timestamps HH:mm and client FileSystems typically use HH:mm:ss. |
|
|
|
* |
|
|
|
* The default is to use MINUTE for PUT actions and NONE for GET |
|
|
|
* actions, since GETs have the <code>preserveLastModified</code> |
|
|
|
* option, which takes care of the problem in most use cases where |
|
|
|
* this level of granularity is an issue. |
|
|
|
* |
|
|
|
*/ |
|
|
|
public static class Granularity extends EnumeratedAttribute { |
|
|
|
|
|
|
|
private static final String[] VALID_GRANULARITIES = { |
|
|
|
"", "MINUTE", "NONE" |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the valid values. |
|
|
|
* @return the list of valid Granularity values |
|
|
|
*/ |
|
|
|
public String[] getValues() { |
|
|
|
return VALID_GRANULARITIES; |
|
|
|
} |
|
|
|
/** |
|
|
|
* returns the number of milliseconds associated with |
|
|
|
* the attribute, which can vary in some cases depending |
|
|
|
* on the value of the action parameter. |
|
|
|
* @param action SEND_FILES or GET_FILES |
|
|
|
* @return the number of milliseconds associated with |
|
|
|
* the attribute, in the context of the supplied action |
|
|
|
*/ |
|
|
|
public long getMilliseconds(int action) { |
|
|
|
String granularityU = getValue().toUpperCase(Locale.US); |
|
|
|
|
|
|
|
if ("".equals(granularityU)) { |
|
|
|
if (action == SEND_FILES) { |
|
|
|
return GRANULARITY_MINUTE; |
|
|
|
} |
|
|
|
} else if ("MINUTE".equals(granularityU)) { |
|
|
|
return GRANULARITY_MINUTE; |
|
|
|
} |
|
|
|
return 0L; |
|
|
|
} |
|
|
|
static final Granularity getDefault() { |
|
|
|
Granularity g = new Granularity(); |
|
|
|
g.setValue(""); |
|
|
|
return g; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
/** |
|
|
|
* one of the valid system type keys recognized by the systemTypeKey |
|
|
|
* attribute. |
|
|
|
*/ |
|
|
|
public static class FTPSystemType extends EnumeratedAttribute { |
|
|
|
|
|
|
|
private static final String[] VALID_SYSTEM_TYPES = { |
|
|
|
"", "UNIX", "VMS", "WINDOWS", "OS/2", "OS/400", |
|
|
|
"MVS" |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get the valid values. |
|
|
|
* @return the list of valid system types. |
|
|
|
*/ |
|
|
|
public String[] getValues() { |
|
|
|
return VALID_SYSTEM_TYPES; |
|
|
|
} |
|
|
|
|
|
|
|
static final FTPSystemType getDefault() { |
|
|
|
FTPSystemType ftpst = new FTPSystemType(); |
|
|
|
ftpst.setValue(""); |
|
|
|
return ftpst; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |