blob: 0bb9025c8d2b28dcafce5400b193ac537de2d2a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2008 Remy Suen, Composent Inc., and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Remy Suen <remy.suen@gmail.com> - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.internal.provider.bittorrent;
import java.io.IOException;
import java.util.Date;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.filetransfer.IFileRangeSpecification;
import org.eclipse.ecf.filetransfer.IFileTransferListener;
import org.eclipse.ecf.filetransfer.IFileTransferPausable;
import org.eclipse.ecf.filetransfer.IFileTransferRateControl;
import org.eclipse.ecf.filetransfer.IIncomingFileTransfer;
import org.eclipse.ecf.filetransfer.IOutgoingFileTransfer;
import org.eclipse.ecf.filetransfer.UserCancelledException;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveDataEvent;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveDoneEvent;
import org.eclipse.ecf.protocol.bittorrent.IPieceProgressListener;
import org.eclipse.ecf.protocol.bittorrent.ITorrentStateListener;
import org.eclipse.ecf.protocol.bittorrent.Torrent;
final class TorrentFileTransfer implements IFileTransferPausable, IFileTransferRateControl, IIncomingFileTransfer, IOutgoingFileTransfer {
private final ID id;
private final IFileTransferListener listener;
private final Torrent torrent;
private final IPieceProgressListener pieceListener;
private final ITorrentStateListener stateListener;
private final double total;
private Exception exception;
private boolean paused = false;
TorrentFileTransfer(ID id, IFileTransferListener listener, Torrent torrent) {
this.id = id;
this.listener = listener;
this.torrent = torrent;
total = torrent.getTorrentFile().getTotalLength();
pieceListener = new IPieceProgressListener() {
public void blockDownloaded(int piece, int index, int blockLength) {
TorrentFileTransfer.this.listener.handleTransferEvent(new IIncomingFileTransferReceiveDataEvent() {
public IIncomingFileTransfer getSource() {
return TorrentFileTransfer.this;
}
});
}
};
stateListener = new ITorrentStateListener() {
public void stateChanged(int state) {
if (state == ITorrentStateListener.FINISHED) {
notifyCompletion(null);
}
}
};
torrent.addPieceProgressListener(pieceListener);
torrent.addTorrentStateListener(stateListener);
try {
torrent.start();
} catch (final IOException e) {
notifyCompletion(e);
}
}
private void notifyCompletion(Exception exception) {
this.exception = exception;
torrent.removePieceProgressListener(pieceListener);
torrent.removeTorrentStateListener(stateListener);
listener.handleTransferEvent(new IIncomingFileTransferReceiveDoneEvent() {
public Exception getException() {
return TorrentFileTransfer.this.exception;
}
public IIncomingFileTransfer getSource() {
return TorrentFileTransfer.this;
}
});
}
public void cancel() {
try {
torrent.stop();
notifyCompletion(new UserCancelledException());
} catch (final IOException e) {
notifyCompletion(e);
}
}
public long getBytesSent() {
return torrent.getUploaded();
}
public Exception getException() {
return exception;
}
public double getPercentComplete() {
return (total - torrent.getRemaining()) / total;
}
public Object getAdapter(Class adapter) {
return adapter.isInstance(this) ? this : null;
}
public ID getID() {
return id;
}
public long getBytesReceived() {
return torrent.getDownloaded();
}
public boolean isDone() {
return exception != null || getPercentComplete() == 1;
}
public boolean pause() {
if (paused || isDone()) {
return false;
}
try {
torrent.stop();
paused = true;
return true;
} catch (final IOException e) {
notifyCompletion(e);
return false;
}
}
public boolean resume() {
if (!paused || isDone()) {
return false;
}
try {
torrent.start();
paused = false;
return true;
} catch (final IOException e) {
notifyCompletion(e);
return false;
}
}
public void setMaxDownloadSpeed(long maxDownloadSpeed) {
torrent.setMaxDownloadSpeed(maxDownloadSpeed);
}
public void setMaxUploadSpeed(long maxUploadSpeed) {
torrent.setMaxUploadSpeed(maxUploadSpeed);
}
public boolean isPaused() {
return paused;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getListener()
*/
public IFileTransferListener getListener() {
return listener;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getFileRangeSpecification()
*/
public IFileRangeSpecification getFileRangeSpecification() {
return null;
}
public long getFileLength() {
return torrent.getTorrentFile().getTotalLength();
}
/* (non-Javadoc)
* @see org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getRemoteFileName()
*/
public String getRemoteFileName() {
if (torrent == null)
return null;
if (!torrent.getTorrentFile().isMultiFile()) {
return torrent.getTorrentFile().getFilenames()[0];
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getRemoteLastModified()
*/
public Date getRemoteLastModified() {
// Not supported
return null;
}
}