package com.limegroup.gnutella;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.limegroup.gnutella.altlocs.AlternateLocation;
import com.limegroup.gnutella.altlocs.AlternateLocationCollection;
import com.limegroup.gnutella.downloader.Interval;
import com.limegroup.gnutella.downloader.ManagedDownloader;
import com.limegroup.gnutella.downloader.VerifyingFile;
import com.limegroup.gnutella.http.HTTPHeaderValue;
/**
* This class extends FileDesc and wraps an incomplete File,
* so it can be used for partial file sharing.
*/
public class IncompleteFileDesc extends FileDesc implements HTTPHeaderValue {
/**
* Ranges smalles than this will never be offered to other servents
*/
private final static int MIN_CHUNK_SIZE = 102400; // 100K
/**
* Needed to find out what ranges are available
*/
private VerifyingFile _verifyingFile;
/**
* The name of the file, as returned by IncompleteFileManager
* .getCompletedName(FILE).
*/
private final String _name;
/**
* The size of the file, casted to an <tt>int</tt>.
*/
private final int _size;
/**
* Constructor for the IncompleteFileDesc object.
*/
public IncompleteFileDesc(File file, Set urns, int index,
String completedName, int completedSize,
VerifyingFile vf) {
super(file, urns, index);
_name = completedName;
_size = completedSize;
_verifyingFile = vf;
}
/**
* Returns the completed size of the file on disk, in bytes.
*
* @return the size of the file on disk, in bytes
*/
public long getSize() {
return _size;
}
/**
* Returns the completed name of this file.
*
* @return the name of this file
*/
public String getName() {
return _name;
}
/**
* Opens an input stream to the <tt>File</tt> instance for this
* <tt>FileDesc</tt>.
*
* @return an <tt>InputStream</tt> to the <tt>File</tt> instance
* @throws <tt>FileNotFoundException</tt> if the file represented
* by the <tt>File</tt> instance could not be found
*/
public InputStream createInputStream() throws FileNotFoundException {
// if we don't have any available ranges, we should never
// have entered the download mesh in the first place!!!
if (getFile().length() == 0)
throw new FileNotFoundException("nothing downloaded");
return new BufferedInputStream(new FileInputStream(getFile()));
}
/**
* Adds the alternate location to this FileDesc and also notifies
* the ManagedDownloader of a new location for this.
*/
public boolean add(AlternateLocation al) {
boolean ret = super.add(al);
if (ret) {
ManagedDownloader md = getMyDownloader();
if( md != null )
md.addDownload(al.createRemoteFileDesc((int)getSize()),false);
}
return ret;
}
/**
* Adds a verified location to this FileDesc, not notifying the
* ManagedDownloader of the location.
*/
public boolean addVerified(AlternateLocation al) {
return super.add(al);
}
/**
* Adds the alternate locations to this FileDesc and also notifies the
* ManagedDownloader of new locations for this.
*/
public int addAll(AlternateLocationCollection alc) {
ManagedDownloader md = getMyDownloader();
// if no downloader, just add the collection.
if( md == null )
return super.addAll(alc);
// otherwise, iterate through and individually add them, to make
// sure they get added to the downloader.
int added = 0;
synchronized(alc) {
for(Iterator iter = alc.iterator(); iter.hasNext(); ) {
AlternateLocation al = (AlternateLocation)iter.next();
if( super.add(al) ) {
md.addDownload(al.createRemoteFileDesc((int)getSize()),false);
added++;
}
} //end of for
} //end of synchronized block
return added;
}
private ManagedDownloader getMyDownloader() {
return RouterService.getDownloadManager().getDownloaderForURN(getSHA1Urn());
}
/**
* Returns whether or not we are actively downloading this file.
*/
public boolean isActivelyDownloading() {
ManagedDownloader md = getMyDownloader();
if(md == null)
return false;
switch(md.getState()) {
case Downloader.QUEUED:
case Downloader.WAITING_FOR_RETRY:
case Downloader.ABORTED:
case Downloader.GAVE_UP:
case Downloader.DISK_PROBLEM:
case Downloader.CORRUPT_FILE:
case Downloader.REMOTE_QUEUED:
case Downloader.WAITING_FOR_USER:
return false;
default:
return true;
}
}
// implements HTTPHeaderValue
public String httpStringValue() {
return "";
}
// overrides Object.toString to provide a more useful description
public String toString() {
return ("IncompleteFileDesc:\r\n"+
"name: "+_name+"\r\n"+
"index: "+getIndex()+"\r\n");
}
}