Extracts configurable networking layer.

* Extracts HttpEngine interface.
* Uses LwHttp as default networking client.
* Implements alternate networking client using OkHttp.
This commit is contained in:
Chuck Greb 2014-03-28 03:29:24 -04:00 committed by Hannes Janetzek
parent 9bca50dfed
commit af7d70cfd8
11 changed files with 264 additions and 9 deletions

View File

@ -5,11 +5,16 @@ configurations { providedCompile }
dependencies { dependencies {
compile 'org.slf4j:slf4j-api:1.7.6' compile 'org.slf4j:slf4j-api:1.7.6'
compile 'com.squareup.okhttp:okhttp:1.5.2'
providedCompile 'com.google.code.findbugs:annotations:2.0.1' providedCompile 'com.google.code.findbugs:annotations:2.0.1'
testCompile 'junit:junit:4.11'
testCompile 'org.mockito:mockito-all:1.9.5'
testCompile 'org.easytesting:fest-assert-core:2.0M10'
} }
sourceSets { sourceSets {
main.java.srcDirs = ['src'] main.java.srcDirs = ['src']
test.java.srcDirs = ['test']
main.resources.srcDirs = ['resources'] main.resources.srcDirs = ['resources']
main.compileClasspath += configurations.providedCompile main.compileClasspath += configurations.providedCompile
} }

View File

@ -0,0 +1,19 @@
package org.oscim.tiling.source;
import org.oscim.core.Tile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface HttpEngine {
InputStream read() throws IOException;
boolean sendRequest(UrlTileSource tileSource, Tile tile) throws IOException;
void close();
void setCache(OutputStream os);
boolean requestCompleted(boolean success);
}

View File

