package com.limegroup.bittorrent;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.limewire.bittorrent.Torrent;
import org.limewire.bittorrent.TorrentManager;
import org.limewire.bittorrent.TorrentParams;
import org.limewire.core.settings.BittorrentSettings;
import org.limewire.inject.LazySingleton;
import org.limewire.logging.Log;
import org.limewire.logging.LogFactory;
import org.limewire.util.FileUtils;
import org.limewire.util.GenericsUtils;
import org.limewire.util.GenericsUtils.ScanMode;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.limegroup.gnutella.ActivityCallback;
/**
* This class is responsible for saving a torrent as an upload memento and
* loading them at startup.
*/
@LazySingleton
public class TorrentUploadManager implements BTUploaderFactory {
private static final Log LOG = LogFactory.getLog(TorrentUploadManager.class);
private final Provider<ActivityCallback> activityCallback;
private final Provider<TorrentManager> torrentManager;
private final Provider<Torrent> torrentProvider;
@Inject
public TorrentUploadManager(Provider<TorrentManager> torrentManager,
Provider<Torrent> torrentProvider, Provider<ActivityCallback> activityCallback) {
this.torrentManager = torrentManager;
this.torrentProvider = torrentProvider;
this.activityCallback = activityCallback;
}
/**
* Iterates through the uploads folder finding saved torrent mementos and
* starting off the uploads.
*/
public void loadSavedUploads() {
File uploadsDirectory = BittorrentSettings.LIBTORRENT_UPLOADS_FOLDER.get();
if (uploadsDirectory.exists()) {
File[] uploadMementos = uploadsDirectory.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return "memento".equals(FileUtils.getFileExtension(file));
}
});
if (uploadMementos != null) {
for (File mementoFile : uploadMementos) {
Map<String, Object> memento = null;
try {
memento = readMemento(mementoFile);
} catch (IllegalArgumentException e) {
LOG.error("Error reading memento for: " + mementoFile, e);
} catch (IOException e) {
LOG.error("Error reading memento for: " + mementoFile, e);
} catch (ClassNotFoundException e) {
LOG.error("Error reading memento for: " + mementoFile, e);
}
if (memento != null) {
Torrent torrent = torrentProvider.get();
File torrentFile = (File) memento.get("torrentFile");
File fastResumeFile = (File) memento.get("fastResumeFile");
File torrentDataFile = (File) memento.get("torrentDataFile");
String sha1 = (String) memento.get("sha1");
String trackerURL = (String) memento.get("trackerURL");
String name = (String) memento.get("name");
if (torrentDataFile.exists()) {
// TODO show error message when seeds cannot be
// resumed?
if (torrentManager.get().isValid()
&& !torrentManager.get().isDownloadingTorrent(mementoFile)) {
try {
TorrentParams params = new TorrentParams(name, sha1);
params.trackerURL(trackerURL).fastResumeFile(fastResumeFile)
.torrentFile(torrentFile).torrentDataFile(
torrentDataFile);
torrent.init(params);
} catch (IOException e) {
LOG.error("Error initializing memento from: " + mementoFile, e);
}
torrentManager.get().registerTorrent(torrent);
createBTUploader(torrent);
torrent.setAutoManaged(true);
torrent.start();
}
}
}
}
}
}
}
private Map<String, Object> readMemento(File mementoFile) throws IOException,
ClassNotFoundException, IllegalArgumentException {
Object mementoObject = FileUtils.readObject(mementoFile);
Map<String, Object> memento = GenericsUtils.scanForMap(mementoObject, String.class,
Object.class, ScanMode.EXCEPTION);
return memento;
}
/**
* Creates an upload memento from the Torrent and writes it to disk.
*/
public void writeMemento(Torrent torrent) throws IOException {
// TODO use database instead of writing to file?
File torrentMomento = getMementoFile(torrent);
torrentMomento.getParentFile().mkdirs();
Map<String, Object> map = new HashMap<String, Object>();
map.put("torrentDataFile", torrent.getTorrentDataFile().getAbsoluteFile());
map.put("torrentFile", torrent.getTorrentFile().getAbsoluteFile());
map.put("fastResumeFile", torrent.getFastResumeFile().getAbsoluteFile());
map.put("sha1", torrent.getSha1());
map.put("trackerURL", torrent.getTrackerURL());
map.put("name", torrent.getName());
FileUtils.writeObject(torrentMomento, map);
}
private File getMementoFile(Torrent torrent) {
File torrentMomento = new File(torrentManager.get().getTorrentManagerSettings()
.getTorrentUploadsFolder(), torrent.getName() + ".memento");
return torrentMomento;
}
/**
* Removes any found upload mementos/artifacts for the given torrent from
* disk.
*/
public void removeMemento(Torrent torrent) {
File torrentMomento = getMementoFile(torrent);
FileUtils.forceDelete(torrentMomento);
FileUtils.forceDelete(torrent.getTorrentFile());
FileUtils.forceDelete(torrent.getFastResumeFile());
}
@Override
public BTUploader createBTUploader(Torrent torrent) {
BTUploader btUploader = new BTUploader(torrent, activityCallback.get(), this,
torrentManager.get());
btUploader.registerTorrentListener();
activityCallback.get().addUpload(btUploader);
return btUploader;
}
}