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 @Override 051 public boolean changeWorkingDirectory(String pathname) throws IOException { 052 if(StringUtil.endsWith(pathname,'/') && pathname.length()!=1)pathname=pathname.substring(0,pathname.length()-1); 053 054 if(pathname.equals(workingDirectory)) return true; 055 workingDirectory=pathname; 056 return super.changeWorkingDirectory(pathname); 057 } 058 059 public String id() { 060 return ftpConnectionData.key(); 061 } 062 063 @Override 064 public boolean equals(Object obj) { 065 066 return ((FTPResourceClient)obj).id().equals(id()); 067 } 068 069 public FTPFile getFTPFile(FTPResource res) throws IOException { 070 String path=res.getInnerPath(); 071 FTPFileWrap fw = (FTPFileWrap) files.get(path); 072 073 if(fw==null) { 074 return createFTPFile(res); 075 } 076 if(fw.time+cacheTimeout<System.currentTimeMillis()) { 077 files.remove(path); 078 return createFTPFile(res); 079 } 080 return fw.file; 081 } 082 public void registerFTPFile(FTPResource res,FTPFile file) { 083 files.put(res.getInnerPath(),new FTPFileWrap(file)); 084 } 085 086 public void unregisterFTPFile(FTPResource res) { 087 files.remove(res.getInnerPath()); 088 } 089 090 091 private FTPFile createFTPFile(FTPResource res) throws IOException { 092 FTPFile[] children=null; 093 boolean isRoot=res.isRoot(); 094 String path=isRoot?res.getInnerPath():res.getInnerParent(); 095 096 synchronized(getToken()){ 097 changeWorkingDirectory(path); 098 children = listFiles(); 099 } 100 101 if(children.length>0) { 102 for(int i=0;i<children.length;i++) { 103 if(isRoot){ 104 if(children[i].getName().equals(".")) { 105 registerFTPFile(res, children[i]); 106 return children[i]; 107 } 108 } 109 else{ 110 if(children[i].getName().equals(res.getName())) { 111 registerFTPFile(res, children[i]); 112 return children[i]; 113 } 114 } 115 } 116 } 117 return null; 118 } 119 120 @Override 121 public boolean deleteFile(String pathname) throws IOException { 122 files.remove(pathname); 123 return super.deleteFile(pathname); 124 } 125 126 class FTPFileWrap { 127 128 private FTPFile file; 129 private long time; 130 131 public FTPFileWrap(FTPFile file) { 132 this.file=file; 133 this.time=System.currentTimeMillis(); 134 } 135 136 } 137 }