@ -36,11 +36,8 @@ import org.slf4j.LoggerFactory;
/** /**
* Lightweight HTTP connection for tile loading. Does not do redirects, * Lightweight HTTP connection for tile loading. Does not do redirects,
* https, full header parsing or stuff. * https, full header parsing or stuff.
*
* TODO extract API interface to be used by UrlTileSource so that one
* could also use HttpUrlConnection, etc.
*/ */
public class LwHttp { public class LwHttp implements HttpEngine {
static final Logger log = LoggerFactory.getLogger(LwHttp.class); static final Logger log = LoggerFactory.getLogger(LwHttp.class);
static final boolean dbg = false; static final boolean dbg = false;
@ -332,6 +329,7 @@ public class LwHttp {
return is; return is;
} }
@Override
public boolean sendRequest(UrlTileSource tileSource, Tile tile) throws IOException { public boolean sendRequest(UrlTileSource tileSource, Tile tile) throws IOException {
if (mSocket != null) { if (mSocket != null) {
@ -405,6 +403,7 @@ public class LwHttp {
return true; return true;
} }
@Override
public void close() { public void close() {
if (mSocket == null) if (mSocket == null)
return; return;
@ -415,6 +414,7 @@ public class LwHttp {
mResponseStream = null; mResponseStream = null;
} }
@Override
public void setCache(OutputStream os) { public void setCache(OutputStream os) {
if (mResponseStream == null) if (mResponseStream == null)
return; return;
@ -422,6 +422,7 @@ public class LwHttp {
mResponseStream.setCache(os); mResponseStream.setCache(os);
} }
@Override
public boolean requestCompleted(boolean success) { public boolean requestCompleted(boolean success) {
if (mResponseStream == null) if (mResponseStream == null)
return false; return false;

View File

@ -0,0 +1,70 @@
package org.oscim.tiling.source;
import com.squareup.okhttp.OkHttpClient;
import org.oscim.core.Tile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class OkHttpEngine implements HttpEngine {
private final URL baseUrl;
private final OkHttpClient client;
private InputStream inputStream;
public OkHttpEngine(URL baseUrl) {
this.baseUrl = baseUrl;
this.client = new OkHttpClient();
}
@Override
public InputStream read() throws IOException {
return inputStream;
}
@Override
public boolean sendRequest(UrlTileSource tileSource, Tile tile) throws IOException {
final URL requestUrl = new URL(baseUrl.toString()
+ "/"
+ Byte.toString(tile.zoomLevel)
+ "/"
+ tile.tileX
+ "/"
+ tile.tileY
+ ".vtm");
final HttpURLConnection connection = client.open(requestUrl);
try {
inputStream = connection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
public void close() {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void setCache(OutputStream os) {
// TODO: Evaluate OkHttp response cache and determine if additional caching is required.
}
@Override
public boolean requestCompleted(boolean success) {
return true;
}
}

View File

@ -38,12 +38,12 @@ import org.slf4j.LoggerFactory;
public class UrlTileDataSource implements ITileDataSource { public class UrlTileDataSource implements ITileDataSource {
static final Logger log = LoggerFactory.getLogger(UrlTileDataSource.class); static final Logger log = LoggerFactory.getLogger(UrlTileDataSource.class);
protected final LwHttp mConn; protected final HttpEngine mConn;
protected final ITileDecoder mTileDecoder; protected final ITileDecoder mTileDecoder;
protected final UrlTileSource mTileSource; protected final UrlTileSource mTileSource;
protected final boolean mUseCache; protected final boolean mUseCache;
public UrlTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder, LwHttp conn) { public UrlTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder, HttpEngine conn) {
mTileDecoder = tileDecoder; mTileDecoder = tileDecoder;
mTileSource = tileSource; mTileSource = tileSource;
mUseCache = (tileSource.tileCache != null); mUseCache = (tileSource.tileCache != null);

View File

@ -26,6 +26,7 @@ public abstract class UrlTileSource extends TileSource {
private final URL mUrl; private final URL mUrl;
private byte[] mExt; private byte[] mExt;
private HttpEngine httpEngine;
public UrlTileSource(String urlString) { public UrlTileSource(String urlString) {
URL url = null; URL url = null;
@ -107,4 +108,16 @@ public abstract class UrlTileSource extends TileSource {
public URL getUrl() { public URL getUrl() {
return mUrl; return mUrl;
} }
public void setHttpEngine(HttpEngine httpEngine) {
this.httpEngine = httpEngine;
}
public HttpEngine getHttpEngine() {
if (httpEngine == null) {
httpEngine = new LwHttp(getUrl());
}
return httpEngine;
}
} }

View File

@ -32,7 +32,7 @@ public class BitmapTileSource extends UrlTileSource {
@Override @Override
public ITileDataSource getDataSource() { public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new BitmapTileDecoder(), new LwHttp(getUrl())); return new UrlTileDataSource(this, new BitmapTileDecoder(), getHttpEngine());
} }
public class BitmapTileDecoder implements ITileDecoder { public class BitmapTileDecoder implements ITileDecoder {

View File

@ -17,7 +17,6 @@
package org.oscim.tiling.source.oscimap4; package org.oscim.tiling.source.oscimap4;
import org.oscim.tiling.ITileDataSource; import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.source.LwHttp;
import org.oscim.tiling.source.UrlTileDataSource; import org.oscim.tiling.source.UrlTileDataSource;
import org.oscim.tiling.source.UrlTileSource; import org.oscim.tiling.source.UrlTileSource;
@ -34,6 +33,6 @@ public class OSciMap4TileSource extends UrlTileSource {
@Override @Override
public ITileDataSource getDataSource() { public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), new LwHttp(getUrl())); return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
} }
} }

View File

@ -0,0 +1,58 @@
package org.oscim.tiling.source;
import com.squareup.okhttp.OkHttpClient;
import org.junit.Before;
import org.junit.Test;
import org.oscim.tiling.ITileDataSource;
import static org.fest.assertions.api.Assertions.assertThat;
public class UrlTileSourceTest {
private UrlTileSource tileSource;
@Before
public void setUp() throws Exception {
tileSource = new TestTileSource("http://example.org/tiles/vtm");
}
@Test
public void shouldNotBeNull() throws Exception {
assertThat(tileSource).isNotNull();
}
@Test
public void shouldUseDefaultHttpEngine() throws Exception {
TestTileDataSource dataSource = (TestTileDataSource) tileSource.getDataSource();
assertThat(dataSource.getConnection()).isInstanceOf(LwHttp.class);
}
@Test
public void shouldUseCustomHttpEngine() throws Exception {
tileSource.setHttpEngine(new OkHttpEngine(tileSource.getUrl()));
TestTileDataSource dataSource = (TestTileDataSource) tileSource.getDataSource();
assertThat(dataSource.getConnection()).isInstanceOf(OkHttpEngine.class);
}
class TestTileSource extends UrlTileSource {
public TestTileSource(String urlString) {
super(urlString);
}
@Override
public ITileDataSource getDataSource() {
return new TestTileDataSource(this, null, getHttpEngine());
}
}
class TestTileDataSource extends UrlTileDataSource {
public TestTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder,
HttpEngine conn) {
super(tileSource, tileDecoder, conn);
}
public HttpEngine getConnection() {
return mConn;
}
}
}

View File

@ -0,0 +1,48 @@
package org.oscim.tiling.source.bitmap;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.source.LwHttp;
import org.oscim.tiling.source.OkHttpEngine;
import static org.fest.assertions.api.Assertions.assertThat;
public class BitmapTileSourceTest {
private BitmapTileSource tileSource;
@Before
public void setUp() throws Exception {
tileSource = new TestBitmapTileSource("http://tile.openstreetmap.org", 0, 18);
}
@Test
public void shouldNotBeNull() throws Exception {
assertThat(tileSource).isNotNull();
}
@Test
public void shouldUseLwHttp() throws Exception {
LwHttp lwHttp = Mockito.mock(LwHttp.class);
tileSource.setHttpEngine(lwHttp);
ITileDataSource dataSource = tileSource.getDataSource();
dataSource.destroy();
Mockito.verify(lwHttp).close();
}
@Test
public void shouldUseOkHttp() throws Exception {
OkHttpEngine okHttp = Mockito.mock(OkHttpEngine.class);
tileSource.setHttpEngine(okHttp);
ITileDataSource dataSource = tileSource.getDataSource();
dataSource.destroy();
Mockito.verify(okHttp).close();
}
class TestBitmapTileSource extends BitmapTileSource {
public TestBitmapTileSource(String url, int zoomMin, int zoomMax) {
super(url, zoomMin, zoomMax);
}
}
}

View File

@ -0,0 +1,42 @@
package org.oscim.tiling.source.oscimap4;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.source.LwHttp;
import org.oscim.tiling.source.OkHttpEngine;
import static org.fest.assertions.api.Assertions.assertThat;
public class OSciMap4TileSourceTest {
private OSciMap4TileSource tileSource;
@Before
public void setUp() throws Exception {
tileSource = new OSciMap4TileSource("http://www.example.org/tiles/vtm");
}
@Test
public void shouldNotBeNull() throws Exception {
assertThat(tileSource).isNotNull();
}
@Test
public void shouldUseLwHttp() throws Exception {
LwHttp lwHttp = Mockito.mock(LwHttp.class);
tileSource.setHttpEngine(lwHttp);
ITileDataSource dataSource = tileSource.getDataSource();
dataSource.destroy();
Mockito.verify(lwHttp).close();
}
@Test
public void shouldUseOkHttp() throws Exception {
OkHttpEngine okHttp = Mockito.mock(OkHttpEngine.class);
tileSource.setHttpEngine(okHttp);
ITileDataSource dataSource = tileSource.getDataSource();
dataSource.destroy();
Mockito.verify(okHttp).close();
}
}