DccDownload.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.xnap.transfer |
![]() |
![]() |
XNap 3 |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* XNap - A P2P framework and client.
*
* See the file AUTHORS for copyright information.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.xnap.transfer;
import javax.swing.Action;
import java.awt.event.ActionEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Hashtable;
import org.apache.log4j.Logger;
import org.xnap.XNap;
import org.xnap.gui.util.IconHelper;
import org.xnap.io.ThrottledInputStream;
import org.xnap.net.NetHelper;
import org.xnap.peer.Peer;
import org.xnap.plugin.Plugin;
import org.xnap.transfer.action.AbstractStopAction;
import org.xnap.transfer.action.AbstractTransferAction;
import org.xnap.util.FileHelper;
import org.xnap.util.FiniteStateMachine;
import org.xnap.util.IllegalOperationException;
import org.xnap.util.State;
/**
* Downloads a file via the dcc protocol.
*/
public class DccDownload extends AbstractTransfer implements Download {
//--- Constant(s) ---
private static final Hashtable TRANSITION_TABLE;
static {
State[][] table = new State[][] {
{ State.NOT_STARTED,
State.CONNECTING, State.STOPPED },
{ State.CONNECTING,
State.DOWNLOADING, State.STOPPING, State.STOPPED, },
{ State.DOWNLOADING,
State.SUCCEEDED, State.STOPPING, State.STOPPED, },
{ State.STOPPING,
State.SUCCEEDED, State.STOPPED }
};
TRANSITION_TABLE = FiniteStateMachine.createStateTable(table);
}
//--- Data field(s) ---
private static Logger logger = Logger.getLogger(DccDownload.class);
private File file;
private String filename;
private long filesize;
private String host;
private Peer peer;
private int port;
private long totalBytesTransferred = 0;
private StateMachine sm = new StateMachine();
private AbstractTransferAction acceptAction = new AcceptAction();
private AbstractTransferAction rejectAction = new RejectAction();
private AbstractTransferAction stopAction = new StopAction();
//--- Constructor(s) ---
/**
*
* @param peer the peer thae file is downloaded from
* @param file the destination file, the downloaded data is stored here
* @param host the host to connect to
* @param port the port to connect to
*/
public DccDownload(Peer peer, String filename, long filesize,
String host, int port)
{
this.peer = peer;
this.filename = filename;
this.filesize = filesize;
this.host = host;
this.port = port;
stopAction.setEnabledLater(false);
}
//--- Method(s) ---
public long getBytesTransferred()
{
return totalBytesTransferred;
}
public Action[] getActions()
{
return new Action[] { acceptAction, rejectAction, stopAction, };
}
public File getFile()
{
return file;
}
public String getFilename()
{
return filename;
}
public long getFilesize()
{
return filesize;
}
public Peer getPeer()
{
return peer;
}
public Plugin getPlugin()
{
return null;
}
public String getStatus()
{
return sm.getDescription();
}
public long getTotalBytesTransferred()
{
return totalBytesTransferred;
}
public boolean isDone()
{
State s = sm.getState();
return s == State.SUCCEEDED || s == State.STOPPED;
}
public boolean isRunning()
{
State s = sm.getState();
return s == State.NOT_STARTED || s == State.CONNECTING
|| s == State.DOWNLOADING;
}
public void reject()
{
try {
setState(State.STOPPED, XNap.tr("Download rejected"));
}
catch(IllegalOperationException e) {
logger.debug("unexpected exception", e);
}
}
public void start()
{
try {
setState(State.CONNECTING);
}
catch(IllegalOperationException e) {
logger.debug("unexpected exception", e);
}
}
private void setState(State newState, String description)
{
sm.setState(newState, description);
stateChanged();
}
private void setState(State newState)
{
sm.setState(newState);
stateChanged();
}
public void stop()
{
try {
setState(State.STOPPING);
}
catch(IllegalOperationException e) {
logger.debug("unexpected exception", e);
}
}
//--- Inner Class(es) ---
/**
* Starts the download offer.
*/
public class AcceptAction extends AbstractTransferAction {
//--- Constructor(s) ---
public AcceptAction()
{
putValue(Action.NAME, XNap.tr("Accept"));
putValue(Action.SHORT_DESCRIPTION,
XNap.tr("Download selected file(s)."));
putValue(IconHelper.XNAP_ICON, "down.png");
}
//--- Method(s) ---
public boolean equals(Object o)
{
return o instanceof AcceptAction;
}
public void actionPerformed(ActionEvent event)
{
DccDownload.this.start();
}
}
/**
* Rejects the download offer.
*/
public class RejectAction extends AbstractTransferAction {
//--- Constructor(s) ---
public RejectAction()
{
putValue(Action.NAME, XNap.tr("Reject"));
putValue(Action.SHORT_DESCRIPTION,
XNap.tr("Rejects selected downloads."));
putValue(IconHelper.XNAP_ICON, "stop_hand.png");
}
//--- Method(s) ---
public boolean equals(Object o)
{
return o instanceof RejectAction;
}
public void actionPerformed(ActionEvent event)
{
DccDownload.this.reject();
}
}
/**
* Starts the download offer.
*/
public class StopAction extends AbstractStopAction {
//--- Constructor(s) ---
public StopAction()
{
}
//--- Method(s) ---
public void actionPerformed(ActionEvent event)
{
DccDownload.this.stop();
}
}
private class StateMachine extends FiniteStateMachine
{
private DownloadRunner runner;
//--- Constructor(s) ---
public StateMachine()
{
super(State.NOT_STARTED, TRANSITION_TABLE);
setDescription(XNap.tr("Please accept or reject download"));
}
//--- Method(s) ---
protected synchronized void stateChanged(State oldState,
State newState)
{
if (newState == State.CONNECTING) {
runner = new DownloadRunner();
Thread t = new Thread(runner, "DccDownload:" + getFilename());
t.start();
stopAction.setEnabledLater(true);
}
else if (newState == State.STOPPING) {
runner.die = true;
stopAction.setEnabledLater(false);
}
else if (newState == State.STOPPED || newState == State.SUCCEEDED) {
runner = null;
stopAction.setEnabledLater(false);
}
if (oldState == State.NOT_STARTED) {
acceptAction.setEnabledLater(false);
rejectAction.setEnabledLater(false);
}
}
}
private class DownloadRunner implements Runnable
{
//--- Data field(s) ---
private boolean die = false;
//--- Method(s) ---
public void run()
{
InputStream in = null;
OutputStream out = null;
try {
// Connect the socket and set a timeout.
logger.debug("connecting to " + host + ":" + port);
Socket socket = new Socket(host, port);
socket.setSoTimeout(SOCKET_TIMEOUT);
in = new ThrottledInputStream
(new BufferedInputStream(socket.getInputStream()));
out = new BufferedOutputStream(socket.getOutputStream());
download(in, out);
setState(die ? State.STOPPED : State.SUCCEEDED);
}
catch (IOException e) {
logger.warn("connection failed", e);
setState(State.STOPPED, NetHelper.getErrorMessage(e));
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
}
catch (IOException e) {
}
}
}
public void download(InputStream in, OutputStream out) throws IOException
{
OutputStream fileOut = null;
try {
file = FileHelper.createIncompleteFile(getFilename());
fileOut = new BufferedOutputStream(new FileOutputStream(file));
setState(State.DOWNLOADING);
byte[] inBuffer = new byte[1024];
byte[] outBuffer = new byte[4];
while (!die && totalBytesTransferred < getFilesize()) {
// compute the number of bytes to read
long toRead = getFilesize() - totalBytesTransferred;
int len = (int)Math.min(toRead, inBuffer.length);
len = in.read(inBuffer, 0, len);
if (len == -1) {
break;
}
fileOut.write(inBuffer, 0, len);
totalBytesTransferred += len;
// send back an acknowledgement of how many bytes
// we have got so far
outBuffer[0] = (byte) ((totalBytesTransferred >> 24) & 0xff);
outBuffer[1] = (byte) ((totalBytesTransferred >> 16) & 0xff);
outBuffer[2] = (byte) ((totalBytesTransferred >> 8) & 0xff);
outBuffer[3] = (byte) ((totalBytesTransferred >> 0) & 0xff);
out.write(outBuffer);
out.flush();
}
fileOut.flush();
}
finally {
transferStopped();
if (fileOut != null) {
try {
fileOut.close();
}
catch (IOException e) {
}
}
}
}
}
}
The table below shows all metrics for DccDownload.java.




