int lState = pDownload.getState();
if (lState != DownloadService.QUEUED) {
return;
}
IPersonalAttachment pPAttachment = pDownload.getAttachment();
URI lLink = pPAttachment.getLink();
URL lUrl;
try {
lUrl = lLink.toURL();
} catch (MalformedURLException e) {
// mmmhh bad link. let's exist.
throw new NetworkException(e.getMessage());
}
sLog.info("Starting download: "
+ pDownload.getAttachment().getName());
GetMethod gMethod = null;
FileOutputStream lOutputStream = null;
InputStream lInputStream = null;
int lCount = 0; // Downloaded bytes count
// STATUS CHANGE CONNECTING
pDownload.setState(DownloadService.CONNECTING);
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_STATUS_CHANGED));
boolean lRedirect = false;
try {
boolean append = false;
if ("http".equals(lUrl.getProtocol())) {
HttpClient hClient = new HttpClient();
// CB TODO, get this from core preferences.
hClient.getParams().setSoTimeout(
NetPropertiesHandler.timeoutValue);
HostConfiguration hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
gMethod = new GetMethod(lUrl.toExternalForm());
// Add a byte range header asking for partial content.
if (pDownload.getAttachment().isIncomplete()) {
append = true;
addByteRangeHeader(pDownload.getAttachment(), gMethod);
gMethod.setFollowRedirects(true);
} else {
gMethod.setFollowRedirects(false);
}
// Need to do redirects manually to get the filename for
// storage. We follow the redirections until a 200 OK.
// we break in case of error.
boolean lContinue = true;
while (lContinue) {
int status = hClient.executeMethod(gMethod);
switch (status) { // Switch the result.
case HttpStatus.SC_OK: {
lContinue = false;
}
break;
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_MOVED_TEMPORARILY:
case HttpStatus.SC_SEE_OTHER:
case HttpStatus.SC_TEMPORARY_REDIRECT: {
lRedirect = true;
// The redirection code fails for
// localhost, use IP address as a workaround.
String redirectLocation;
Header locationHeader = gMethod
.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
gMethod.setFollowRedirects(true);
lUrl = new URL(redirectLocation);
} else {
}
}
break;
case HttpStatus.SC_PARTIAL_CONTENT:
// sLog.info("(1) Partial download granted for: "
// + pUrl.toExternalForm());
// sLog.info("(2) Start at byte: "
// + gMethod.getRequestHeader("Range")
// .getValue());
lContinue = false;
break;
case HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE: {
// 28-07-2006, Duh? OK let's try again without
// Range.
// sLog.warn("(1) Partial download denied for: "
// + pUrl.toExternalForm());
Header lRHeader = gMethod
.getResponseHeader("Content-Range");
if (lRHeader != null) {
// sLog.warn("(2) The content-range is: "
// + lRHeader.getValue());
}
// sLog.warn(gMethod.getResponseBodyAsString());
Header h = gMethod.getRequestHeader("Range");
gMethod.removeRequestHeader(h);
append = false;
}
break;
case HttpStatus.SC_UNAUTHORIZED: {
// Retry with password.
hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
hClient.getState()
.setCredentials(
new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT,
AuthScope.ANY_REALM),
getCredentials(pDownload
.getAttachment().getNews()
.getFeedReference().resolve()));
gMethod = new GetMethod(lUrl.toString());
gMethod.setDoAuthentication(true);
}
break;
case HttpStatus.SC_METHOD_NOT_ALLOWED: {
// This sometimes happens, we exit with an error
// message.
sLog.warn(gMethod.getStatusLine().getReasonPhrase()
+ " to URL " + lUrl.toExternalForm());
}
break;
default: {
pDownload.setState(DownloadService.ERROR);
pDownload.setMessage(gMethod.getStatusLine()
.getReasonPhrase());
throw new NetworkException(pDownload.getMessage());
}
}
}
// CB TODO Asser the HEADER information.
HTTPHEADInfo lInfo = getHeadInfo(gMethod);
if (!append) {
try {
pDownload.getAttachment().setContentSize(lInfo.length);
} catch (IllegalArgumentException iae) {
// Likely parsing of the HEAD Date failed.
}
} else {
pDownload.getAttachment().setContentSize(
(int) pDownload.getAttachment().getLength());
}
pDownload.getAttachment().setContentDate(
lInfo.getModifiedLong());
pDownload.setLength(pDownload.getAttachment().getContentSize());
lInputStream = gMethod.getResponseBodyAsStream();
} else {
pDownload.setLength(0);
lInputStream = lUrl.openStream();
}
// REDIRECT Handling.
// In case of re-direct we re-create a download file.
// We don't store the re-direct URL. (It is volatile).
// The volatile redirect URL is used to generate the file name.
// if it can't be generated, we create a filename from the
// the RSS entry and set it in the enclosure object. Before we
// redownload
// the file, we also want to
// check if the file is by chance an already existing file in
// the folder, cache or player. If so we cancel the download.
// We fire a change event.
boolean lInspect = false;
if (lRedirect) {
File lFile = pPAttachment.getFile(true);
pPAttachment.setFileName(lFile.getName());
}
File lF = pPAttachment.getFile();
if (!lF.exists()) {
lF.createNewFile();
lInspect = false;
}
// --- File Inspection.
// CB FIXME Do we have to inspect only after redirect?
// We don't inspect a file with a random number.
if (lInspect) {
// If we re-inspect and remark, we ignore the
// candidate restriction has we are already
// in the download phase. The enclosure was either
// a candidate before or downloaded manually.
pPAttachment.setCandidate(false);
// CB TODO, migrate inspections.
// XFeedLogic.getInstance().inspectSingleFile(pEncl);
// XFeedLogic.getInstance().markSingleEnclosure(pEncl);
if (pPAttachment.isIncomplete()) {
// CB FIXME This is a problem, as we
// need to execute again to get the byte range.
// Rethink the whole redirect handling.
}
// CB TODO, this is very jPodder specific.
// updating the candidate, can likely be done
// in the model.
// pEncl.getFeed().updateSingleCandidate(pEncl,
// Configuration.getInstance().getMarkMax());
if (!pPAttachment.isMarked()) {
pDownload.setState(DownloadService.CANCELLED);
pDownload.setMessage("Redirect leads to existing file");
throw new NetworkException(
"Redirect leads to existing file");
}
}
// THE ENCLOSURE FILE IS NEVER NULL, AND EXISTS FROM HERE!
// WE ARE IN DEEP SHIT OTHERWISE.
sLog.info(Messages.getString("tasks.download.newDownload")
+ pPAttachment.getFile());
lOutputStream = new FileOutputStream(lF, append);
if (append) {
lCount = (int) pPAttachment.getFile().length();
}
if (pDownload.getLength() != 0) {
} else {
// Length of the file is unknown.
// This not good. (only for HTTP)