| /* |
| * 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 |
| * |
| * https://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.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 { |
| public static final int SEND_FILES = 0; |
| public static final int GET_FILES = 1; |
| public static final int DEL_FILES = 2; |
| public static final int LIST_FILES = 3; |
| public static final int MK_DIR = 4; |
| public static final int CHMOD = 5; |
| public static final int RM_DIR = 6; |
| public 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<FileSet> 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; |
| |
| public static final String[] ACTION_STRS = { //NOSONAR |
| "sending", |
| "getting", |
| "deleting", |
| "listing", |
| "making directory", |
| "chmod", |
| "removing", |
| "site" |
| }; |
| |
| public static final String[] COMPLETED_ACTION_STRS = { //NOSONAR |
| "sent", |
| "retrieved", |
| "deleted", |
| "listed", |
| "created directory", |
| "mode changed", |
| "removed", |
| "site command executed" |
| }; |
| |
| public static final String[] ACTION_TARGET_STRS = { //NOSONAR |
| "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 <code>depends</code>. 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<FileSet> 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. |
| */ |
| @Deprecated |
| 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().isEmpty()) { |
| 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.isEmpty()) { |
| 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.isEmpty()) { |
| 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 && !serverLanguageCode.isEmpty()) { |
| 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.isEmpty()) { |
| 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.isEmpty()) { |
| 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: %s", |
| retriesAllowed); |
| } |
| this.retriesAllowed = retries; |
| } catch (NumberFormatException px) { |
| throw new BuildException( |
| "Invalid value for retriesAllowed attribute: %s", |
| retriesAllowed); |
| } |
| |
| } |
| } |
| |
| public int getRetriesAllowed() { |
| return retriesAllowed; |
| } |
| |
| /** |
| * @return Returns the systemTypeKey. |
| */ |
| @Override |
| public String getSystemTypeKey() { |
| return systemTypeKey.getValue(); |
| } |
| |
| /** |
| * @return Returns the defaultDateFormatConfig. |
| */ |
| @Override |
| public String getDefaultDateFormatConfig() { |
| return defaultDateFormatConfig; |
| } |
| |
| /** |
| * @return Returns the recentDateFormatConfig. |
| */ |
| @Override |
| public String getRecentDateFormatConfig() { |
| return recentDateFormatConfig; |
| } |
| |
| /** |
| * @return Returns the serverLanguageCodeConfig. |
| */ |
| @Override |
| public String getServerLanguageCodeConfig() { |
| return serverLanguageCodeConfig; |
| } |
| |
| /** |
| * @return Returns the serverTimeZoneConfig. |
| */ |
| @Override |
| public String getServerTimeZoneConfig() { |
| return serverTimeZoneConfig; |
| } |
| |
| /** |
| * @return Returns the shortMonthNamesConfig. |
| */ |
| @Override |
| public String getShortMonthNamesConfig() { |
| return shortMonthNamesConfig; |
| } |
| |
| /** |
| * @return Returns the timestampGranularity. |
| */ |
| public Granularity getTimestampGranularity() { |
| return timestampGranularity; |
| } |
| |
| /** |
| * Sets the timestampGranularity attribute |
| * @param timestampGranularity The timestampGranularity to set. |
| */ |
| public void setTimestampGranularity(Granularity timestampGranularity) { |
| if (null == timestampGranularity || timestampGranularity.getValue().isEmpty()) { |
| 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. |
| * |
| * @param b boolean |
| * @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. |
| */ |
| @Override |
| 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<? extends FTPTaskMirror> c = |
| loader.loadClass(FTPTaskMirror.class.getName() + "Impl") |
| .asSubclass(FTPTaskMirror.class); |
| if (c.getClassLoader() != loader) { |
| throw new BuildException("Overdelegating loader", |
| task.getLocation()); |
| } |
| Constructor<? extends FTPTaskMirror> cons = |
| c.getConstructor(FTPTask.class); |
| return cons.newInstance(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. |
| */ |
| @Override |
| 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.ENGLISH); |
| switch (actionL) { |
| case "send": |
| case "put": |
| return SEND_FILES; |
| case "recv": |
| case "get": |
| return GET_FILES; |
| case "del": |
| case "delete": |
| return DEL_FILES; |
| case "list": |
| return LIST_FILES; |
| case "chmod": |
| return CHMOD; |
| case "mkdir": |
| return MK_DIR; |
| case "rmdir": |
| return RM_DIR; |
| case "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 |
| */ |
| @Override |
| 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.ENGLISH); |
| if (granularityU.isEmpty()) { |
| 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. |
| */ |
| @Override |
| public String[] getValues() { |
| return VALID_SYSTEM_TYPES; |
| } |
| |
| static final FTPSystemType getDefault() { |
| FTPSystemType ftpst = new FTPSystemType(); |
| ftpst.setValue(""); |
| return ftpst; |
| } |
| } |
| |
| } |