1 18 package org.apache.tools.ant.taskdefs.optional.net; 19 20 import java.io.BufferedInputStream ; 21 import java.io.BufferedOutputStream ; 22 import java.io.BufferedWriter ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileOutputStream ; 26 import java.io.FileWriter ; 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.OutputStream ; 30 import java.text.SimpleDateFormat ; 31 import java.util.Collection ; 32 import java.util.Date ; 33 import java.util.Enumeration ; 34 import java.util.HashMap ; 35 import java.util.HashSet ; 36 import java.util.Hashtable ; 37 import java.util.Iterator ; 38 import java.util.Locale ; 39 import java.util.Map ; 40 import java.util.Set ; 41 import java.util.StringTokenizer ; 42 import java.util.Vector ; 43 44 import org.apache.commons.net.ftp.FTPClient; 45 import org.apache.commons.net.ftp.FTPClientConfig; 46 import org.apache.commons.net.ftp.FTPFile; 47 import org.apache.commons.net.ftp.FTPReply; 48 import org.apache.tools.ant.BuildException; 49 import org.apache.tools.ant.DirectoryScanner; 50 import org.apache.tools.ant.Project; 51 import org.apache.tools.ant.Task; 52 import org.apache.tools.ant.taskdefs.Delete; 53 import org.apache.tools.ant.types.EnumeratedAttribute; 54 import org.apache.tools.ant.types.FileSet; 55 import org.apache.tools.ant.types.selectors.SelectorUtils; 56 import org.apache.tools.ant.util.FileUtils; 57 import org.apache.tools.ant.util.RetryHandler; 58 import org.apache.tools.ant.util.Retryable; 59 60 81 public class FTP 82 extends Task { 83 protected static final int SEND_FILES = 0; 84 protected static final int GET_FILES = 1; 85 protected static final int DEL_FILES = 2; 86 protected static final int LIST_FILES = 3; 87 protected static final int MK_DIR = 4; 88 protected static final int CHMOD = 5; 89 protected static final int RM_DIR = 6; 90 protected static final int SITE_CMD = 7; 91 92 private static final int CODE_521 = 521; 93 94 96 private static final long GRANULARITY_MINUTE = 60000L; 97 98 99 public static final int DEFAULT_FTP_PORT = 21; 100 101 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 102 103 private String remotedir; 104 private String server; 105 private String userid; 106 private String password; 107 private String account; 108 private File listing; 109 private boolean binary = true; 110 private boolean passive = false; 111 private boolean verbose = false; 112 private boolean newerOnly = false; 113 private long timeDiffMillis = 0; 114 private long granularityMillis = 0L; 115 private boolean timeDiffAuto = false; 116 private int action = SEND_FILES; 117 private Vector filesets = new Vector (); 118 private Vector dirCache = new Vector (); 119 private int transferred = 0; 120 private String remoteFileSep = "/"; 121 private int port = DEFAULT_FTP_PORT; 122 private boolean skipFailedTransfers = false; 123 private int skipped = 0; 124 private boolean ignoreNoncriticalErrors = false; 125 private boolean preserveLastModified = false; 126 private String chmod = null; 127 private String umask = null; 128 private FTPSystemType systemTypeKey = FTPSystemType.getDefault(); 129 private String defaultDateFormatConfig = null; 130 private String recentDateFormatConfig = null; 131 private LanguageCode serverLanguageCodeConfig = LanguageCode.getDefault(); 132 private String serverTimeZoneConfig = null; 133 private String shortMonthNamesConfig = null; 134 private Granularity timestampGranularity = Granularity.getDefault(); 135 private boolean isConfigurationSet = false; 136 private int retriesAllowed = 0; 137 private String siteCommand = null; 138 private String initialSiteCommand = null; 139 140 protected static final String [] ACTION_STRS = { 141 "sending", 142 "getting", 143 "deleting", 144 "listing", 145 "making directory", 146 "chmod", 147 "removing", 148 "site" 149 }; 150 151 protected static final String [] COMPLETED_ACTION_STRS = { 152 "sent", 153 "retrieved", 154 "deleted", 155 "listed", 156 "created directory", 157 "mode changed", 158 "removed", 159 "site command executed" 160 }; 161 162 protected static final String [] ACTION_TARGET_STRS = { 163 "files", 164 "files", 165 "files", 166 "files", 167 "directory", 168 "files", 169 "directories", 170 "site command" 171 }; 172 173 174 182 protected class FTPDirectoryScanner extends DirectoryScanner { 183 protected FTPClient ftp = null; 185 187 private String rootPath = null; 188 189 193 private boolean remoteSystemCaseSensitive = false; 194 private boolean remoteSensitivityChecked = false; 195 196 200 public FTPDirectoryScanner(FTPClient ftp) { 201 super(); 202 this.ftp = ftp; 203 this.setFollowSymlinks(false); 204 } 205 206 207 211 public void scan() { 212 if (includes == null) { 213 includes = new String [1]; 215 includes[0] = "**"; 216 } 217 if (excludes == null) { 218 excludes = new String [0]; 219 } 220 221 filesIncluded = new Vector (); 222 filesNotIncluded = new Vector (); 223 filesExcluded = new Vector (); 224 dirsIncluded = new Vector (); 225 dirsNotIncluded = new Vector (); 226 dirsExcluded = new Vector (); 227 228 try { 229 String cwd = ftp.printWorkingDirectory(); 230 forceRemoteSensitivityCheck(); 232 233 checkIncludePatterns(); 234 clearCaches(); 235 ftp.changeWorkingDirectory(cwd); 236 } catch (IOException e) { 237 throw new BuildException("Unable to scan FTP server: ", e); 238 } 239 } 240 241 242 247 private void checkIncludePatterns() { 248 249 Hashtable newroots = new Hashtable (); 250 for (int icounter = 0; icounter < includes.length; icounter++) { 253 String newpattern = 254 SelectorUtils.rtrimWildcardTokens(includes[icounter]); 255 newroots.put(newpattern, includes[icounter]); 256 } 257 if (remotedir == null) { 258 try { 259 remotedir = ftp.printWorkingDirectory(); 260 } catch (IOException e) { 261 throw new BuildException("could not read current ftp directory", 262 getLocation()); 263 } 264 } 265 AntFTPFile baseFTPFile = new AntFTPRootFile(ftp, remotedir); 266 rootPath = baseFTPFile.getAbsolutePath(); 267 if (newroots.containsKey("")) { 269 scandir(rootPath, "", true); 271 } else { 272 Enumeration enum2 = newroots.keys(); 275 276 while (enum2.hasMoreElements()) { 277 String currentelement = (String ) enum2.nextElement(); 278 String originalpattern = (String ) newroots.get(currentelement); 279 AntFTPFile myfile = new AntFTPFile(baseFTPFile, currentelement); 280 boolean isOK = true; 281 boolean traversesSymlinks = false; 282 String path = null; 283 284 if (myfile.exists()) { 285 forceRemoteSensitivityCheck(); 286 if (remoteSensitivityChecked 287 && remoteSystemCaseSensitive && isFollowSymlinks()) { 288 path = myfile.getFastRelativePath(); 291 } else { 292 try { 296 path = myfile.getRelativePath(); 297 traversesSymlinks = myfile.isTraverseSymlinks(); 298 } catch (IOException be) { 299 throw new BuildException(be, getLocation()); 300 } catch (BuildException be) { 301 isOK = false; 302 } 303 } 304 } else { 305 isOK = false; 306 } 307 if (isOK) { 308 currentelement = path.replace(remoteFileSep.charAt(0), File.separatorChar); 309 if (!isFollowSymlinks() 310 && traversesSymlinks) { 311 continue; 312 } 313 314 if (myfile.isDirectory()) { 315 if (isIncluded(currentelement) 316 && currentelement.length() > 0) { 317 accountForIncludedDir(currentelement, myfile, true); 318 } else { 319 if (currentelement.length() > 0) { 320 if (currentelement.charAt(currentelement 321 .length() - 1) 322 != File.separatorChar) { 323 currentelement = 324 currentelement + File.separatorChar; 325 } 326 } 327 scandir(myfile.getAbsolutePath(), currentelement, true); 328 } 329 } else { 330 if (isCaseSensitive 331 && originalpattern.equals(currentelement)) { 332 accountForIncludedFile(currentelement); 333 } else if (!isCaseSensitive 334 && originalpattern 335 .equalsIgnoreCase(currentelement)) { 336 accountForIncludedFile(currentelement); 337 } 338 } 339 } 340 } 341 } 342 } 343 350 protected void scandir(String dir, String vpath, boolean fast) { 351 if (fast && hasBeenScanned(vpath)) { 353 return; 354 } 355 try { 356 if (!ftp.changeWorkingDirectory(dir)) { 357 return; 358 } 359 String completePath = null; 360 if (!vpath.equals("")) { 361 completePath = rootPath + remoteFileSep 362 + vpath.replace(File.separatorChar, remoteFileSep.charAt(0)); 363 } else { 364 completePath = rootPath; 365 } 366 FTPFile[] newfiles = listFiles(completePath, false); 367 368 if (newfiles == null) { 369 ftp.changeToParentDirectory(); 370 return; 371 } 372 for (int i = 0; i < newfiles.length; i++) { 373 FTPFile file = newfiles[i]; 374 if (!file.getName().equals(".") 375 && !file.getName().equals("..")) { 376 if (isFunctioningAsDirectory(ftp, dir, file)) { 377 String name = vpath + file.getName(); 378 boolean slowScanAllowed = true; 379 if (!isFollowSymlinks() && file.isSymbolicLink()) { 380 dirsExcluded.addElement(name); 381 slowScanAllowed = false; 382 } else if (isIncluded(name)) { 383 accountForIncludedDir(name, 384 new AntFTPFile(ftp, file, completePath) , fast); 385 } else { 386 dirsNotIncluded.addElement(name); 387 if (fast && couldHoldIncluded(name)) { 388 scandir(file.getName(), 389 name + File.separator, fast); 390 } 391 } 392 if (!fast && slowScanAllowed) { 393 scandir(file.getName(), 394 name + File.separator, fast); 395 } 396 } else { 397 String name = vpath + file.getName(); 398 if (!isFollowSymlinks() && file.isSymbolicLink()) { 399 filesExcluded.addElement(name); 400 } else if (isFunctioningAsFile(ftp, dir, file)) { 401 accountForIncludedFile(name); 402 } 403 } 404 } 405 } 406 ftp.changeToParentDirectory(); 407 } catch (IOException e) { 408 throw new BuildException("Error while communicating with FTP " 409 + "server: ", e); 410 } 411 } 412 416 private void accountForIncludedFile(String name) { 417 if (!filesIncluded.contains(name) 418 && !filesExcluded.contains(name)) { 419 420 if (isIncluded(name)) { 421 if (!isExcluded(name)) { 422 filesIncluded.addElement(name); 423 } else { 424 filesExcluded.addElement(name); 425 } 426 } else { 427 filesNotIncluded.addElement(name); 428 } 429 } 430 } 431 432 439 private void accountForIncludedDir(String name, AntFTPFile file, boolean fast) { 440 if (!dirsIncluded.contains(name) 441 && !dirsExcluded.contains(name)) { 442 443 if (!isExcluded(name)) { 444 if (fast) { 445 if (file.isSymbolicLink()) { 446 try { 447 file.getClient().changeWorkingDirectory(file.curpwd); 448 } catch (IOException ioe) { 449 throw new BuildException("could not change directory to curpwd"); 450 } 451 scandir(file.getLink(), 452 name + File.separator, fast); 453 } else { 454 try { 455 file.getClient().changeWorkingDirectory(file.curpwd); 456 } catch (IOException ioe) { 457 throw new BuildException("could not change directory to curpwd"); 458 } 459 scandir(file.getName(), 460 name + File.separator, fast); 461 } 462 } 463 dirsIncluded.addElement(name); 464 } else { 465 dirsExcluded.addElement(name); 466 if (fast && couldHoldIncluded(name)) { 467 try { 468 file.getClient().changeWorkingDirectory(file.curpwd); 469 } catch (IOException ioe) { 470 throw new BuildException("could not change directory to curpwd"); 471 } 472 scandir(file.getName(), 473 name + File.separator, fast); 474 } 475 } 476 } 477 } 478 483 private Map fileListMap = new HashMap (); 484 489 private Set scannedDirs = new HashSet (); 490 491 499 private boolean hasBeenScanned(String vpath) { 500 return !scannedDirs.add(vpath); 501 } 502 503 508 private void clearCaches() { 509 fileListMap.clear(); 510 scannedDirs.clear(); 511 } 512 518 public FTPFile[] listFiles(String directory, boolean changedir) { 519 String currentPath = directory; 521 if (changedir) { 522 try { 523 boolean result = ftp.changeWorkingDirectory(directory); 524 if (!result) { 525 return null; 526 } 527 currentPath = ftp.printWorkingDirectory(); 528 } catch (IOException ioe) { 529 throw new BuildException(ioe, getLocation()); 530 } 531 } 532 if (fileListMap.containsKey(currentPath)) { 533 getProject().log("filelist map used in listing files", Project.MSG_DEBUG); 534 return ((FTPFile[]) fileListMap.get(currentPath)); 535 } 536 FTPFile[] result = null; 537 try { 538 result = ftp.listFiles(); 539 } catch (IOException ioe) { 540 throw new BuildException(ioe, getLocation()); 541 } 542 fileListMap.put(currentPath, result); 543 if (!remoteSensitivityChecked) { 544 checkRemoteSensitivity(result, directory); 545 } 546 return result; 547 } 548 549 private void forceRemoteSensitivityCheck() { 550 if (!remoteSensitivityChecked) { 551 try { 552 checkRemoteSensitivity(ftp.listFiles(), ftp.printWorkingDirectory()); 553 } catch (IOException ioe) { 554 throw new BuildException(ioe, getLocation()); 555 } 556 } 557 } 558 564 public FTPFile[] listFiles(String directory) { 565 return listFiles(directory, true); 566 } 567 private void checkRemoteSensitivity(FTPFile[] array, String directory) { 568 if (array == null) { 569 return; 570 } 571 boolean candidateFound = false; 572 String target = null; 573 for (int icounter = 0; icounter < array.length; icounter++) { 574 if (array[icounter].isDirectory()) { 575 if (!array[icounter].getName().equals(".") 576 && !array[icounter].getName().equals("..")) { 577 candidateFound = true; 578 target = fiddleName(array[icounter].getName()); 579 getProject().log("will try to cd to " 580 + target + " where a directory called " + array[icounter].getName() 581 + " exists", Project.MSG_DEBUG); 582 for (int pcounter = 0; pcounter < array.length; pcounter++) { 583 if (array[pcounter].getName().equals(target) && pcounter != icounter) { 584 candidateFound = false; 585 } 586 } 587 if (candidateFound) { 588 break; 589 } 590 } 591 } 592 } 593 if (candidateFound) { 594 try { 595 getProject().log("testing case sensitivity, attempting to cd to " 596 + target, Project.MSG_DEBUG); 597 remoteSystemCaseSensitive = !ftp.changeWorkingDirectory(target); 598 } catch (IOException ioe) { 599 remoteSystemCaseSensitive = true; 600 } finally { 601 try { 602 ftp.changeWorkingDirectory(directory); 603 } catch (IOException ioe) { 604 throw new BuildException(ioe, getLocation()); 605 } 606 } 607 getProject().log("remote system is case sensitive : " + remoteSystemCaseSensitive, 608 Project.MSG_VERBOSE); 609 remoteSensitivityChecked = true; 610 } 611 } 612 private String fiddleName(String origin) { 613 StringBuffer result = new StringBuffer (); 614 for (int icounter = 0; icounter < origin.length(); icounter++) { 615 if (Character.isLowerCase(origin.charAt(icounter))) { 616 result.append(Character.toUpperCase(origin.charAt(icounter))); 617 } else if (Character.isUpperCase(origin.charAt(icounter))) { 618 result.append(Character.toLowerCase(origin.charAt(icounter))); 619 } else { 620 result.append(origin.charAt(icounter)); 621 } 622 } 623 return result.toString(); 624 } 625 629 protected class AntFTPFile { 630 633 private FTPClient client; 634 637 private String curpwd; 638 641 private FTPFile ftpFile; 642 645 private AntFTPFile parent = null; 646 private boolean relativePathCalculated = false; 647 private boolean traversesSymlinks = false; 648 private String relativePath = ""; 649 655 public AntFTPFile(FTPClient client, FTPFile ftpFile, String curpwd) { 656 this.client = client; 657 this.ftpFile = ftpFile; 658 this.curpwd = curpwd; 659 } 660 665 public AntFTPFile(AntFTPFile parent, String path) { 666 this.parent = parent; 667 this.client = parent.client; 668 Vector pathElements = SelectorUtils.tokenizePath(path); 669 try { 670 boolean result = this.client.changeWorkingDirectory(parent.getAbsolutePath()); 671 if (!result) { 673 return; 674 } 675 this.curpwd = parent.getAbsolutePath(); 676 } catch (IOException ioe) { 677 throw new BuildException("could not change working dir to " 678 + parent.curpwd); 679 } 680 for (int fcount = 0; fcount < pathElements.size() - 1; fcount++) { 681 String currentPathElement = (String ) pathElements.elementAt(fcount); 682 try { 683 boolean result = this.client.changeWorkingDirectory(currentPathElement); 684 if (!result && !isCaseSensitive() 685 && (remoteSystemCaseSensitive || !remoteSensitivityChecked)) { 686 currentPathElement = findPathElementCaseUnsensitive(this.curpwd, 687 currentPathElement); 688 if (currentPathElement == null) { 689 return; 690 } 691 } else if (!result) { 692 return; 693 } 694 this.curpwd = this.curpwd + remoteFileSep 695 + currentPathElement; 696 } catch (IOException ioe) { 697 throw new BuildException("could not change working dir to " 698 + (String ) pathElements.elementAt(fcount) 699 + " from " + this.curpwd); 700 } 701 702 } 703 String lastpathelement = (String ) pathElements.elementAt(pathElements.size() - 1); 704 FTPFile [] theFiles = listFiles(this.curpwd); 705 this.ftpFile = getFile(theFiles, lastpathelement); 706 } 707 713 private String findPathElementCaseUnsensitive(String parentPath, 714 String soughtPathElement) { 715 FTPFile[] theFiles = listFiles(parentPath, false); 718 if (theFiles == null) { 719 return null; 720 } 721 for (int icounter = 0; icounter < theFiles.length; icounter++) { 722 if (theFiles[icounter].getName().equalsIgnoreCase(soughtPathElement)) { 723 return theFiles[icounter].getName(); 724 } 725 } 726 return null; 727 } 728 732 public boolean exists() { 733 return (ftpFile != null); 734 } 735 739 public String getLink() { 740 return ftpFile.getLink(); 741 } 742 746 public String getName() { 747 return ftpFile.getName(); 748 } 749 753 public String getAbsolutePath() { 754 return curpwd + remoteFileSep + ftpFile.getName(); 755 } 756 762 public String getFastRelativePath() { 763 String absPath = getAbsolutePath(); 764 if (absPath.indexOf(rootPath + remoteFileSep) == 0) { 765 return absPath.substring(rootPath.length() + remoteFileSep.length()); 766 } 767 return null; 768 } 769 782 public String getRelativePath() throws IOException , BuildException { 783 if (!relativePathCalculated) { 784 if (parent != null) { 785 traversesSymlinks = parent.isTraverseSymlinks(); 786 relativePath = getRelativePath(parent.getAbsolutePath(), 787 parent.getRelativePath()); 788 } else { 789 relativePath = getRelativePath(rootPath, ""); 790 relativePathCalculated = true; 791 } 792 } 793 return relativePath; 794 } 795 801 private String getRelativePath(String currentPath, String currentRelativePath) { 802 Vector pathElements = SelectorUtils.tokenizePath(getAbsolutePath(), remoteFileSep); 803 Vector pathElements2 = SelectorUtils.tokenizePath(currentPath, remoteFileSep); 804 String relPath = currentRelativePath; 805 for (int pcount = pathElements2.size(); pcount < pathElements.size(); pcount++) { 806 String currentElement = (String ) pathElements.elementAt(pcount); 807 FTPFile[] theFiles = listFiles(currentPath); 808 FTPFile theFile = null; 809 if (theFiles != null) { 810 theFile = getFile(theFiles, currentElement); 811 } 812 if (!relPath.equals("")) { 813 relPath = relPath + remoteFileSep; 814 } 815 if (theFile == null) { 816 relPath = relPath + currentElement; 818 currentPath = currentPath + remoteFileSep + currentElement; 819 log("Hidden file " + relPath 820 + " assumed to not be a symlink.", 821 Project.MSG_VERBOSE); 822 } else { 823 traversesSymlinks = traversesSymlinks || theFile.isSymbolicLink(); 824 relPath = relPath + theFile.getName(); 825 currentPath = currentPath + remoteFileSep + theFile.getName(); 826 } 827 } 828 return relPath; 829 } 830 839 public FTPFile getFile(FTPFile[] theFiles, String lastpathelement) { 840 if (theFiles == null) { 841 return null; 842 } 843 for (int fcount = 0; fcount < theFiles.length; fcount++) { 844 if (theFiles[fcount].getName().equals(lastpathelement)) { 845 return theFiles[fcount]; 846 } else if (!isCaseSensitive() 847 && theFiles[fcount].getName().equalsIgnoreCase(lastpathelement)) { 848 return theFiles[fcount]; 849 } 850 } 851 return null; 852 } 853 858 public boolean isDirectory() { 859 return ftpFile.isDirectory(); 860 } 861 865 public boolean isSymbolicLink() { 866 return ftpFile.isSymbolicLink(); 867 } 868 873 protected FTPClient getClient() { 874 return client; 875 } 876 877 881 protected void setCurpwd(String curpwd) { 882 this.curpwd = curpwd; 883 } 884 889 public String getCurpwd() { 890 return curpwd; 891 } 892 900 public boolean isTraverseSymlinks() throws IOException , BuildException { 901 if (!relativePathCalculated) { 902 getRelativePath(); 904 } 905 return traversesSymlinks; 906 } 907 908 912 public String toString() { 913 return "AntFtpFile: " + curpwd + "%" + ftpFile; 914 } 915 } 916 920 protected class AntFTPRootFile extends AntFTPFile { 921 private String remotedir; 922 927 public AntFTPRootFile(FTPClient aclient, String remotedir) { 928 super(aclient, null, remotedir); 929 this.remotedir = remotedir; 930 try { 931 this.getClient().changeWorkingDirectory(this.remotedir); 932 this.setCurpwd(this.getClient().printWorkingDirectory()); 933 } catch (IOException ioe) { 934 throw new BuildException(ioe, getLocation()); 935 } 936 } 937 941 public String getAbsolutePath() { 942 return this.getCurpwd(); 943 } 944 950 public String getRelativePath() throws BuildException, IOException { 951 return ""; 952 } 953 } 954 } 955 964 private boolean isFunctioningAsDirectory(FTPClient ftp, String dir, FTPFile file) { 965 boolean result = false; 966 String currentWorkingDir = null; 967 if (file.isDirectory()) { 968 return true; 969 } else if (file.isFile()) { 970 return false; 971 } 972 try { 973 currentWorkingDir = ftp.printWorkingDirectory(); 974 } catch (IOException ioe) { 975 getProject().log("could not find current working directory " + dir 976 + " while checking a symlink", 977 Project.MSG_DEBUG); 978 } 979 if (currentWorkingDir != null) { 980 try { 981 result = ftp.changeWorkingDirectory(file.getLink()); 982 } catch (IOException ioe) { 983 getProject().log("could not cd to " + file.getLink() + " while checking a symlink", 984 Project.MSG_DEBUG); 985 } 986 if (result) { 987 boolean comeback = false; 988 try { 989 comeback = ftp.changeWorkingDirectory(currentWorkingDir); 990 } catch (IOException ioe) { 991 getProject().log("could not cd back to " + dir + " while checking a symlink", 992 Project.MSG_ERR); 993 } finally { 994 if (!comeback) { 995 throw new BuildException("could not cd back to " + dir 996 + " while checking a symlink"); 997 } 998 } 999 } 1000 } 1001 return result; 1002 } 1003 1012 private boolean isFunctioningAsFile(FTPClient ftp, String dir, FTPFile file) { 1013 if (file.isDirectory()) { 1014 return false; 1015 } else if (file.isFile()) { 1016 return true; 1017 } 1018 return !isFunctioningAsDirectory(ftp, dir, file); 1019 } 1020 1027 public void setRemotedir(String dir) { 1028 this.remotedir = dir; 1029 } 1030 1031 1032 1037 public void setServer(String server) { 1038 this.server = server; 1039 } 1040 1041 1042 1047 public void setPort(int port) { 1048 this.port = port; 1049 } 1050 1051 1052 1057 public void setUserid(String userid) { 1058 this.userid = userid; 1059 } 1060 1061 1062 1067 public void setPassword(String password) { 1068 this.password = password; 1069 } 1070 1071 1077 public void setAccount(String pAccount) { 1078 this.account = pAccount; 1079 } 1080 1081 1082 1087 public void setBinary(boolean binary) { 1088 this.binary = binary; 1089 } 1090 1091 1092 1099 public void setPassive(boolean passive) { 1100 this.passive = passive; 1101 } 1102 1103 1104 1110 public void setVerbose(boolean verbose) { 1111 this.verbose = verbose; 1112 } 1113 1114 1115 1123 public void setNewer(boolean newer) { 1124 this.newerOnly = newer; 1125 } 1126 1127 1137 public void setTimeDiffMillis(long timeDiffMillis) { 1138 this.timeDiffMillis = timeDiffMillis; 1139 } 1140 1141 1152 public void setTimeDiffAuto(boolean timeDiffAuto) { 1153 this.timeDiffAuto = timeDiffAuto; 1154 } 1155 1156 1161 public void setPreserveLastModified(boolean preserveLastModified) { 1162 this.preserveLastModified = preserveLastModified; 1163 } 1164 1165 1166 1172 public void setDepends(boolean depends) { 1173 this.newerOnly = depends; 1174 } 1175 1176 1177 1185 public void setSeparator(String separator) { 1186 remoteFileSep = separator; 1187 } 1188 1189 1190 1197 public void setChmod(String theMode) { 1198 this.chmod = theMode; 1199 } 1200 1201 1202 1207 public void setUmask(String theUmask) { 1208 this.umask = theUmask; 1209 } 1210 1211 1212 1218 public void addFileset(FileSet set) { 1219 filesets.addElement(set); 1220 } 1221 1222 1223 1238 public void setAction(String action) throws BuildException { 1239 log("DEPRECATED - The setAction(String) method has been deprecated." 1240 + " Use setAction(FTP.Action) instead."); 1241 1242 Action a = new Action(); 1243 1244 a.setValue(action); 1245 this.action = a.getAction(); 1246 } 1247 1248 1249 1257 public void setAction(Action action) throws BuildException { 1258 this.action = action.getAction(); 1259 } 1260 1261 1262 1268 public void setListing(File listing) { 1269 this.listing = listing; 1270 } 1271 1272 1273 1280 public void setSkipFailedTransfers(boolean skipFailedTransfers) { 1281 this.skipFailedTransfers = skipFailedTransfers; 1282 } 1283 1284 1285 1292 public void setIgnoreNoncriticalErrors(boolean ignoreNoncriticalErrors) { 1293 this.ignoreNoncriticalErrors = ignoreNoncriticalErrors; 1294 } 1295 1296 private void configurationHasBeenSet() { 1297 this.isConfigurationSet = true; 1298 } 1299 1300 1308 public void setSystemTypeKey(FTPSystemType systemKey) { 1309 if (systemKey != null && !systemKey.getValue().equals("")) { 1310 this.systemTypeKey = systemKey; 1311 configurationHasBeenSet(); 1312 } 1313 } 1314 1315 1321 public void setDefaultDateFormatConfig(String defaultDateFormat) { 1322 if (defaultDateFormat != null && !defaultDateFormat.equals("")) { 1323 this.defaultDateFormatConfig = defaultDateFormat; 1324 configurationHasBeenSet(); 1325 } 1326 } 1327 1328 1334 public void setRecentDateFormatConfig(String recentDateFormat) { 1335 if (recentDateFormat != null && !recentDateFormat.equals("")) { 1336 this.recentDateFormatConfig = recentDateFormat; 1337 configurationHasBeenSet(); 1338 } 1339 } 1340 1341 1347 public void setServerLanguageCodeConfig(LanguageCode serverLanguageCode) { 1348 if (serverLanguageCode != null && !serverLanguageCode.equals("")) { 1349 this.serverLanguageCodeConfig = serverLanguageCode; 1350 configurationHasBeenSet(); 1351 } 1352 } 1353 1354 1360 public void setServerTimeZoneConfig(String serverTimeZoneId) { 1361 if (serverTimeZoneId != null && !serverTimeZoneId.equals("")) { 1362 this.serverTimeZoneConfig = serverTimeZoneId; 1363 configurationHasBeenSet(); 1364 } 1365 } 1366 1367 1374 public void setShortMonthNamesConfig(String shortMonthNames) { 1375 if (shortMonthNames != null && !shortMonthNames.equals("")) { 1376 this.shortMonthNamesConfig = shortMonthNames; 1377 configurationHasBeenSet(); 1378 } 1379 } 1380 1381 1382 1383 1391 public void setRetriesAllowed(String retriesAllowed) { 1392 if ("FOREVER".equalsIgnoreCase(retriesAllowed)) { 1393 this.retriesAllowed = Retryable.RETRY_FOREVER; 1394 } else { 1395 try { 1396 int retries = Integer.parseInt(retriesAllowed); 1397 if (retries < Retryable.RETRY_FOREVER) { 1398 throw new BuildException( 1399 "Invalid value for retriesAllowed attribute: " 1400 + retriesAllowed); 1401 1402 } 1403 this.retriesAllowed = retries; 1404 } catch (NumberFormatException px) { 1405 throw new BuildException( 1406 "Invalid value for retriesAllowed attribute: " 1407 + retriesAllowed); 1408 1409 } 1410 1411 } 1412 } 1413 1416 String getSystemTypeKey() { 1417 return systemTypeKey.getValue(); 1418 } 1419 1422 String getDefaultDateFormatConfig() { 1423 return defaultDateFormatConfig; 1424 } 1425 1428 String getRecentDateFormatConfig() { 1429 return recentDateFormatConfig; 1430 } 1431 1434 String getServerLanguageCodeConfig() { 1435 return serverLanguageCodeConfig.getValue(); 1436 } 1437 1440 String getServerTimeZoneConfig() { 1441 return serverTimeZoneConfig; 1442 } 1443 1446 String getShortMonthNamesConfig() { 1447 return shortMonthNamesConfig; 1448 } 1449 1452 Granularity getTimestampGranularity() { 1453 return timestampGranularity; 1454 } 1455 1459 public void setTimestampGranularity(Granularity timestampGranularity) { 1460 if (null == timestampGranularity || "".equals(timestampGranularity)) { 1461 return; 1462 } 1463 this.timestampGranularity = timestampGranularity; 1464 } 1465 1471 public void setSiteCommand(String siteCommand) { 1472 this.siteCommand = siteCommand; 1473 } 1474 1480 public void setInitialSiteCommand(String initialCommand) { 1481 this.initialSiteCommand = initialCommand; 1482 } 1483 1488 protected void checkAttributes() throws BuildException { 1489 if (server == null) { 1490 throw new BuildException("server attribute must be set!"); 1491 } 1492 if (userid == null) { 1493 throw new BuildException("userid attribute must be set!"); 1494 } 1495 if (password == null) { 1496 throw new BuildException("password attribute must be set!"); 1497 } 1498 1499 if ((action == LIST_FILES) && (listing == null)) { 1500 throw new BuildException("listing attribute must be set for list " 1501 + "action!"); 1502 } 1503 1504 if (action == MK_DIR && remotedir == null) { 1505 throw new BuildException("remotedir attribute must be set for " 1506 + "mkdir action!"); 1507 } 1508 1509 if (action == CHMOD && chmod == null) { 1510 throw new BuildException("chmod attribute must be set for chmod " 1511 + "action!"); 1512 } 1513 if (action == SITE_CMD && siteCommand == null) { 1514 throw new BuildException("sitecommand attribute must be set for site " 1515 + "action!"); 1516 } 1517 1518 1519 if (this.isConfigurationSet) { 1520 try { 1521 Class.forName("org.apache.commons.net.ftp.FTPClientConfig"); 1522 } catch (ClassNotFoundException e) { 1523 throw new BuildException( 1524 "commons-net.jar >= 1.4.0 is required for at least one" 1525 + " of the attributes specified."); 1526 } 1527 } 1528 } 1529 1530 1538 protected void executeRetryable(RetryHandler h, Retryable r, String descr) 1539 throws IOException { 1540 h.execute(r, descr); 1541 } 1542 1543 1544 1556 protected int transferFiles(final FTPClient ftp, FileSet fs) 1557 throws IOException , BuildException { 1558 DirectoryScanner ds; 1559 if (action == SEND_FILES) { 1560 ds = fs.getDirectoryScanner(getProject()); 1561 } else { 1562 if (fs.getSelectors(getProject()).length != 0) { 1564 getProject().log("selectors are not supported in remote filesets", 1565 Project.MSG_WARN); 1566 } 1567 ds = new FTPDirectoryScanner(ftp); 1568 fs.setupDirectoryScanner(ds, getProject()); 1569 ds.setFollowSymlinks(fs.isFollowSymlinks()); 1570 ds.scan(); 1571 } 1572 1573 String [] dsfiles = null; 1574 if (action == RM_DIR) { 1575 dsfiles = ds.getIncludedDirectories(); 1576 } else { 1577 dsfiles = ds.getIncludedFiles(); 1578 } 1579 String dir = null; 1580 1581 if ((ds.getBasedir() == null) 1582 && ((action == SEND_FILES) || (action == GET_FILES))) { 1583 throw new BuildException("the dir attribute must be set for send " 1584 + "and get actions"); 1585 } else { 1586 if ((action == SEND_FILES) || (action == GET_FILES)) { 1587 dir = ds.getBasedir().getAbsolutePath(); 1588 } 1589 } 1590 1591 BufferedWriter bw = null; 1593 1594 try { 1595 if (action == LIST_FILES) { 1596 File pd = listing.getParentFile(); 1597 1598 if (!pd.exists()) { 1599 pd.mkdirs(); 1600 } 1601 bw = new BufferedWriter (new FileWriter (listing)); 1602 } 1603 RetryHandler h = new RetryHandler(this.retriesAllowed, this); 1604 if (action == RM_DIR) { 1605 for (int i = dsfiles.length - 1; i >= 0; i--) { 1608 final String dsfile = dsfiles[i]; 1609 executeRetryable(h, new Retryable() { 1610 public void execute() throws IOException { 1611 rmDir(ftp, dsfile); 1612 } 1613 }, dsfile); 1614 } 1615 } else { 1616 final BufferedWriter fbw = bw; 1617 final String fdir = dir; 1618 if (this.newerOnly) { 1619 this.granularityMillis = 1620 this.timestampGranularity.getMilliseconds(action); 1621 } 1622 for (int i = 0; i < dsfiles.length; i++) { 1623 final String dsfile = dsfiles[i]; 1624 executeRetryable(h, new Retryable() { 1625 public void execute() throws IOException { 1626 switch (action) { 1627 case SEND_FILES: 1628 sendFile(ftp, fdir, dsfile); 1629 break; 1630 case GET_FILES: 1631 getFile(ftp, fdir, dsfile); 1632 break; 1633 case DEL_FILES: 1634 delFile(ftp, dsfile); 1635 break; 1636 case LIST_FILES: 1637 listFile(ftp, fbw, dsfile); 1638 break; 1639 case CHMOD: 1640 doSiteCommand(ftp, "chmod " + chmod 1641 + " " + resolveFile(dsfile)); 1642 transferred++; 1643 break; 1644 default: 1645 throw new BuildException("unknown ftp action " + action); 1646 } 1647 } 1648 }, dsfile); 1649 } 1650 } 1651 } finally { 1652 if (bw != null) { 1653 bw.close(); 1654 } 1655 } 1656 1657 return dsfiles.length; 1658 } 1659 1660 1661 1670 protected void transferFiles(FTPClient ftp) 1671 throws IOException , BuildException { 1672 transferred = 0; 1673 skipped = 0; 1674 1675 if (filesets.size() == 0) { 1676 throw new BuildException("at least one fileset must be specified."); 1677 } else { 1678 for (int i = 0; i < filesets.size(); i++) { 1680 FileSet fs = (FileSet) filesets.elementAt(i); 1681 1682 if (fs != null) { 1683 transferFiles(ftp, fs); 1684 } 1685 } 1686 } 1687 1688 log(transferred + " " + ACTION_TARGET_STRS[action] + " " 1689 + COMPLETED_ACTION_STRS[action]); 1690 if (skipped != 0) { 1691 log(skipped + " " + ACTION_TARGET_STRS[action] 1692 + " were not successfully " + COMPLETED_ACTION_STRS[action]); 1693 } 1694 } 1695 1696 1697 1708 protected String resolveFile(String file) { 1709 return file.replace(System.getProperty("file.separator").charAt(0), 1710 remoteFileSep.charAt(0)); 1711 } 1712 1713 1714 1726 protected void createParents(FTPClient ftp, String filename) 1727 throws IOException , BuildException { 1728 1729 File dir = new File (filename); 1730 if (dirCache.contains(dir)) { 1731 return; 1732 } 1733 1734 1735 Vector parents = new Vector (); 1736 String dirname; 1737 1738 while ((dirname = dir.getParent()) != null) { 1739 File checkDir = new File (dirname); 1740 if (dirCache.contains(checkDir)) { 1741 break; 1742 } 1743 dir = checkDir; 1744 parents.addElement(dir); 1745 } 1746 1747 int i = parents.size() - 1; 1749 1750 if (i >= 0) { 1751 String cwd = ftp.printWorkingDirectory(); 1752 String parent = dir.getParent(); 1753 if (parent != null) { 1754 if (!ftp.changeWorkingDirectory(resolveFile(parent))) { 1755 throw new BuildException("could not change to " 1756 + "directory: " + ftp.getReplyString()); 1757 } 1758 } 1759 1760 while (i >= 0) { 1761 dir = (File ) parents.elementAt(i--); 1762 if (!ftp.changeWorkingDirectory(dir.getName())) { 1764 log("creating remote directory " 1766 + resolveFile(dir.getPath()), Project.MSG_VERBOSE); 1767 if (!ftp.makeDirectory(dir.getName())) { 1768 handleMkDirFailure(ftp); 1769 } 1770 if (!ftp.changeWorkingDirectory(dir.getName())) { 1771 throw new BuildException("could not change to " 1772 + "directory: " + ftp.getReplyString()); 1773 } 1774 } 1775 dirCache.addElement(dir); 1776 } 1777 ftp.changeWorkingDirectory(cwd); 1778 } 1779 } 1780 1786 private long getTimeDiff(FTPClient ftp) { 1787 long returnValue = 0; 1788 File tempFile = findFileName(ftp); 1789 try { 1790 FILE_UTILS.createNewFile(tempFile); 1792 long localTimeStamp = tempFile.lastModified(); 1793 BufferedInputStream instream = new BufferedInputStream (new FileInputStream (tempFile)); 1794 ftp.storeFile(tempFile.getName(), instream); 1795 instream.close(); 1796 boolean success = FTPReply.isPositiveCompletion(ftp.getReplyCode()); 1797 if (success) { 1798 FTPFile [] ftpFiles = ftp.listFiles(tempFile.getName()); 1799 if (ftpFiles.length == 1) { 1800 long remoteTimeStamp = ftpFiles[0].getTimestamp().getTime().getTime(); 1801 returnValue = localTimeStamp - remoteTimeStamp; 1802 } 1803 ftp.deleteFile(ftpFiles[0].getName()); 1804 } 1805 Delete mydelete = new Delete(); 1808 mydelete.bindToOwner(this); 1809 mydelete.setFile(tempFile.getCanonicalFile()); 1810 mydelete.execute(); 1811 } catch (Exception e) { 1812 throw new BuildException(e, getLocation()); 1813 } 1814 return returnValue; 1815 } 1816 1819 private File findFileName(FTPClient ftp) { 1820 FTPFile [] theFiles = null; 1821 final int maxIterations = 1000; 1822 for (int counter = 1; counter < maxIterations; counter++) { 1823 File localFile = FILE_UTILS.createTempFile("ant" + Integer.toString(counter), ".tmp", 1824 null); 1825 String fileName = localFile.getName(); 1826 boolean found = false; 1827 try { 1828 if (counter == 1) { 1829 theFiles = ftp.listFiles(); 1830 } 1831 for (int counter2 = 0; counter2 < theFiles.length; counter2++) { 1832 if (theFiles[counter2].getName().equals(fileName)) { 1833 found = true; 1834 break; 1835 } 1836 } 1837 } catch (IOException ioe) { 1838 throw new BuildException(ioe, getLocation()); 1839 } 1840 if (!found) { 1841 localFile.deleteOnExit(); 1842 return localFile; 1843 } 1844 } 1845 return null; 1846 } 1847 1848 private static final SimpleDateFormat TIMESTAMP_LOGGING_SDF = 1849 new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); 1850 1851 1862 protected boolean isUpToDate(FTPClient ftp, File localFile, 1863 String remoteFile) 1864 throws IOException , BuildException { 1865 log("checking date for " + remoteFile, Project.MSG_VERBOSE); 1866 1867 FTPFile[] files = ftp.listFiles(remoteFile); 1868 1869 if (files == null || files.length == 0) { 1872 1875 if (action == SEND_FILES) { 1876 log("Could not date test remote file: " + remoteFile 1877 + "assuming out of date.", Project.MSG_VERBOSE); 1878 return false; 1879 } else { 1880 throw new BuildException("could not date test remote file: " 1881 + ftp.getReplyString()); 1882 } 1883 } 1884 1885 long remoteTimestamp = files[0].getTimestamp().getTime().getTime(); 1886 long localTimestamp = localFile.lastModified(); 1887 long adjustedRemoteTimestamp = 1888 remoteTimestamp + this.timeDiffMillis + this.granularityMillis; 1889 1890 StringBuffer msg = new StringBuffer (" [") 1891 .append(TIMESTAMP_LOGGING_SDF.format(new Date (localTimestamp))) 1892 .append("] local"); 1893 log(msg.toString(), Project.MSG_VERBOSE); 1894 1895 msg = new StringBuffer (" [") 1896 .append(TIMESTAMP_LOGGING_SDF.format(new Date (adjustedRemoteTimestamp))) 1897 .append("] remote"); 1898 if (remoteTimestamp != adjustedRemoteTimestamp) { 1899 msg.append(" - (raw: ") 1900 .append(TIMESTAMP_LOGGING_SDF.format(new Date (remoteTimestamp))) 1901 .append(")"); 1902 } 1903 log(msg.toString(), Project.MSG_VERBOSE); 1904 1905 1906 1907 if (this.action == SEND_FILES) { 1908 return adjustedRemoteTimestamp >= localTimestamp; 1909 } else { 1910 return localTimestamp >= adjustedRemoteTimestamp; 1911 } 1912 } 1913 1914 1915 1922 protected void doSiteCommand(FTPClient ftp, String theCMD) 1923 throws IOException , BuildException { 1924 boolean rc; 1925 String [] myReply = null; 1926 1927 log("Doing Site Command: " + theCMD, Project.MSG_VERBOSE); 1928 1929 rc = ftp.sendSiteCommand(theCMD); 1930 1931 if (!rc) { 1932 log("Failed to issue Site Command: " + theCMD, Project.MSG_WARN); 1933 } else { 1934 1935 myReply = ftp.getReplyStrings(); 1936 1937 for (int x = 0; x < myReply.length; x++) { 1938 if (myReply[x].indexOf("200") == -1) { 1939 log(myReply[x], Project.MSG_WARN); 1940 } 1941 } 1942 } 1943 } 1944 1945 1946 1962 protected void sendFile(FTPClient ftp, String dir, String filename) 1963 throws IOException , BuildException { 1964 InputStream instream = null; 1965 1966 try { 1967 File file = getProject().resolveFile(new File (dir, filename).getPath()); 1969 1970 if (newerOnly && isUpToDate(ftp, file, resolveFile(filename))) { 1971 return; 1972 } 1973 1974 if (verbose) { 1975 log("transferring " + file.getAbsolutePath()); 1976 } 1977 1978 instream = new BufferedInputStream (new FileInputStream (file)); 1979 1980 createParents(ftp, filename); 1981 1982 ftp.storeFile(resolveFile(filename), instream); 1983 1984 boolean success = FTPReply.isPositiveCompletion(ftp.getReplyCode()); 1985 1986 if (!success) { 1987 String s = "could not put file: " + ftp.getReplyString(); 1988 1989 if (skipFailedTransfers) { 1990 log(s, Project.MSG_WARN); 1991 skipped++; 1992 } else { 1993 throw new BuildException(s); 1994 } 1995 1996 } else { 1997 if (chmod != null) { 1999 doSiteCommand(ftp, "chmod " + chmod + " " + resolveFile(filename)); 2000 } 2001 log("File " + file.getAbsolutePath() + " copied to " + server, 2002 Project.MSG_VERBOSE); 2003 transferred++; 2004 } 2005 } finally { 2006 if (instream != null) { 2007 try { 2008 instream.close(); 2009 } catch (IOException ex) { 2010 } 2012 } 2013 } 2014 } 2015 2016 2017 2025 protected void delFile(FTPClient ftp, String filename) 2026 throws IOException , BuildException { 2027 if (verbose) { 2028 log("deleting " + filename); 2029 } 2030 2031 if (!ftp.deleteFile(resolveFile(filename))) { 2032 String s = "could not delete file: " + ftp.getReplyString(); 2033 2034 if (skipFailedTransfers) { 2035 log(s, Project.MSG_WARN); 2036 skipped++; 2037 } else { 2038 throw new BuildException(s); 2039 } 2040 } else { 2041 log("File " + filename + " deleted from " + server, 2042 Project.MSG_VERBOSE); 2043 transferred++; 2044 } 2045 } 2046 2047 2055 protected void rmDir(FTPClient ftp, String dirname) 2056 throws IOException , BuildException { 2057 if (verbose) { 2058 log("removing " + dirname); 2059 } 2060 2061 if (!ftp.removeDirectory(resolveFile(dirname))) { 2062 String s = "could not remove directory: " + ftp.getReplyString(); 2063 2064 if (skipFailedTransfers) { 2065 log(s, Project.MSG_WARN); 2066 skipped++; 2067 } else { 2068 throw new BuildException(s); 2069 } 2070 } else { 2071 log("Directory " + dirname + " removed from " + server, 2072 Project.MSG_VERBOSE); 2073 transferred++; 2074 } 2075 } 2076 2077 2078 2094 protected void getFile(FTPClient ftp, String dir, String filename) 2095 throws IOException , BuildException { 2096 OutputStream outstream = null; 2097 try { 2098 File file = getProject().resolveFile(new File (dir, filename).getPath()); 2099 2100 if (newerOnly && isUpToDate(ftp, file, resolveFile(filename))) { 2101 return; 2102 } 2103 2104 if (verbose) { 2105 log("transferring " + filename + " to " 2106 + file.getAbsolutePath()); 2107 } 2108 2109 File pdir = file.getParentFile(); 2110 2111 if (!pdir.exists()) { 2112 pdir.mkdirs(); 2113 } 2114 outstream = new BufferedOutputStream (new FileOutputStream (file)); 2115 ftp.retrieveFile(resolveFile(filename), outstream); 2116 2117 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2118 String s = "could not get file: " + ftp.getReplyString(); 2119 2120 if (skipFailedTransfers) { 2121 log(s, Project.MSG_WARN); 2122 skipped++; 2123 } else { 2124 throw new BuildException(s); 2125 } 2126 2127 } else { 2128 log("File " + file.getAbsolutePath() + " copied from " 2129 + server, Project.MSG_VERBOSE); 2130 transferred++; 2131 if (preserveLastModified) { 2132 outstream.close(); 2133 outstream = null; 2134 FTPFile[] remote = ftp.listFiles(resolveFile(filename)); 2135 if (remote.length > 0) { 2136 FILE_UTILS.setFileLastModified(file, 2137 remote[0].getTimestamp() 2138 .getTime().getTime()); 2139 } 2140 } 2141 } 2142 } finally { 2143 if (outstream != null) { 2144 try { 2145 outstream.close(); 2146 } catch (IOException ex) { 2147 } 2149 } 2150 } 2151 } 2152 2153 2154 2168 protected void listFile(FTPClient ftp, BufferedWriter bw, String filename) 2169 throws IOException , BuildException { 2170 if (verbose) { 2171 log("listing " + filename); 2172 } 2173 FTPFile[] ftpfiles = ftp.listFiles(resolveFile(filename)); 2174 2175 if (ftpfiles != null && ftpfiles.length > 0) { 2176 bw.write(ftpfiles[0].toString()); 2177 bw.newLine(); 2178 transferred++; 2179 } 2180 } 2181 2182 2183 2195 protected void makeRemoteDir(FTPClient ftp, String dir) 2196 throws IOException , BuildException { 2197 String workingDirectory = ftp.printWorkingDirectory(); 2198 if (verbose) { 2199 log("Creating directory: " + dir); 2200 } 2201 if (dir.indexOf("/") == 0) { 2202 ftp.changeWorkingDirectory("/"); 2203 } 2204 String subdir = new String (); 2205 StringTokenizer st = new StringTokenizer (dir, "/"); 2206 while (st.hasMoreTokens()) { 2207 subdir = st.nextToken(); 2208 log("Checking " + subdir, Project.MSG_DEBUG); 2209 if (!ftp.changeWorkingDirectory(subdir)) { 2210 if (!ftp.makeDirectory(subdir)) { 2211 int rc = ftp.getReplyCode(); 2215 if (!(ignoreNoncriticalErrors 2216 && (rc == FTPReply.CODE_550 || rc == FTPReply.CODE_553 2217 || rc == CODE_521))) { 2218 throw new BuildException("could not create directory: " 2219 + ftp.getReplyString()); 2220 } 2221 if (verbose) { 2222 log("Directory already exists"); 2223 } 2224 } else { 2225 if (verbose) { 2226 log("Directory created OK"); 2227 } 2228 ftp.changeWorkingDirectory(subdir); 2229 } 2230 } 2231 } 2232 if (workingDirectory != null) { 2233 ftp.changeWorkingDirectory(workingDirectory); 2234 } 2235 } 2236 2237 2243 private void handleMkDirFailure(FTPClient ftp) 2244 throws BuildException { 2245 int rc = ftp.getReplyCode(); 2246 if (!(ignoreNoncriticalErrors 2247 && (rc == FTPReply.CODE_550 || rc == FTPReply.CODE_553 || rc == CODE_521))) { 2248 throw new BuildException("could not create directory: " 2249 + ftp.getReplyString()); 2250 } 2251 } 2252 2253 2259 public void execute() throws BuildException { 2260 checkAttributes(); 2261 2262 FTPClient ftp = null; 2263 2264 try { 2265 log("Opening FTP connection to " + server, Project.MSG_VERBOSE); 2266 2267 ftp = new FTPClient(); 2268 if (this.isConfigurationSet) { 2269 ftp = FTPConfigurator.configure(ftp, this); 2270 } 2271 2272 ftp.connect(server, port); 2273 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2274 throw new BuildException("FTP connection failed: " 2275 + ftp.getReplyString()); 2276 } 2277 2278 log("connected", Project.MSG_VERBOSE); 2279 log("logging in to FTP server", Project.MSG_VERBOSE); 2280 2281 if ((this.account != null && !ftp.login(userid, password, account)) 2282 || (this.account == null && !ftp.login(userid, password))) { 2283 throw new BuildException("Could not login to FTP server"); 2284 } 2285 2286 log("login succeeded", Project.MSG_VERBOSE); 2287 2288 if (binary) { 2289 ftp.setFileType(org.apache.commons.net.ftp.FTP.IMAGE_FILE_TYPE); 2290 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2291 throw new BuildException("could not set transfer type: " 2292 + ftp.getReplyString()); 2293 } 2294 } else { 2295 ftp.setFileType(org.apache.commons.net.ftp.FTP.ASCII_FILE_TYPE); 2296 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2297 throw new BuildException("could not set transfer type: " 2298 + ftp.getReplyString()); 2299 } 2300 } 2301 2302 if (passive) { 2303 log("entering passive mode", Project.MSG_VERBOSE); 2304 ftp.enterLocalPassiveMode(); 2305 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2306 throw new BuildException("could not enter into passive " 2307 + "mode: " + ftp.getReplyString()); 2308 } 2309 } 2310 2311 if (this.initialSiteCommand != null) { 2316 RetryHandler h = new RetryHandler(this.retriesAllowed, this); 2317 final FTPClient lftp = ftp; 2318 executeRetryable(h, new Retryable() { 2319 public void execute() throws IOException { 2320 doSiteCommand(lftp, FTP.this.initialSiteCommand); 2321 } 2322 }, "initial site command: " + this.initialSiteCommand); 2323 } 2324 2325 2326 2329 if (umask != null) { 2330 RetryHandler h = new RetryHandler(this.retriesAllowed, this); 2331 final FTPClient lftp = ftp; 2332 executeRetryable(h, new Retryable() { 2333 public void execute() throws IOException { 2334 doSiteCommand(lftp, "umask " + umask); 2335 } 2336 }, "umask " + umask); 2337 } 2338 2339 2342 if (action == MK_DIR) { 2343 RetryHandler h = new RetryHandler(this.retriesAllowed, this); 2344 final FTPClient lftp = ftp; 2345 executeRetryable(h, new Retryable() { 2346 public void execute() throws IOException { 2347 makeRemoteDir(lftp, remotedir); 2348 } 2349 }, remotedir); 2350 } else if (action == SITE_CMD) { 2351 RetryHandler h = new RetryHandler(this.retriesAllowed, this); 2352 final FTPClient lftp = ftp; 2353 executeRetryable(h, new Retryable() { 2354 public void execute() throws IOException { 2355 doSiteCommand(lftp, FTP.this.siteCommand); 2356 } 2357 }, "Site Command: " + this.siteCommand); 2358 } else { 2359 if (remotedir != null) { 2360 log("changing the remote directory", Project.MSG_VERBOSE); 2361 ftp.changeWorkingDirectory(remotedir); 2362 if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { 2363 throw new BuildException("could not change remote " 2364 + "directory: " + ftp.getReplyString()); 2365 } 2366 } 2367 if (newerOnly && timeDiffAuto) { 2368 timeDiffMillis = getTimeDiff(ftp); 2371 } 2372 log(ACTION_STRS[action] + " " + ACTION_TARGET_STRS[action]); 2373 transferFiles(ftp); 2374 } 2375 2376 } catch (IOException ex) { 2377 throw new BuildException("error during FTP transfer: " + ex, ex); 2378 } finally { 2379 if (ftp != null && ftp.isConnected()) { 2380 try { 2381 log("disconnecting", Project.MSG_VERBOSE); 2382 ftp.logout(); 2383 ftp.disconnect(); 2384 } catch (IOException ex) { 2385 } 2387 } 2388 } 2389 } 2390 2391 2392 2397 public static class Action extends EnumeratedAttribute { 2398 2399 private static final String [] VALID_ACTIONS = { 2400 "send", "put", "recv", "get", "del", "delete", "list", "mkdir", 2401 "chmod", "rmdir", "site" 2402 }; 2403 2404 2405 2410 public String [] getValues() { 2411 return VALID_ACTIONS; 2412 } 2413 2414 2415 2420 public int getAction() { 2421 String actionL = getValue().toLowerCase(Locale.US); 2422 2423 if (actionL.equals("send") || actionL.equals("put")) { 2424 return SEND_FILES; 2425 } else if (actionL.equals("recv") || actionL.equals("get")) { 2426 return GET_FILES; 2427 } else if (actionL.equals("del") || actionL.equals("delete")) { 2428 return DEL_FILES; 2429 } else if (actionL.equals("list")) { 2430 return LIST_FILES; 2431 } else if (actionL.equals("chmod")) { 2432 return CHMOD; 2433 } else if (actionL.equals("mkdir")) { 2434 return MK_DIR; 2435 } else if (actionL.equals("rmdir")) { 2436 return RM_DIR; 2437 } else if (actionL.equals("site")) { 2438 return SITE_CMD; 2439 } 2440 return SEND_FILES; 2441 } 2442 } 2443 2458 public static class Granularity extends EnumeratedAttribute { 2459 2460 private static final String [] VALID_GRANULARITIES = { 2461 "", "MINUTE", "NONE" 2462 }; 2463 2464 2468 public String [] getValues() { 2469 return VALID_GRANULARITIES; 2471 } 2472 2480 public long getMilliseconds(int action) { 2481 String granularityU = getValue().toUpperCase(Locale.US); 2482 2483 if ("".equals(granularityU)) { 2484 if (action == SEND_FILES) { 2485 return GRANULARITY_MINUTE; 2486 } 2487 } else if ("MINUTE".equals(granularityU)) { 2488 return GRANULARITY_MINUTE; 2489 } 2490 return 0L; 2491 } 2492 static final Granularity getDefault() { 2493 Granularity g = new Granularity(); 2494 g.setValue(""); 2495 return g; 2496 } 2497 2498 } 2499 2503 public static class FTPSystemType extends EnumeratedAttribute { 2504 2505 private static final String [] VALID_SYSTEM_TYPES = { 2506 "", "UNIX", "VMS", "WINDOWS", "OS/2", "OS/400", 2507 "MVS" 2508 }; 2509 2510 2511 2515 public String [] getValues() { 2516 return VALID_SYSTEM_TYPES; 2517 } 2518 2519 static final FTPSystemType getDefault() { 2520 FTPSystemType ftpst = new FTPSystemType(); 2521 ftpst.setValue(""); 2522 return ftpst; 2523 } 2524 } 2525 2528 public static class LanguageCode extends EnumeratedAttribute { 2529 2530 2531 private static final String [] VALID_LANGUAGE_CODES = 2532 getValidLanguageCodes(); 2533 2534 private static String [] getValidLanguageCodes() { 2535 Collection c = FTPClientConfig.getSupportedLanguageCodes(); 2536 String [] ret = new String [c.size() + 1]; 2537 int i = 0; 2538 ret[i++] = ""; 2539 for (Iterator it = c.iterator(); it.hasNext(); i++) { 2540 ret[i] = (String ) it.next(); 2541 } 2542 return ret; 2543 } 2544 2545 2546 2550 public String [] getValues() { 2551 return VALID_LANGUAGE_CODES; 2552 } 2553 2554 static final LanguageCode getDefault() { 2555 LanguageCode lc = new LanguageCode(); 2556 lc.setValue(""); 2557 return lc; 2558 } 2559 } 2560 2561} 2562 | Popular Tags |