package transfer.download;
import java.awt.TrayIcon;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Collection;
import main.settings.Settings;
import transfer.AbstractFileTransfer;
import transfer.download.logic.SourceLogic;
import ui.tray.TrayManager;
import common.ClientServerProtocol;
import common.connection.ConnectionWriterInterface;
import common.files.NamedFile;
import common.info.FileSource;
import connection.peer.GenericPeerConnection;
import connection.server.ServerConnection;
import static main.ClientMain.*;
public class FileDownload extends AbstractFileTransfer implements Serializable
{
private static final long serialVersionUID = 8560432095110899110L;
private static class DownloadStatus extends AbstractStatus
{
public static final DownloadStatus INACTIVE = new DownloadStatus("inactive");
public static final DownloadStatus NO_SOURCES = new DownloadStatus("no sources");
public static final DownloadStatus QUERYING = new DownloadStatus("querying");
public static final DownloadStatus CONNECTING = new DownloadStatus("connecting");
public static final DownloadStatus DOWNLOADING = new DownloadStatus("downloading");
public static final DownloadStatus FINISHED = new DownloadStatus("finished");
protected DownloadStatus(String name)
{
super(name);
}
}
private File target;
private static final Object FILE_SYSTEM_LOCK = new Object();
private long chunkLength;
private SourceLogic sourceLogic = new SourceLogic(this);
private boolean interrupted = false;
public FileDownload(NamedFile file, long chunkLength)
{
super(file, 0);
target = new File(Settings.share.folder.incomplete + File.separator
+ file.buildTempName());
this.chunkLength = chunkLength;
transitTo(DownloadStatus.INACTIVE);
}
public void query(ServerConnection serverConnection)
{
if ((getStatus() != DownloadStatus.INACTIVE)
&& (getStatus() != DownloadStatus.NO_SOURCES))
{
return;
}
transitTo(DownloadStatus.QUERYING);
int protocolId = ClientServerProtocol.PROTOCOL_FILES;
int opcode = ClientServerProtocol.Files.OP_GET_SOURCES;
serverConnection.sendOverlapped(protocolId, opcode,
new ConnectionWriterInterface()
{
public void run(ObjectOutputStream os) throws IOException
{
os.writeObject(file);
os.writeBoolean(false);
}
});
}
public void contactSources(Collection<FileSource> sources)
{
if (getStatus() != DownloadStatus.QUERYING)
{
return;
}
transitTo(DownloadStatus.CONNECTING);
sourceLogic.chooseSource(sources);
}
public void startDownloading(FileDownloadConnection connection)
{
setConnection(connection);
transitTo(DownloadStatus.DOWNLOADING);
}
public void notifyNoSources()
{
transitTo(DownloadStatus.NO_SOURCES);
}
public void notifyFinished()
{
setFinished();
transitTo(DownloadStatus.FINISHED);
moveToDownloadFolder();
notifyUser();
}
public void notifySourceDown()
{
setConnection(null);
transitTo(DownloadStatus.INACTIVE);
getDownloadManager().updateDownload(this);
}
public void interrupt()
{
GenericPeerConnection connection = getConnection();
if (connection != null)
{
connection.terminate();
}
interrupted = true;
}
public boolean isInterrupted()
{
return interrupted;
}
public OutputStream openTarget() throws FileNotFoundException
{
FileOutputStream fos = new FileOutputStream(target);
return new BufferedOutputStream(fos);
}
private void moveToDownloadFolder()
{
synchronized (FILE_SYSTEM_LOCK)
{
File newPath = getUniquePath();
target.renameTo(newPath);
target = newPath;
}
}
private File getUniquePath()
{
final String prefix = Settings.share.folder.download + File.separator;
File uniquePath = new File(prefix + file.getName());
while (uniquePath.exists())
{
uniquePath = new File(prefix + "Copy of " + uniquePath.getName());
}
return uniquePath;
}
private void notifyUser()
{
TrayManager trayManager = getGuiManager().getTrayManager();
if (trayManager.isTrayed())
{
trayManager.showTrayMessage("Sillian - Download finished",
"Finished downloading " + file.getName(), TrayIcon.MessageType.INFO);
}
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException
{
doReadObject(in);
transitTo(DownloadStatus.INACTIVE);
target = (File) in.readObject();
chunkLength = in.readLong();
}
private void writeObject(ObjectOutputStream out) throws IOException
{
doWriteObject(out);
out.writeObject(target);
out.writeLong(chunkLength);
}
}