/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2006 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.contrib.podcast.core.net;
/**
* @author <a href="mailto:christophe@kualasoft.com">Christophe Bouhier </a>
* @since 1.0
* @version 1.1
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.rssowl.contrib.i18n.Messages;
import org.rssowl.contrib.podcast.core.download.DownloadService;
import org.rssowl.contrib.podcast.core.download.IDownload;
import org.rssowl.contrib.podcast.model.IPersonalAttachment;
import org.rssowl.contrib.podcast.util.Logger;
import org.rssowl.core.persist.IFeed;
/**
* Class is holder for various static net related tasks. It also holds a
* download a runnable download class which fire events on success or error.
* <p>
* An instance of a download task can be retrieved with
* <code>getDownloadTask()</code>
* <p>
* Add a listner to this class, if notification of downloads is needed.
*
*/
public class NetTask implements RejectedExecutionHandler {
private static Logger sLog = new Logger(NetTask.class.getName());
private static NetTask mSelf;
private final ArrayList<INetTaskListener> mListenerList = new ArrayList<INetTaskListener>();
// private static ExecutorService mExecService = null;
public NetTask() {
// CB TODO Migrate thread pool usage to eclipse jobs.
// System.getProperties().setProperty("httpclient.useragent",
// "mozilla/4.0");
// System.getProperties().setProperty("httpclient.useragent",
// Main.APP_TITLE + " " + Main.APP_RELEASE);
// Uncomment to show the HTTP wire log.
// NetDebug.initialize();
// initTreadPool();
}
// CB TODO remove later, we don't need the thread pool
// public void initTreadPool() {
//
// mExecService = Executors.newFixedThreadPool(5);
//
// if (mExecService instanceof ThreadPoolExecutor) {
// ThreadPoolExecutor lExec = (ThreadPoolExecutor) mExecService;
// // lExec.setCorePoolSize(5);
// // lExec.setMaximumPoolSize(5);
// // lExec.setKeepAliveTime(5, TimeUnit.SECONDS);
// lExec.setRejectedExecutionHandler(this);
// BlockingQueue<Runnable> lQueue = lExec.getQueue();
//
// long lTime = lExec
// .getKeepAliveTime(java.util.concurrent.TimeUnit.MILLISECONDS);
//
// // sLog.info("Download threads will timeout when idle in: " + lTime
// // + " mili sec.");
// }
// }
public void rejectedExecution(Runnable arg0, ThreadPoolExecutor arg1) {
// sLog.error("Execution rejected for:" + arg0);
}
public static NetTask getInstance() {
if (mSelf == null) {
mSelf = new NetTask();
}
return mSelf;
}
/**
* Add a Listener to the list.
* <p>
*
* @param pListener
* NetActionListener. The listener to be added.
*/
public final void addNetActionListener(INetTaskListener pListener) {
if (pListener != null && !mListenerList.contains(pListener)) {
mListenerList.add(pListener);
}
}
/**
* Remove a listener from the list.
* <p>
*
* @param pListener
* The listener to be removed.
*/
public final void removeNetActionListener(INetTaskListener pListener) {
if (pListener != null && mListenerList.contains(pListener)) {
mListenerList.remove(pListener);
}
}
/**
* Fire a download complete event.
*
* @param event
* DownloadCompleteEvent
*/
public void notifyNetworkEvent(NetTaskEvent event) {
Iterator<INetTaskListener> it = mListenerList.iterator();
while (it.hasNext()) {
INetTaskListener listener = it.next();
listener.netActionPerformed(event);
}
}
// CB Remove later.
// /**
// * Download from an URL to a file.
// * <p>
// *
// * @param pDownload
// * Downloads.Download
// * @throws Exception
// */
// public static void download(IDownload pDownload) throws Exception {
// NetDownloadTask lTask = getDownloadTask(pDownload);
// mExecService.execute(lTask);
// }
// public static NetDownloadTask getDownloadTask(IDownload pDownload) {
// if (mSelf == null) {
// getInstance();
// }
// return mSelf.new NetDownloadTask(pDownload);
// }
/**
* Get a reader. The connection is left open and should be closed after
* having processed the response.
*
* @param feed
* @param url
* @param head
* NetHEADInfo
* @throws Exception
* @return Reader
*/
public static HTTPHEADInfo getHeadInfoWithGet(IFeed feed, URL url)
throws NetworkException {
HttpClient hClient = new HttpClient();
HostConfiguration hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
GetMethod gMethod = new GetMethod(url.toString());
gMethod.setRequestHeader("cache-control", "no-cache");
try {
int status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
// Check for redirection.
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|| status == HttpStatus.SC_MOVED_TEMPORARILY
|| status == HttpStatus.SC_SEE_OTHER
|| status == HttpStatus.SC_TEMPORARY_REDIRECT) {
String redirectLocation;
Header locationHeader = gMethod
.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
gMethod = new GetMethod(redirectLocation);
status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(gMethod.getStatusLine()
.getReasonPhrase());
}
} else {
// The response is invalid and did not provide the
// new
// location for
// the resource. Report an error or possibly handle
// the
// response
// like a 404 Not Found error.
}
} else {
if (status == 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(feed));
gMethod = new GetMethod(url.toString());
gMethod.setDoAuthentication(true);
status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(gMethod.getStatusLine()
.getReasonPhrase());
}
} else {
throw new NetworkException(gMethod.getStatusLine()
.getReasonPhrase());
}
}
}
return getHeadInfo(gMethod);
} catch (HttpException he) {
throw new NetworkException(he.getMessage());
} catch (IOException ioe) {
throw new NetworkException(ioe.getMessage());
}
}
public static Reader getReader(URL url) throws NetworkException {
return getReader(null, url, null);
}
public static Reader getReader(IFeed pFeed, URL url, HTTPHEADInfo head)
throws NetworkException {
InputStream lStream = getStream(pFeed, url, head);
InputStreamReader reader = new InputStreamReader(lStream);
return reader;
}
public static InputStream getStream(IFeed pFeed, URL url, HTTPHEADInfo head)
throws NetworkException {
InputStream lInputStream;
// sLog.debug(Messages.getMessage("net.feed.reader", new String[] {
// url + "", (url != null ? url.getProtocol() : "no-protocol") }));
// Check if HTTP protocol otherwise assume we have a local file
if ("http".equals(url.getProtocol())) {
HttpClient hClient = new HttpClient();
hClient.getParams().setSoTimeout(NetPropertiesHandler.timeoutValue);
HostConfiguration hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
GetMethod gMethod = new GetMethod(url.toString());
gMethod.setFollowRedirects(false);
gMethod.setRequestHeader("cache-control", "no-cache");
try {
int status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
// Check for redirection.
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|| status == HttpStatus.SC_MOVED_TEMPORARILY
|| status == HttpStatus.SC_SEE_OTHER
|| status == HttpStatus.SC_TEMPORARY_REDIRECT) {
String redirectLocation;
Header locationHeader = gMethod
.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
gMethod = new GetMethod(redirectLocation);
status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(gMethod
.getStatusLine().getReasonPhrase());
}
} else {
// The response is invalid and did not provide
// the
// new
// location for
// the resource. Report an error or possibly
// handle
// the
// response
// like a 404 Not Found error.
}
} else {
if (status == HttpStatus.SC_UNAUTHORIZED) {
hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
hClient.getState().setCredentials(
new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT,
AuthScope.ANY_REALM),
getCredentials(pFeed));
gMethod = new GetMethod(url.toString());
gMethod.setDoAuthentication(true);
status = hClient.executeMethod(gMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(gMethod
.getStatusLine().getReasonPhrase());
}
} else {
throw new NetworkException(gMethod.getStatusLine()
.getReasonPhrase());
}
}
}
head = getHeadInfo(gMethod);
lInputStream = gMethod.getResponseBodyAsStream();
} catch (HttpException he) {
throw new NetworkException(he.getMessage());
} catch (IOException ioe) {
throw new NetworkException(ioe.getMessage());
}
} else {
try {
lInputStream = url.openStream();
} catch (IOException ioe) {
throw new NetworkException(ioe.getMessage());
}
}
return lInputStream;
}
/**
* Get the HTTP HEAD information. A static method, which gets the HEAD from
* an HTTP Connection.
*
* @param feed
* @param url
* @throws Exception
* @return NetHEADInfo
*/
public static HTTPHEADInfo getHeadInfo(IFeed feed, URL url)
throws NetworkException {
HTTPHEADInfo head = null;
HttpClient hClient = new HttpClient();
hClient.getParams().setSoTimeout(25000);
// hClient.setTimeout(5000); deprecated in 3.0 client
HostConfiguration hc = hClient.getHostConfiguration();
hc = setProxySetttings(hClient, hc);
HeadMethod hMethod = null;
try {
hMethod = new HeadMethod(url.toString());
hMethod.setRequestHeader("cache-control", "no-cache");
int status = hClient.executeMethod(hMethod);
if (status != HttpStatus.SC_OK) {
// Check for redirection.
if (status == HttpStatus.SC_MOVED_PERMANENTLY
|| status == HttpStatus.SC_MOVED_TEMPORARILY
|| status == HttpStatus.SC_SEE_OTHER
|| status == HttpStatus.SC_TEMPORARY_REDIRECT) {
String redirectLocation;
Header locationHeader = hMethod
.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
hMethod = new HeadMethod(redirectLocation);
status = hClient.executeMethod(hMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(hMethod.getStatusLine()
.getReasonPhrase());
}
} else {
// The response is invalid and did not provide the
// new
// location for
// the resource. Report an error or possibly handle
// the
// response
// like a 404 Not Found error.
}
} else {
if (status == HttpStatus.SC_UNAUTHORIZED) {
// Retry with password.
hc = hClient.getHostConfiguration();
try {
hClient.getState().setCredentials(
new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT,
AuthScope.ANY_REALM),
getCredentials(feed)
);
} catch (Exception e) {
throw new NetworkException(e.getMessage());
}
hMethod = new HeadMethod(url.toString());
hMethod.setDoAuthentication(true);
status = hClient.executeMethod(hMethod);
if (status != HttpStatus.SC_OK) {
throw new NetworkException(hMethod.getStatusLine()
.getReasonPhrase());
}
} else {
throw new NetworkException(hMethod.getStatusLine()
.getReasonPhrase());
}
}
}
head = getHeadInfo(hMethod);
} catch (HttpException he) {
// Received Illegal redirect exception on some URLs
throw new NetworkException(he.getMessage(), he);
} catch (IOException ioe) {
throw new NetworkException(ioe.getMessage(), ioe);
} catch (java.lang.IllegalArgumentException iae) {
throw new NetworkException(iae.getMessage(), iae);
} finally {
if (hMethod != null) {
hMethod.releaseConnection();
}
}
return head;
}
/**
* Set the http proxy server for a host configuration.
*
* @param hClient
*
* @param hConf
* HostConfiguration
* @return HostConfiguration The configuration of the host which will be
* addressed
*/
public static HostConfiguration setProxySetttings(HttpClient hClient,
HostConfiguration hConf) {
if (NetPropertiesHandler.proxyServer != null) {
hConf.setProxy(NetPropertiesHandler.proxyServer.getHost(),
NetPropertiesHandler.proxyServer.getPort());
}
// Set the proxy Authentication if the proxy is checked.
String userName = NetPropertiesHandler.userName;
String password = NetPropertiesHandler.password;
if (NetPropertiesHandler.proxyOn
&& (userName != null && userName.length() > 0)
&& (password != null && password.length() > 0)) {
hClient.getState().setProxyCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(userName, password));
}
return hConf;
}
/**
* Get HTTP HEAD information.
*
* @param method
* HttpMethodBase
* @return NetHEADInfo
*/
private static HTTPHEADInfo getHeadInfo(HttpMethodBase method) {
Header header;
String lastModifiedDate = null;
String contentType = null;
String contentLength = "0";
String date = null;
Header[] lHeaders = method.getResponseHeaders();
for (int i = 0; i < lHeaders.length; i++) {
Header lHeader = lHeaders[i];
String lValue = lHeader.getValue();
// if (Debug.WITH_DEV_DEBUG && lValue != null && lValue.length() >
// 0) {
// sLog.debug(lHeader.getName() + ":" + lValue);
// }
}
if ((header = method.getResponseHeader("Date")) != null) {
date = header.getValue();
}
if ((header = method.getResponseHeader("Last-Modified")) != null) {
lastModifiedDate = header.getValue();
}
if ((header = method.getResponseHeader("Content-Type")) != null) {
contentType = header.getValue();
}
if ((header = method.getResponseHeader("Content-Length")) != null) {
contentLength = header.getValue();
}
// headers = gMethod.getResponseFooters();
return new HTTPHEADInfo(contentLength != null ? new Integer(
contentLength).intValue() : 0, contentType, null, date, null,
lastModifiedDate);
}
/**
* Perform network actions in a runnable class. The actions are: 1) Get a
* reader from an HTTP Connection. 2) Get the HTTP HEAD information. 3)
* Download a HTTP URL to a file on the file system.
* <p>
* The action is determined by the <code>actionType</code> argument in the
* constructor. you have to call the <code>setDownload()</code> method in
* case the action is a DOWNLOAD. Various results are reported with a
* network action.
*/
// public class NetDownloadTask implements Runnable {
//
// final static short DOWNLOAD = 400;
//
// final static short HEAD = 401;
//
// final static short STREAM = 402;
//
// private IDownload mDownload;
//
// /**
// * Constructor.
// *
// * @param actionHandler
// * NetActionHandler
// * @param actionType
// * short
// */
// public NetDownloadTask(IDownload pDownload) {
//
// mDownload = pDownload;
// }
//
// /**
// * Runnable class. Executes the net action, as provided by the
// * actionType parameter.
// */
// public void run() {
// try {
// downLoad(mDownload);
// } catch (Exception ie) {
// // sLog.debug(Messages.getMessage("net.download.failed",
// // new String[] { mDownload + "" }), ie);
// // if (mDownload != null) {
// fireNetActionPerformed(new NetTaskEvent(mDownload,
// NetTaskEvent.DOWNLOAD_FAILED, ie));
// }
// }
// }
/**
* Download using the apache httpClient.
*
* @param d
* Downloads.Download
* @throws Exception
*/
public void downLoad(IDownload pDownload) throws NetworkException {
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)
}
pDownload.setStart(lCount);
// STATUS CHANGE DOWNLOADING
pDownload.setState(DownloadService.DOWNLOADING);
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_STATUS_CHANGED));
int read;
byte[] buffer = new byte[8192];
while ((read = lInputStream.read(buffer)) > 0) {
lOutputStream.write(buffer, 0, read);
lCount += read;
pDownload.setCurrent(lCount);
if (pDownload.getState() == DownloadService.CANCELLED
|| pDownload.getState() == DownloadService.PAUZED) {
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_STATUS_CHANGED));
break;
}
}
// sLog.info(Messages
// .getMessage("net.download.start", new String[] {
// lCount + "", pDownload.lengthOfTask + "" }));
} catch (org.apache.commons.httpclient.HttpException he) {
pDownload.setState(DownloadService.ERROR);
pDownload.setMessage(he.getMessage());
} catch (java.io.FileNotFoundException fnfe) {
pDownload.setState(DownloadService.ERROR);
pDownload.setMessage(fnfe.getMessage());
} catch (java.io.IOException ioe) {
pDownload.setState(DownloadService.ERROR);
pDownload.setMessage(ioe.getMessage());
} catch (Exception e) {
pDownload.setState(DownloadService.ERROR);
pDownload.setMessage(e.getMessage());
}
// catch (java.lang.IllegalArgumentException iae) {
// pDownload.setState(DownloadLogic.ERROR);
// pDownload.setMessage("Programatic Error");
// }
finally {
lState = pDownload.getState();
if (lState == DownloadService.DOWNLOADING) {
// Incompleted downlads are checked.
if (pDownload.getLength() != 0
&& lCount != pDownload.getLength()) {
// sLog.info("Partial download of : "
// + pDownload.getEnclosure().getFile());
pDownload.setState(DownloadService.ERROR);
// pDownload.setMessage(Messages
// .getString("nettask.incomplete"));
} else {
// STATUS CHANGE COMPLETE
pDownload.setState(DownloadService.COMPLETED);
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_STATUS_CHANGED));
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_SUCCESS));
}
}
if (lState == DownloadService.ERROR) {
notifyNetworkEvent(new NetTaskEvent(pDownload,
NetTaskEvent.DOWNLOAD_STATUS_CHANGED));
throw new NetworkException(pDownload.getMessage());
}
if (gMethod != null) {
gMethod.abort();
gMethod.releaseConnection();
}
try {
if (lOutputStream != null)
lOutputStream.close();
if (lInputStream != null) {
lInputStream.close();
}
} catch (IOException ioe) {
throw new NetworkException(ioe.getMessage());
}
}
}
private void addByteRangeHeader(IPersonalAttachment encl, GetMethod gMethod) {
int fileLen = new Long(encl.getFile().length()).intValue();
String contentRange = "bytes=" + new Integer((fileLen)).toString()
+ "-";
Header head = new Header();
head.setName("Range");
head.setValue(contentRange);
gMethod.addRequestHeader(head);
}
// CB TODO.
// public class AuthDialog implements CredentialsProvider {
//
// public AuthDialog() {
// super();
// }
//
// public Credentials getCredentials(final AuthScheme authscheme,
// final String host, int port, boolean proxy)
// throws CredentialsNotAvailableException {
// if (authscheme == null) {
// return null;
// }
// try {
// if (authscheme instanceof NTLMScheme) {
// // System.out.println(host + ":" + port + " requires
// // Windows
// // authentication");
// // System.out.print("Enter domain: ");
// // String domain = readConsole();
// // System.out.print("Enter username: ");
// // String user = readConsole();
// // System.out.print("Enter password: ");
// // String password = readConsole();
// // return new NTCredentials(user, password, host,
// // domain);
// throw new CredentialsNotAvailableException(
// "Unsupported authentication scheme: "
// + authscheme.getSchemeName());
// } else if (authscheme instanceof RFC2617Scheme) {
// System.out.println(host + ":" + port
// + " requires authentication with the realm '"
// + authscheme.getRealm() + "'");
// int result = CredentialDialog.showDialog();
// if (result == JOptionPane.OK_OPTION) {
// String username = CredentialDialog.getNameField()
// .getText();
// String password = CredentialDialog.getPassField()
// .getText();
// return new UsernamePasswordCredentials(username,
// password);
// } else {
// // User pressed cancel.
// throw new CredentialsNotAvailableException(
// "Unsupported authentication scheme: "
// + authscheme.getSchemeName());
// }
//
// } else {
// throw new CredentialsNotAvailableException(
// "Unsupported authentication scheme: "
// + authscheme.getSchemeName());
// }
// } catch (IOException e) {
// throw new CredentialsNotAvailableException(e.getMessage(),
// e);
// }
// }
// }
// }
public static UsernamePasswordCredentials getCredentials(IFeed feed)
throws NetworkException {
// FeedCredentials fc = feed.getCredentials();
// UsernamePasswordCredentials credentials = null;
// if (fc != null) {
// credentials = new UsernamePasswordCredentials(fc.getName(), fc
// .getPassword());
// } else {
// Credentials are unknown, show a popup dialog.
// CB TODO Handover the UI portion to some other part
// of the code.
// int result = CredentialDialog.showDialog();
// if (result == JOptionPane.OK_OPTION) {
//
// // FIXME Migrate Authentication support.
// String username = ""; // CredentialDialog.getNameField().getText();
// String password = ""; // CredentialDialog.getPassField().getText();
//
// credentials = new UsernamePasswordCredentials(username,
// password);
// FeedCredentials lCredentials = ((XPersonalFeed) feed).new
// FeedCredentials(
// username, password);
// feed.setCredentials(lCredentials);
// } else {
// // User cancelled, throw exception, can not authenticate.
// throw new NetworkException("Authentication aborted.");
// }
// }
// return credentials;
return null;
}
}