package com.nutiteq.task;
import java.io.IOException;
import java.io.InputStream;
import com.nutiteq.cache.Cache;
import com.nutiteq.components.MapTile;
import com.nutiteq.io.ResourceDataWaiter;
import com.nutiteq.io.ResourceRequestor;
import com.nutiteq.io.ResourceStreamWaiter;
import com.nutiteq.listeners.ErrorListener;
import com.nutiteq.log.Log;
import com.nutiteq.net.DataPostingDownloadable;
import com.nutiteq.net.DownloadCounter;
import com.nutiteq.net.DownloadStreamOpener;
import com.nutiteq.net.DownloadStreamWaiter;
import com.nutiteq.net.StreamedTilesDownloadable;
import com.nutiteq.utils.IOUtils;
public class RetrieveNetworkResourceTask extends NetworkTask implements DownloadStreamWaiter {
private final ResourceRequestor downloadable;
private final ErrorListener errorListener;
private Cache networkCache;
private String downloadableUrl;
public RetrieveNetworkResourceTask(final ResourceRequestor downloadable,
final ErrorListener errorListener, final int cacheLevel) {
this.downloadable = downloadable;
this.errorListener = errorListener;
}
public void execute() {
execute(getDownloadStreamOpener(), getNetworkCache(), getDownloadCounter());
}
private void execute(final DownloadStreamOpener opener, final Cache networkCache,
final DownloadCounter downloadCounter) {
this.networkCache = networkCache;
downloadableUrl = downloadable.resourcePath();
if (downloadableUrl == null || "".equals(downloadableUrl)) {
Log.error("Null or empty url from downloadable!");
downloadable.notifyError();
return;
}
//TODO jaanus : check also if resource has caching value
final byte[] cacheData = networkCache == null ? null : networkCache.get(downloadableUrl);
if (cacheData != null && downloadable instanceof ResourceDataWaiter) {
if (downloadCounter != null) {
downloadCounter.cacheHit(downloadableUrl, cacheData.length);
}
((ResourceDataWaiter) downloadable).dataRetrieved(cacheData);
} else if (downloadable instanceof DataPostingDownloadable) {
opener.openInputStream(this, (DataPostingDownloadable) downloadable);
} else {
// TODO jaanus : handle download separator
opener.openInputStream(this, downloadableUrl);
}
}
public void streamOpened(final InputStream stream) throws IOException {
final DownloadCounter downloadCounter = getDownloadCounter();
if (downloadCounter != null) {
downloadCounter.networkRequest(downloadableUrl);
}
if (downloadable instanceof ResourceStreamWaiter) {
((ResourceStreamWaiter) downloadable).streamOpened(stream, downloadCounter, networkCache);
} else {
final byte[] downloadedData = IOUtils.readFully(stream);
if (networkCache != null) {
networkCache.cache(downloadableUrl, downloadedData, downloadable.getCachingLevel());
}
if (downloadCounter != null) {
downloadCounter.downloaded(downloadedData.length);
}
((ResourceDataWaiter) downloadable).dataRetrieved(downloadedData);
}
if (downloadCounter != null) {
downloadCounter.downloadCompleted();
}
}
public void error(final int errorCode, final String message) {
Log.error("Network error "+errorCode+ " : "+message);
if (getDownloadCounter() != null) {
getDownloadCounter().downloadCompleted();
}
//TODO jaanus : this can't be normal
//error handling for tiles is done outside
if (downloadable instanceof MapTile || downloadable instanceof StreamedTilesDownloadable) {
return;
}
downloadable.notifyError();
if (errorListener != null) {
switch (errorCode) {
case DownloadStreamOpener.NETWORK_ERROR:
errorListener.networkError("Network error: " + message);
return;
case DownloadStreamOpener.RESPONCE_NOT_OK:
errorListener.networkError("Response code was not 200");
return;
case DownloadStreamOpener.SECURITY_EXCEPTION:
errorListener.networkError("Security exception: " + message);
return;
case DownloadStreamOpener.TOO_MANY_REDIRECTS:
errorListener.networkError("Redirects: " + message);
return;
}
}
}
public ResourceRequestor getDownloadable() {
return downloadable;
}
public void notifyError() {
downloadable.notifyError();
}
}