package railo.commons.io.res.type.ftp; import java.io.IOException; import java.util.Map; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import railo.commons.collection.MapFactory; import railo.commons.lang.SerializableObject; import railo.commons.lang.StringUtil; public final class FTPResourceClient extends FTPClient { private String workingDirectory=null; private final FTPConnectionData ftpConnectionData; private long lastAccess; private final Object token=new SerializableObject(); private final Map<String,FTPFileWrap> files=MapFactory.<String,FTPFileWrap>getConcurrentMap(); private final int cacheTimeout; public FTPResourceClient(FTPConnectionData ftpConnectionData,int cacheTimeout) { this.ftpConnectionData=ftpConnectionData; this.cacheTimeout=cacheTimeout; } /** * @return the ftpConnectionData */ public FTPConnectionData getFtpConnectionData() { return ftpConnectionData; } public void touch() { this.lastAccess=System.currentTimeMillis(); } /** * @return the lastAccess */ public long getLastAccess() { return lastAccess; } public Object getToken() { return token; } @Override public boolean changeWorkingDirectory(String pathname) throws IOException { if(StringUtil.endsWith(pathname,'/') && pathname.length()!=1)pathname=pathname.substring(0,pathname.length()-1); if(pathname.equals(workingDirectory)) return true; workingDirectory=pathname; return super.changeWorkingDirectory(pathname); } public String id() { return ftpConnectionData.key(); } @Override public boolean equals(Object obj) { return ((FTPResourceClient)obj).id().equals(id()); } public FTPFile getFTPFile(FTPResource res) throws IOException { String path=res.getInnerPath(); FTPFileWrap fw = files.get(path); if(fw==null) { return createFTPFile(res); } if(fw.time+cacheTimeout<System.currentTimeMillis()) { files.remove(path); return createFTPFile(res); } return fw.file; } public void registerFTPFile(FTPResource res,FTPFile file) { files.put(res.getInnerPath(),new FTPFileWrap(file)); } public void unregisterFTPFile(FTPResource res) { files.remove(res.getInnerPath()); } private FTPFile createFTPFile(FTPResource res) throws IOException { FTPFile[] children=null; boolean isRoot=res.isRoot(); String path=isRoot?res.getInnerPath():res.getInnerParent(); synchronized(getToken()){ changeWorkingDirectory(path); children = listFiles(); } if(children.length>0) { for(int i=0;i<children.length;i++) { if(isRoot){ if(children[i].getName().equals(".")) { registerFTPFile(res, children[i]); return children[i]; } } else{ if(children[i].getName().equals(res.getName())) { registerFTPFile(res, children[i]); return children[i]; } } } } return null; } @Override public boolean deleteFile(String pathname) throws IOException { files.remove(pathname); return super.deleteFile(pathname); } class FTPFileWrap { private FTPFile file; private long time; public FTPFileWrap(FTPFile file) { this.file=file; this.time=System.currentTimeMillis(); } } }