package org.limewire.libtorrent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.limewire.bittorrent.BTData;
import org.limewire.bittorrent.BTDataImpl;
import org.limewire.bittorrent.TorrentParams;
import org.limewire.bittorrent.bencoding.Token;
import org.limewire.io.IOUtils;
import org.limewire.util.StringUtils;
public class LibTorrentParams implements TorrentParams {
private final File downloadFolder;
private String name = null;;
private String sha1 = null;
private List<URI> trackers = null;
private File fastResumeFile = null;
private File torrentFile = null;
private File torrentDataFile = null;
private Boolean isPrivate = null;
private float seedRatioLimit = -1;
private int timeRatioLimit = -1;
private final AtomicBoolean filled = new AtomicBoolean(false);
/**
* Creates the torrent params using the required field download folder and a
* torrent file. After fill is called, the name and sha1 must be filled in.
*/
public LibTorrentParams(File downloadFolder, File torrentFile) {
this.downloadFolder = downloadFolder;
this.torrentFile = torrentFile;
}
/**
* Creates the torrent params using the required field download folder and
* the fields from a magnet link.
*/
public LibTorrentParams(File downloadFolder, String name, String sha1, List<URI> trackers) {
this.downloadFolder = downloadFolder;
setName(name);
setSha1(sha1);
setTrackers(trackers);
}
/**
* Created the torrent params using the current three required fields of
* name downloadfolder and sha1.
*/
public LibTorrentParams(File downloadFolder, String name, String sha1) {
this.downloadFolder = downloadFolder;
// TODO make the name no longer a required field.
this.name = name;
this.sha1 = sha1;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getSha1() {
return sha1;
}
@Override
public void setSha1(String sha1) {
this.sha1 = sha1;
}
@Override
public List<URI> getTrackers() {
return trackers;
}
@Override
public void setTrackers(List<URI> trackers) {
this.trackers = trackers;
}
@Override
public File getFastResumeFile() {
return fastResumeFile;
}
@Override
public void setFastResumeFile(File fastResumeFile) {
this.fastResumeFile = fastResumeFile;
}
@Override
public File getTorrentFile() {
return torrentFile;
}
@Override
public File getDownloadFolder() {
return downloadFolder;
}
@Override
public void setTorrentFile(File torrentFile) {
filled.set(false);
this.torrentFile = torrentFile;
}
@Override
public File getTorrentDataFile() {
return torrentDataFile;
}
@Override
public void setTorrentDataFile(File torrentDataFile) {
this.torrentDataFile = torrentDataFile;
}
@Override
public Boolean getPrivate() {
return isPrivate;
}
@Override
public void setPrivate(Boolean isPrivate) {
this.isPrivate = isPrivate;
}
@Override
public float getSeedRatioLimit() {
return seedRatioLimit;
}
@Override
public void setSeedRatioLimit(float value) {
this.seedRatioLimit = value;
}
@Override
public int getTimeRatioLimit() {
return timeRatioLimit;
}
@Override
public void setTimeRatioLimit(int value) {
this.timeRatioLimit = value;
}
@Override
public void fill() throws IOException {
if (!filled.getAndSet(true)) {
String sha1 = getSha1();
File torrentFile = getTorrentFile();
String name = getName();
List<URI> trackerURIS = getTrackers();
Boolean isPrivate = getPrivate();
File torrentDataFile = getTorrentDataFile();
File fastResumeFile = getFastResumeFile();
if (torrentFile != null && torrentFile.exists()) {
FileInputStream fis = null;
FileChannel fileChannel = null;
try {
fis = new FileInputStream(torrentFile);
fileChannel = fis.getChannel();
Map metaInfo = (Map) Token.parse(fileChannel);
BTData btData = new BTDataImpl(metaInfo);
if (name == null) {
name = btData.getName();
setName(name);
}
if (trackerURIS == null) {
trackerURIS = btData.getTrackerUris();
setTrackers(trackerURIS);
}
if (sha1 == null) {
sha1 = StringUtils.toHexString(btData.getInfoHash());
setSha1(sha1);
}
if (isPrivate == null) {
isPrivate = btData.isPrivate();
setPrivate(isPrivate);
}
} finally {
IOUtils.close(fileChannel);
IOUtils.close(fis);
}
}
File downloadFolder = getDownloadFolder();
if (name == null || downloadFolder == null || sha1 == null) {
// TODO eventually we need to support this without the name
// parameter
throw new IOException("There was an error initializing the torrent parameters.");
}
setFastResumeFile(fastResumeFile == null ? new File(downloadFolder, name
+ ".fastresume") : fastResumeFile);
setTorrentDataFile(torrentDataFile == null ? new File(downloadFolder, name)
: torrentDataFile);
if (torrentFile != null) {
File possibleTorrentFile = new File(downloadFolder, name + ".torrent");
if (possibleTorrentFile.exists()) {
setTorrentFile(new File(downloadFolder, name + ".torrent"));
}
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("sha1: ").append(sha1).append("\n");
for ( URI tracker : trackers ) {
sb.append("trackerURI: ").append(tracker.toASCIIString()).append("\n");
}
sb.append("name: ").append(name).append("\n");
sb.append("torrentFile: ").append(torrentFile).append("\n");
sb.append("torrentDataFile: ").append(torrentDataFile).append("\n");
sb.append("downloadFolder: ").append(downloadFolder).append("\n");
sb.append("isPrivate: ").append(isPrivate).append("\n");
sb.append("fastResumeFile: ").append(fastResumeFile).append("\n");
sb.append("seedRatioLimit: ").append(seedRatioLimit).append("\n");
sb.append("timeRatioLimit: ").append(timeRatioLimit).append("\n");
return sb.toString();
}
}