package com.qubling.sidekick.fetch.other;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import com.qubling.sidekick.fetch.AbstractFetcher;
import com.qubling.sidekick.fetch.SerialUpdateFetcher;
import com.qubling.sidekick.fetch.UpdateFetcher;
import com.qubling.sidekick.instance.Gravatar;
import com.qubling.sidekick.model.Model;
import com.qubling.sidekick.search.ResultSet;
import com.qubling.sidekick.search.ResultsForUpdate;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
public class GravatarFetcher extends AbstractFetcher<Gravatar> implements UpdateFetcher<Gravatar> {
private float gravatarDpSize;
private int timeoutAbsolute;
private static final int TIMEOUT_CONNECTION = 2000;
private static final int TIMEOUT_SOCKET = 3000;
// private static final String GRAVATAR_TOOK_TOO_LONG = "Gravatar took too long";
// private static int requestCounter = 0;
public static final int DEFAULT_TIMEOUT_ABSOLUTE = 3100;
public GravatarFetcher(Model<Gravatar> model, float gravatarDpSize, int timeoutAbsolute) {
super(model);
this.gravatarDpSize = gravatarDpSize;
this.timeoutAbsolute = timeoutAbsolute;
}
public GravatarFetcher(Model<Gravatar> model, float gravatarDpSize) {
this(model, gravatarDpSize, DEFAULT_TIMEOUT_ABSOLUTE);
}
@Override
public boolean needsUpdate(Gravatar gravatar) {
// Log.d("GravatarFetcher", "Needs update? " + (gravatar.getBitmap() == null));
return gravatar.getBitmap() == null;
}
public float getGravatarDpSize() {
return gravatarDpSize;
}
public int getTimeoutAbsolute() {
return timeoutAbsolute;
}
@Override
protected void execute() {
// Log.d("GravatarFetcher", "START execute()");
// Calculate the pixel size of the Gravatar
Context context = getContext();
int gravatarPixelSize = Math.min(
(int) (gravatarDpSize * context.getResources().getDisplayMetrics().density + 0.5f),
512);
ResultSet<Gravatar> inputResults = getResultSet();
for (Gravatar gravatar : inputResults) {
try {
Bitmap bitmap = fetchBitmap(gravatar.getUrl(gravatarPixelSize));
gravatar.setBitmap(bitmap);
// Log.d("GravatarFetcher", "Fetched " + gravatar.getUrl(gravatarPixelSize));
}
catch (RuntimeException e) {
Log.e("GravatarFetcher", "error fetching Gravatar", e);
}
}
// Log.d("GravatarFetcher", "END execute()");
}
@Override
public void setIncomingResultSet(ResultsForUpdate<Gravatar> inputResults) {
setResultSet(inputResults);
}
private Bitmap fetchBitmap(final String gravatarURL) {
// try {
Timer timer = new Timer();
try {
// Make sure we don't get stuck waiting for a Gravatar
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_CONNECTION);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_SOCKET);
// Prepare the request
// Log.d("AuthorByDistributionSearch", "Gravatar: " + resizedGravatarURL);
HttpClient httpClient = getHttpClient();
final HttpGet req = new HttpGet(gravatarURL);
req.setParams(httpParams);
// Start the absolute timer for the request
// final int reqId = ++requestCounter;
// final Date ts = new Date();
timer.schedule(new TimerTask() {
@Override
public void run() {
// long elapsed = new Date().getTime() - ts.getTime();
// Log.w("GravatarFetcher", "Gravatar request #" + reqId + " took too long (" + elapsed + " �s), aborting fetch: " + resizedGravatarURL);
Log.w("GravatarFetcher", "Gravatar request took too long, aborting fetch: " + gravatarURL);
req.abort();
//throw new RuntimeException(GRAVATAR_TOOK_TOO_LONG);
}
}, timeoutAbsolute);
// Do the request
HttpResponse res = httpClient.execute(req);
// Cancel as soon as we have the response to avoid weird exceptions
timer.cancel();
// Get the response content
HttpEntity entity = res.getEntity();
InputStream content = entity.getContent();
Bitmap gravatarBitmap = BitmapFactory.decodeStream(content);
return gravatarBitmap;
}
catch (InterruptedIOException e) {
// No message, since this probably means Gravatar took too long
return null;
}
catch (IOException e) {
Log.e("GravatarFetcher", "Error loading Gravatar: " + e, e);
return null;
}
// During testing, I sometimes get an IllegalStateException: Connection is not open.
// This is a stupid exception and nearly any illegal state exception we can ignore by
// just not loading the Gravatar. The bitmap is not *that* important.
catch (IllegalStateException e) {
Log.e("GravatarFetcher", "Error fetching Gravatar: " + e, e);
return null;
}
// catch (RuntimeException e) {
// if (GRAVATAR_TOOK_TOO_LONG.equals(e.getMessage())) {
// return null;
// }
// else {
// throw e;
// }
// }
finally {
// Request is finished, stop the timer
// long elapsed = new Date().getTime() - ts.getTime();
// Log.d("GravatarFetcher", "Gravatar request #" + reqId + " finished executing request (" + elapsed + " �s)");
timer.cancel();
}
// }
// Guarantee that Gravatar took too long never escapes from here...
// catch (RuntimeException e) {
// if (GRAVATAR_TOOK_TOO_LONG.equals(e.getMessage())) {
// return null;
// }
// else {
// throw e;
// }
// }
}
public String toString() {
return getModel() + ":GravatarFetch(" + gravatarDpSize + ";" + getResultSet() + ")";
}
@Override
public SerialUpdateFetcher<Gravatar> thenDoFetch(UpdateFetcher<Gravatar> fetcher) {
return super.thenDoFetch(fetcher);
}
}