package uc.files.transfer; import java.io.File; import java.io.IOException; import uc.DCClient; import uc.IUser; import uc.crypto.HashValue; import uc.crypto.InterleaveHashes; import uc.files.downloadqueue.AbstractDownloadQueueEntry; import uc.files.downloadqueue.FileDQE; import uc.files.filelist.FileListFile; import uc.files.transfer.AbstractReadableFileInterval.FileReadInterval; import uc.files.transfer.AbstractReadableFileInterval.MemoryReadInterval; import uc.protocols.Compression; import uc.protocols.TransferType; import uc.protocols.client.ClientProtocol; /** * CommandPattern for FileTransfer information.. * * @author Quicksilver * */ public class FileTransferInformation { // private static Logger logger = LoggerFactory.make(Level.DEBUG); private final DCClient dcc; /** * transfer will happen with this user */ private IUser other; /** * what compression that is to be used */ private Compression compression = Compression.NONE; /** * start position in the file * */ private long startposition; private long length; /** * if its a file or TTHL transfer * this is the root hash otherwise null */ private HashValue hashValue; /** * what type of transfer this is */ private volatile TransferType type; private volatile String nameOfTransferred; /** * for a download the DownloadQueueEntry * is needed to gather information on target path and likewise */ private AbstractDownloadQueueEntry dqe; /** * true if upload * false for download * null if not yet set. */ private volatile Boolean download; private AbstractFileInterval fileInterval; /** * for partial Filelist * null means whole filelist * if not recursive only single directory is sent.. */ private String fileListSubPath = null; private volatile boolean bz2Compressed = false; private volatile boolean partialList = false; private boolean recursive = true; public FileTransferInformation(DCClient dcc) { super(); this.dcc = dcc; } /** * checks if the gained information is valid and can be used * to create a transfer * @return */ public boolean isValid() { if (isUpload() && isValidForSND() && fileInterval != null) { return true; } if (isValidForGet() && fileInterval != null) { return true; } return false; } public boolean isValidForGet() { if (type == null || !isDownload() || other == null) { return false; } switch(type) { case FILE: if (nameOfTransferred == null) { //files need a name return false; } //fall through! case TTHL: if (hashValue == null) { return false; } case FILELIST: return true; //no special requirements.. } throw new IllegalStateException(); } private boolean isValidForSND() { if (type == null || !isUpload() ||other == null) { return false; } switch(type) { case FILE: if (nameOfTransferred == null) { //files need a name return false; } //fall through! case TTHL: if (hashValue == null) { return false; } case FILELIST: return true; //no special requirements.. } throw new IllegalStateException(); } public IUser getOther() { return other; } public void setOther(IUser other) { this.other = other; } public Compression getCompression() { return compression; } public void setCompression(Compression comp) { this.compression = comp; } /** * sets compression for downloading.. what we would prefer.. * @param otherIsLocal */ public void setCompression(boolean otherIsLocal,boolean otherSupportsCompression) { switch(type) { case FILE: setCompression(otherIsLocal||!otherSupportsCompression ? Compression.NONE: Compression.ZLIB_BEST); break; case TTHL: setCompression(Compression.NONE); break; case FILELIST: setCompression(otherSupportsCompression?Compression.ZLIB_FAST:Compression.NONE); break; } } public long getStartposition() { if (getType() == TransferType.FILE) { return startposition; } else { return 0; } } public void setStartposition(long startposition) { this.startposition = startposition; } public long getLength() { return length; } public void setLength(long length) { this.length = length; } public HashValue getHashValue() { return hashValue; } public void setHashValue(HashValue hashValue) { this.hashValue = hashValue; } public TransferType getType() { return type; } public void setType(TransferType type) { this.type = type; } public String getNameOfTransferred() { if (type != null) { switch(type) { case FILE: return nameOfTransferred; case FILELIST: return "FileList"; case TTHL: return "TTHL: "+getHashValue(); } } return nameOfTransferred; } /** * sets the name of the transferred.. * only needed for files.. not for TTHL or Filelist * @param nameOfTransferred */ public void setNameOfTransferred(String nameOfTransferred) { this.nameOfTransferred = nameOfTransferred; } public Boolean getDownload() { return download; } public boolean isUpload() { return download != null && !download; } public boolean isDownload() { return download != null && download; } public void setDownload(Boolean download) { this.download = download; } /** * gets the filepath either source or target .. * for displaying in gui .. * @return Targetpath if download ... sourcepath if upload * null if not applicable */ public File getFile() { File f = null; if (isUpload()) { TransferType t = getType(); if (t == null) { return null; } switch(t) { case FILE: case TTHL: f = dcc.getFilelist().getFile(getHashValue()); } } else if (isDownload()) { f = dqe.getTargetPath(); } return f; } public FileListFile getFileListFile() { if (isUpload() && getHashValue() != null) { return dcc.getFilelist().get(getHashValue()); } return null; } /** * creates a file interval for the upload.. * * @return true if creation was successful */ public boolean setFileInterval() { fileInterval = null; if (isUpload()) { File f = null; switch(getType()) { case FILE: FileListFile flfile = dcc.getFilelist().get(getHashValue()); long startpos = getStartposition(); if (flfile != null && flfile.mayDownload(getOther())) { f = dcc.getFilelist().getFile(flfile); if (f != null && f.canRead()) { if (getLength() == -1) { setLength( f.length() - startpos); } //check if the requested length is not too long.. if (getLength() + startpos > f.length()) { setLength(f.length()- startpos ); } fileInterval = new FileReadInterval(f,getStartposition(),getLength()); setNameOfTransferred(f.getName()); } } else { AbstractDownloadQueueEntry adqe = dcc.getDownloadQueue().get(getHashValue()); if (adqe instanceof FileDQE) { FileDQE fdqe = (FileDQE)adqe; if (getLength() == -1 | getLength() > fdqe.getBytesReadable(startpos)) { setLength(fdqe.getBytesReadable(startpos)); } fileInterval = fdqe.getReadInterval(this); setNameOfTransferred(fdqe.getFileName()); } } break; case FILELIST: byte[] filelist = dcc.getOwnFileList().writeFileList(fileListSubPath, recursive,bz2Compressed); fileInterval = new MemoryReadInterval(filelist); setLength(filelist.length); break; case TTHL: InterleaveHashes interleaves = dcc.getDatabase().getInterleaves(getHashValue(),false); if (interleaves != null) { fileInterval = AbstractReadableFileInterval.create(interleaves); setLength(fileInterval.length()); } break; } } else if (isDownload()) { fileInterval = dqe.getInterval(this); //new WritableFileInterval(dqe,startposition,length); } return fileInterval != null; } /** * create an abstract File transfer from the gathered date. * @return */ public AbstractFileTransfer create(ClientProtocol cp) throws IOException { if (isDownload()) { return new Download(this,cp,(AbstractWritableFileInterval)fileInterval); } else if (isUpload()){ return new Upload(this,cp,(AbstractReadableFileInterval)fileInterval); } throw new IllegalStateException(); } public AbstractDownloadQueueEntry getDqe() { return dqe; } public void setDqe(AbstractDownloadQueueEntry dqe) { this.dqe = dqe; } public void setPartialFileList(String fileListSubPath,boolean recursive) { this.fileListSubPath = fileListSubPath; this.recursive = recursive; } public String getFileListSubPath() { return fileListSubPath; } public boolean isRecursive() { return recursive; } public boolean isBz2Compressed() { return bz2Compressed; } public void setBz2Compressed(boolean bz2Compressed) { this.bz2Compressed = bz2Compressed; } public boolean isPartialList() { return partialList; } public void setPartialList(boolean partialList) { this.partialList = partialList; } @Override public String toString() { return "FileTransferInformation [other=" + other + ", compression=" + compression + ", startposition=" + startposition + ", length=" + length + ", hashValue=" + hashValue + ", type=" + type + ", nameOfTransferred=" + nameOfTransferred + ", dqe=" + dqe + ", download=" + download + ", fileInterval=" + fileInterval + ", fileListSubPath=" + fileListSubPath + ", recursive=" + recursive + "]"; } }