diff --git a/http/src/main/java/retrofit/http/Fetcher.java b/http/src/main/java/retrofit/http/Fetcher.java deleted file mode 100644 index 8f4d1f66e8b9ce2024244e2d49653f91ca062758..0000000000000000000000000000000000000000 --- a/http/src/main/java/retrofit/http/Fetcher.java +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 Square, Inc. -package retrofit.http; - -import org.apache.http.HttpEntity; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import retrofit.io.ByteSink; - -import javax.inject.Inject; -import javax.inject.Provider; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; -import java.text.DateFormat; -import java.util.Date; -import java.util.concurrent.Executor; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static retrofit.http.RestAdapter.DATE_FORMAT; - -/** - * Fetches URL contents to files. - * - * @author Bob Lee (bob@squareup.com) - */ -public class Fetcher { - private static final Logger LOGGER = Logger.getLogger(Fetcher.class.getName()); - - // TODO: Support conditional get. - - private final Provider httpClientProvider; - private final Executor executor; - private final MainThread mainThread; - - @Inject Fetcher(Provider httpClientProvider, Executor executor, MainThread mainThread) { - this.httpClientProvider = httpClientProvider; - this.executor = executor; - this.mainThread = mainThread; - } - - /** - * Fetches the contents of a URL to a file. - * - * @param url to fetch - * @param destination for download - * @param callback to invoke in the UI thread once the download completes - * @param progressListener listens for progress, can be null - */ - public void fetch(final String url, final ByteSink.Factory destination, Callback callback, - final ProgressListener progressListener) { - if (url == null) throw new NullPointerException("url"); - if (destination == null) throw new NullPointerException("destination"); - if (callback == null) throw new NullPointerException("callback"); - final HttpGet get = new HttpGet(url); - final UiCallback uiCallback = new UiCallback(callback, mainThread); - executor.execute(new Runnable() { - public void run() { - try { - DownloadHandler downloadHandler = - new DownloadHandler(url, destination, uiCallback, progressListener, mainThread, new Date(), DATE_FORMAT); - httpClientProvider.get().execute(get, downloadHandler); - } catch (IOException e) { - LOGGER.log(Level.WARNING, "fetch exception", e); - uiCallback.networkError(); - } catch (Throwable t) { - uiCallback.unexpectedError(t); - } - } - }); - } - - static class DownloadHandler extends CallbackResponseHandler { - /** Throttles how often we send progress updates. Specified in %. */ - private static final int PROGRESS_GRANULARITY = 5; - - private final ByteSink.Factory destination; - private final ProgressListener progressListener; - private final MainThread mainThread; - private final ProgressUpdate progressUpdate = new ProgressUpdate(); - - DownloadHandler(String url, ByteSink.Factory destination, UiCallback callback, - ProgressListener progressListener, MainThread mainThread, Date start, ThreadLocal dateFormat) { - super(callback, null, null, url, start, dateFormat); - this.destination = destination; - this.progressListener = progressListener; - this.mainThread = mainThread; - } - - @Override protected Object parse(HttpEntity entity, Type type) throws ConversionException { - try { - // Save the result to the sink instead of returning it. - InputStream in = entity.getContent(); - try { - ByteSink out = destination.newSink(); - final int total = (int) entity.getContentLength(); - int totalRead = 0; - try { - byte[] buffer = new byte[4096]; - int read; - while ((read = in.read(buffer)) != -1) { - out.write(buffer, read); - if (progressListener != null) { - totalRead += read; - int percent = totalRead * 100 / total; - if (percent - progressUpdate.percent > PROGRESS_GRANULARITY) { - progressUpdate.percent = percent; - mainThread.execute(progressUpdate); - } - } - } - } finally { - out.close(); - } - } finally { - in.close(); - } - } catch (IOException e) { - throw new ConversionException(e); - } - return null; - } - - /** Invokes ProgressListener in UI thread. */ - private class ProgressUpdate implements Runnable { - private volatile int percent; - public void run() { - progressListener.hearProgress(percent); - } - } - } -} diff --git a/http/src/main/java/retrofit/http/ProgressListener.java b/http/src/main/java/retrofit/http/ProgressListener.java deleted file mode 100644 index 7427ca45b20ba22828491460c7ea30d8dbe3c0d1..0000000000000000000000000000000000000000 --- a/http/src/main/java/retrofit/http/ProgressListener.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2010 Square, Inc. -package retrofit.http; - -/** - * Listens for progress. - * - * @author Bob Lee (bob@squareup.com) - */ -public interface ProgressListener { - - /** - * Hears a progress update. - * - * @param percent 0-100 - */ - void hearProgress(int percent); -} diff --git a/http/src/test/java/retrofit/http/FetcherTest.java b/http/src/test/java/retrofit/http/FetcherTest.java deleted file mode 100644 index cbddcff4398f4c1ee8836695be540fc99dfca53b..0000000000000000000000000000000000000000 --- a/http/src/test/java/retrofit/http/FetcherTest.java +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2010 Square, Inc. -package retrofit.http; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpUriRequest; -import org.junit.Test; -import retrofit.io.ByteSink; - -import javax.inject.Provider; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.concurrent.Executor; - -import static org.easymock.EasyMock.anyInt; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.fest.assertions.Assertions.assertThat; - -/** - * Fetcher test cases. - * - * @author Bob Lee (bob@squareup.com) - */ -public class FetcherTest { - - private static final String URL = "http://crazybob.org/"; - - private ByteSink.Factory sinkFactory = createMock(ByteSink.Factory.class); - private StatusLine statusLine = createMock(StatusLine.class); - private HttpEntity entity = createMock(HttpEntity.class); - private HttpResponse response = createMock(HttpResponse.class); - @SuppressWarnings("unchecked") - private Callback callback = createMock(Callback.class); - private ProgressListener progressListener - = createMock(ProgressListener.class); - - @Test public void testSuccessfulFetch() throws Exception { - DummyInputStream in = new DummyInputStream(); - final SingletonHttpClient httpClient = new SingletonHttpClient(response); - DummyExecutor executor = new DummyExecutor(); - DummyMainThread uiThread = new DummyMainThread(); - ArraySink sink = new ArraySink(); - - expect(response.getStatusLine()).andReturn(statusLine); - expect(statusLine.getStatusCode()).andReturn(200); - expect(response.getEntity()).andReturn(entity); - expect(entity.getContentLength()).andReturn(3L); - expect(entity.getContent()).andReturn(in); - expect(sinkFactory.newSink()).andReturn(sink); - progressListener.hearProgress(anyInt()); expectLastCall().atLeastOnce(); - callback.call(null); - - replayAll(); - - Fetcher fetcher = new Fetcher(new Provider() { - public HttpClient get() { - return httpClient; - } - }, executor, uiThread); - fetcher.fetch(URL, sinkFactory, callback, progressListener); - - verifyAll(); - assertThat(executor.calls).isEqualTo(1); - assertThat(uiThread.calls).isGreaterThan(1); // result + progress updates - assertThat(httpClient.calls).isEqualTo(1); - assertThat(sink.toArray()).isEqualTo(new byte[] { 1, 2, 3 }); - } - - private void replayAll() { - replay(sinkFactory, statusLine, entity, response, callback, - progressListener); - } - - private void verifyAll() { - verify(sinkFactory, statusLine, entity, response, callback, - progressListener); - } - - static class ArraySink implements ByteSink { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - boolean closed; - public void write(byte[] buffer, int count) throws IOException { - bout.write(buffer, 0, count); - } - public void close() throws IOException { - closed = true; - } - public byte[] toArray() { - return bout.toByteArray(); - } - } - - /** Returns { 1, 2, 3 }, 1 byte at a time. */ - static class DummyInputStream extends InputStream { - int count; - @Override public int read(byte[] b) throws IOException { - if (count++ == 3) return -1; - Arrays.fill(b, 0, 1, (byte) count); - return 1; - } - @Override public int read() throws IOException { - throw new UnsupportedOperationException(); - } - } - - static class DummyExecutor implements Executor { - int calls; - public void execute(Runnable command) { - calls++; - command.run(); - } - } - - static class DummyMainThread extends DummyExecutor implements MainThread { - public void executeDelayed(Runnable r, long delay) { - throw new UnsupportedOperationException(); - } - - public void executeSynchronously(Runnable r) { - throw new UnsupportedOperationException(); - } - - @Override public void executeOnMain(Runnable r) { - throw new UnsupportedOperationException(); - } - - public void cancel(Runnable r) { - throw new UnsupportedOperationException(); - } - } - - /** An HttpClient that returns one response. */ - private class SingletonHttpClient extends DummyHttpClient { - private final HttpResponse response; - public SingletonHttpClient(HttpResponse response) { - this.response = response; - } - int calls; - public T execute(HttpUriRequest request, - ResponseHandler responseHandler) throws IOException { - calls++; - assertThat(request.getURI().toString()).isEqualTo(FetcherTest.URL); - T t = responseHandler.handleResponse(response); - assertThat(t).isNull(); - return t; - } - } -}