📄 ftp.java
字号:
/* * 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.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.text.SimpleDateFormat;import java.util.Collection;import java.util.Date;import java.util.Enumeration;import java.util.HashMap;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;import java.util.Locale;import java.util.Map;import java.util.Set;import java.util.StringTokenizer;import java.util.Vector;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPClientConfig;import org.apache.commons.net.ftp.FTPFile;import org.apache.commons.net.ftp.FTPReply;import org.apache.tools.ant.BuildException;import org.apache.tools.ant.DirectoryScanner;import org.apache.tools.ant.Project;import org.apache.tools.ant.Task;import org.apache.tools.ant.taskdefs.Delete;import org.apache.tools.ant.types.EnumeratedAttribute;import org.apache.tools.ant.types.FileSet;import org.apache.tools.ant.types.selectors.SelectorUtils;import org.apache.tools.ant.util.FileUtils;import org.apache.tools.ant.util.RetryHandler;import org.apache.tools.ant.util.Retryable;/** * 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 FTP extends Task { protected static final int SEND_FILES = 0; protected static final int GET_FILES = 1; protected static final int DEL_FILES = 2; protected static final int LIST_FILES = 3; protected static final int MK_DIR = 4; protected static final int CHMOD = 5; protected static final int RM_DIR = 6; protected static final int SITE_CMD = 7; /** return code of ftp - not implemented in commons-net version 1.0 */ private static final int CODE_521 = 521; /** 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 static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 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 Vector dirCache = new Vector(); private int transferred = 0; private String remoteFileSep = "/"; private int port = DEFAULT_FTP_PORT; private boolean skipFailedTransfers = false; private int skipped = 0; 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 LanguageCode serverLanguageCodeConfig = LanguageCode.getDefault(); 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; protected static final String[] ACTION_STRS = { "sending", "getting", "deleting", "listing", "making directory", "chmod", "removing", "site" }; protected static final String[] COMPLETED_ACTION_STRS = { "sent", "retrieved", "deleted", "listed", "created directory", "mode changed", "removed", "site command executed" }; protected static final String[] ACTION_TARGET_STRS = { "files", "files", "files", "files", "directory", "files", "directories", "site command" }; /** * internal class allowing to read the contents of a remote file system * using the FTP protocol * used in particular for ftp get operations * differences with DirectoryScanner * "" (the root of the fileset) is never included in the included directories * followSymlinks defaults to false */ protected class FTPDirectoryScanner extends DirectoryScanner { // CheckStyle:VisibilityModifier OFF - bc protected FTPClient ftp = null; // CheckStyle:VisibilityModifier ON private String rootPath = null; /** * since ant 1.6 * this flag should be set to true on UNIX and can save scanning time */ private boolean remoteSystemCaseSensitive = false; private boolean remoteSensitivityChecked = false; /** * constructor * @param ftp ftpclient object */ public FTPDirectoryScanner(FTPClient ftp) { super(); this.ftp = ftp; this.setFollowSymlinks(false); } /** * scans the remote directory, * storing internally the included files, directories, ... */ 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(); // always start from the current ftp working dir forceRemoteSensitivityCheck(); checkIncludePatterns(); clearCaches(); ftp.changeWorkingDirectory(cwd); } catch (IOException e) { throw new BuildException("Unable to scan FTP server: ", e); } } /** * this routine is actually checking all the include patterns in * order to avoid scanning everything under base dir * @since ant1.6 */ private void checkIncludePatterns() { Hashtable newroots = new Hashtable(); // put in the newroots vector the include patterns without // wildcard tokens for (int icounter = 0; icounter < includes.length; icounter++) { String newpattern = SelectorUtils.rtrimWildcardTokens(includes[icounter]); newroots.put(newpattern, includes[icounter]); } if (remotedir == null) { try { remotedir = ftp.printWorkingDirectory(); } catch (IOException e) { throw new BuildException("could not read current ftp directory", getLocation()); } } AntFTPFile baseFTPFile = new AntFTPRootFile(ftp, remotedir); rootPath = baseFTPFile.getAbsolutePath(); // construct it if (newroots.containsKey("")) { // we are going to scan everything anyway scandir(rootPath, "", true); } else { // only scan directories that can include matched files or // directories Enumeration enum2 = newroots.keys(); while (enum2.hasMoreElements()) { String currentelement = (String) enum2.nextElement(); String originalpattern = (String) newroots.get(currentelement); AntFTPFile myfile = new AntFTPFile(baseFTPFile, currentelement); boolean isOK = true; boolean traversesSymlinks = false; String path = null; if (myfile.exists()) { forceRemoteSensitivityCheck(); if (remoteSensitivityChecked && remoteSystemCaseSensitive && isFollowSymlinks()) { // cool case, //we do not need to scan all the subdirs in the relative path path = myfile.getFastRelativePath(); } else { // may be on a case insensitive file system. We want // the results to show what's really on the disk, so // we need to double check. try { path = myfile.getRelativePath(); traversesSymlinks = myfile.isTraverseSymlinks(); } catch (IOException be) { throw new BuildException(be, getLocation()); } catch (BuildException be) { isOK = false; } } } else { isOK = false; } if (isOK) { currentelement = path.replace(remoteFileSep.charAt(0), File.separatorChar); if (!isFollowSymlinks() && traversesSymlinks) { continue; } if (myfile.isDirectory()) { if (isIncluded(currentelement) && currentelement.length() > 0) { accountForIncludedDir(currentelement, myfile, true); } else { if (currentelement.length() > 0) { if (currentelement.charAt(currentelement .length() - 1) != File.separatorChar) { currentelement = currentelement + File.separatorChar; } } scandir(myfile.getAbsolutePath(), currentelement, true); } } else { if (isCaseSensitive && originalpattern.equals(currentelement)) { accountForIncludedFile(currentelement); } else if (!isCaseSensitive && originalpattern .equalsIgnoreCase(currentelement)) { accountForIncludedFile(currentelement); } } } } } } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -