001 package railo.commons.io.res.type.ftp; 002 003 import java.io.IOException; 004 005 import org.apache.commons.net.ftp.FTPClient; 006 import org.apache.commons.net.ftp.FTPFile; 007 008 import railo.commons.collections.HashTable; 009 import railo.commons.lang.SerializableObject; 010 import railo.commons.lang.StringUtil; 011 012 public final class FTPResourceClient extends FTPClient { 013 014 private String workingDirectory=null; 015 016 017 private final FTPConnectionData ftpConnectionData; 018 private long lastAccess; 019 private final Object token=new SerializableObject(); 020 private final HashTable files=new HashTable(); 021 private final int cacheTimeout; 022 023 public FTPResourceClient(FTPConnectionData ftpConnectionData,int cacheTimeout) { 024 this.ftpConnectionData=ftpConnectionData; 025 this.cacheTimeout=cacheTimeout; 026 } 027 028 /** 029 * @return the ftpConnectionData 030 */ 031 public FTPConnectionData getFtpConnectionData() { 032 return ftpConnectionData; 033 } 034 035 public void touch() { 036 this.lastAccess=System.currentTimeMillis(); 037 } 038 039 /** 040 * @return the lastAccess 041 */ 042 public long getLastAccess() { 043 return lastAccess; 044 } 045 046 public Object getToken() { 047 return token; 048 } 049 050 /** 051 * @see org.apache.commons.net.ftp.FTPClient#changeWorkingDirectory(java.lang.String) 052 */ 053 public boolean changeWorkingDirectory(String pathname) throws IOException { 054 if(StringUtil.endsWith(pathname,'/') && pathname.length()!=1)pathname=pathname.substring(0,pathname.length()-1); 055 056 if(pathname.equals(workingDirectory)) return true; 057 workingDirectory=pathname; 058 return super.changeWorkingDirectory(pathname); 059 } 060 061 /** 062 * 063 * @see java.lang.Object#equals(java.lang.Object) 064 */ 065 public String id() { 066 return ftpConnectionData.key(); 067 } 068 069 /** 070 * 071 * @see java.lang.Object#equals(java.lang.Object) 072 */ 073 public boolean equals(Object obj) { 074 075 return ((FTPResourceClient)obj).id().equals(id()); 076 } 077 078 public FTPFile getFTPFile(FTPResource res) throws IOException { 079 String path=res.getInnerPath(); 080 FTPFileWrap fw = (FTPFileWrap) files.get(path); 081 082 if(fw==null) { 083 return createFTPFile(res); 084 } 085 if(fw.time+cacheTimeout<System.currentTimeMillis()) { 086 files.remove(path); 087 return createFTPFile(res); 088 } 089 return fw.file; 090 } 091 public void registerFTPFile(FTPResource res,FTPFile file) { 092 files.put(res.getInnerPath(),new FTPFileWrap(file)); 093 } 094 095 public void unregisterFTPFile(FTPResource res) { 096 files.remove(res.getInnerPath()); 097 } 098 099 100 private FTPFile createFTPFile(FTPResource res) throws IOException { 101 FTPFile[] children=null; 102 boolean isRoot=res.isRoot(); 103 String path=isRoot?res.getInnerPath():res.getInnerParent(); 104 105 synchronized(getToken()){ 106 changeWorkingDirectory(path); 107 children = listFiles(); 108 } 109 110 if(children.length>0) { 111 for(int i=0;i<children.length;i++) { 112 if(isRoot){ 113 if(children[i].getName().equals(".")) { 114 registerFTPFile(res, children[i]); 115 return children[i]; 116 } 117 } 118 else{ 119 if(children[i].getName().equals(res.getName())) { 120 registerFTPFile(res, children[i]); 121 return children[i]; 122 } 123 } 124 } 125 } 126 return null; 127 } 128 129 /** 130 * 131 * @see org.apache.commons.net.ftp.FTPClient#deleteFile(java.lang.String) 132 */ 133 public boolean deleteFile(String pathname) throws IOException { 134 files.remove(pathname); 135 return super.deleteFile(pathname); 136 } 137 138 class FTPFileWrap { 139 140 private FTPFile file; 141 private long time; 142 143 public FTPFileWrap(FTPFile file) { 144 this.file=file; 145 this.time=System.currentTimeMillis(); 146 } 147 148 } 149 }