AbstractDownload.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
xnap.net |
![]() |
![]() |
XNap |
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.
/*
* Java Napster version x.yz (for current version number as well as for
* additional information see version.txt)
*
* Previous versions of this program were written by Florian Student
* and Michael Ransburg available at www.weblicity.de/jnapster and
* http://www.tux.org/~daneel/content/projects/10.shtml respectively.
*
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 xnap.net;
import xnap.util.*;
import java.beans.*;
import java.io.*;
import java.net.*;
import java.util.*;
public abstract class AbstractDownload extends AbstractTransfer {
// --- Constant(s) ---
public final static int SOCKET_TIMEOUT = 5 * 1000;
public static String INCOMPLETE_EXTENSION = "incomplete";
//--- Data field(s) ---
protected boolean checkOnly = false;
protected boolean delIncompleteFiles;
protected boolean downloading = false;
protected String downloadDir;
protected String incompleteDir;
protected AbstractSearchResult sr;
protected long initialSize;
//--- Constructor(s) ---
/**
* AbstractDownload provides two different constructor, one starting a
* whole new download the other, getting an incomplete file as argument
* resuming a previously failed download.
*/
protected AbstractDownload(AbstractSearchResult sr, String incompleteDir,
String downloadDir, boolean delIncopmleteFiles)
{
this.sr = sr;
this.incompleteDir = incompleteDir;
this.downloadDir = downloadDir;
this.delIncompleteFiles = delIncompleteFiles;
setFilename(sr.getShortFilename());
setFilesize(sr.getFilesize());
setUser(sr.getUser());
addPropertyChangeListener(sr);
}
protected AbstractDownload(AbstractSearchResult sr, String incopmleteDir,
String downloadDir, boolean delIncompleteFiles,
long offset)
{
this(sr, incopmleteDir, downloadDir, delIncompleteFiles);
this.offset = offset;
}
protected AbstractDownload(AbstractSearchResult sr, String incompleteDir,
String downloadDir, File toResume)
{
this(sr, incompleteDir, downloadDir, false);
file = toResume;
filename = toResume.getName();
setInitialSize(toResume.length());
}
//--- Method(s) ---
public AbstractSearchResult getSearchResult()
{
return sr;
}
/**
* this should be implemented by all download classes
*/
public void setInitialSize(long size)
{
initialSize = size;
offset = Math.max(0, size - 100);
}
public void setCheckOnly(boolean newValue)
{
checkOnly = newValue;
}
public void setDelIncompleteFiles(boolean newValue)
{
delIncompleteFiles = newValue;
}
public void setDownloadDir(String newValue)
{
downloadDir = newValue;
}
public void setIncompleteDir(String newValue)
{
incompleteDir = newValue;
}
abstract public void run();
public void download(InputStream in, File file)
{
FileOutputStream fileOut;
if (die)
return;
try {
/* true means append */
fileOut = new FileOutputStream(file.getAbsolutePath(), true);
}
catch (FileNotFoundException fnf) {
setStatus(STATUS_FAILED,
"Invalid incomplete directory (check preferences)");
return;
} catch (IOException io) {
setStatus(STATUS_FAILED, "Could not write file " + file.getName());
return;
}
setStatus(STATUS_DOWNLOADING);
writeFile(fileOut, in);
try {
fileOut.flush();
fileOut.close();
if (bytesTransferred >= filesize || file.length() >= filesize) {
String completeFilename = Filename.uniqueFilename(downloadDir
+ filename);
// boolean complete = file.renameTo(new File(completeFilename));
// display average at last
setCurrentRate((bytesTransferred * 1000) / getElapsedTime());
setStatus(STATUS_FINISHED);
// setStatus(STATUS_FAILED,
// "Invalid download directory (check preferences)");
}
else {
/* this is the place to delete incomplete files
immediately after download */
if (delIncompleteFiles)
file.deleteOnExit();
if (die)
setStatus(STATUS_ABORTED);
else
setStatus(STATUS_INCOMPLETE);
}
}
catch (IOException e) {
setStatus(STATUS_FAILED, "Could not close file");
}
}
protected void writeFile(FileOutputStream out, InputStream in)
{
// we need to catch aborts for slow connects quickly
byte[] data = new byte[512];
int byteCount;
bytesTransferred = 0;
startTransfer();
/* what if we don't have the correct filesize ? */
while (bytesTransferred < sr.getFilesize()) {
try {
// wait for data
byteCount = 0;
while (byteCount == 0) {
if (die) {
Debug.log("Download aborted: " + getFilename());
throw new InterruptedException();
}
recalculateRate();
// blocks for at most SOCKET_TIMEOUT
byteCount = in.read(data);
}
if (byteCount == -1)
break;
bytesTransferred += byteCount;
if (offset < initialSize) {
int i = checkFile(data, byteCount);
Debug.log("result of checkFile: " + i);
switch(i) {
case -1:
setStatus(STATUS_FAILED, "files didn't match");
return;
case 0:
break;
default:
out.write(data, i, byteCount - i);
}
}
else
out.write(data, 0, byteCount);
} catch (IOException e) {
break;
} catch (InterruptedException e) {
break;
}
}
}
/**
* Compares <code>byteCount</code> bytes from incomplete file with newly
* downloaded bytes in <code>data</code>.
* @return 0, if they match, -1 if they don't match, a positive offset if
* a remainder should be written to.
*/
private int checkFile(byte[] data, int byteCount)
{
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
}
catch (FileNotFoundException fne) {
Debug.log("file not found");
return -1;
}
/* determine length of actually available bytes */
int numOfBytes = (int) Math.min(byteCount, initialSize - offset);
byte[] array = new byte[numOfBytes];
try {
raf.seek(offset);
raf.readFully(array);
}
catch (IOException e) {
Debug.log("dl: Wrong numOfBytes");
return -1;
}
Debug.log("first array: " + data);
Debug.log("second array: " + array);
for (int i = 0; i < numOfBytes; i++) {
if (data[i] != array[i])
return -1;
}
offset += numOfBytes;
if (byteCount > numOfBytes)
return numOfBytes;
return 0;
}
/**
* checks whether there is another file having the same name and the same
* final filesize.
* @return filename of incomplete file which is to be resumed.
*/
protected File checkForIncompleteFile(String filename, long filesize)
{
String name;
Debug.log("Checking for a file with name " + filename + " and size "
+ filesize);
try {
name = filename.substring(0, filename.lastIndexOf("."));
}
catch (StringIndexOutOfBoundsException e) {
return new File(Filename.uniqueFilename(incompleteDir + filename,
(new Long(filesize)).toString()));
}
//filename += "." + (new Long(filesize)).toString();
Debug.log("file to be found starts with: " + name);
File[] list = (new File(incompleteDir)).listFiles();
if (list != null) {
for (int i=0; i < list.length; i++) {
/* I totally rely on file size and renounce at using the
filenames too */
//if (list[i].getName().indexOf(name) != -1) {
/* parse for final filesize and compare */
try {
String file = list[i].getName();
String length = file.substring(0, file.lastIndexOf("."));
length = length.substring(length.lastIndexOf(".") + 1,
length.length());
Debug.log("size to look for: " + length);
try {
if (Long.parseLong(length) == filesize)
return list[i];
}
catch (NumberFormatException e) {
}
}
catch (StringIndexOutOfBoundsException e) {
}
// }
}
}
return new File(Filename.uniqueFilename(incompleteDir + filename,
(new Long(filesize)).toString()));
}
}
The table below shows all metrics for AbstractDownload.java.




