Merge branch 'pluggable-network-layer'
This commit is contained in:
commit
ca69f329cc
@ -1,4 +1,5 @@
|
|||||||
include ':vtm'
|
include ':vtm'
|
||||||
|
include ':vtm-tests'
|
||||||
include ':vtm-extras'
|
include ':vtm-extras'
|
||||||
include ':vtm-android'
|
include ':vtm-android'
|
||||||
include ':vtm-android-example'
|
include ':vtm-android-example'
|
||||||
|
@ -22,27 +22,29 @@ import java.util.Map;
|
|||||||
import org.oscim.core.MapElement;
|
import org.oscim.core.MapElement;
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
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;
|
||||||
|
|
||||||
public abstract class GeoJsonTileSource extends UrlTileSource {
|
public abstract class GeoJsonTileSource extends UrlTileSource {
|
||||||
|
|
||||||
public GeoJsonTileSource(String url) {
|
public GeoJsonTileSource(String url) {
|
||||||
super(url);
|
super(url, "/{Z}/{X}/{Y}.json");
|
||||||
setExtension(".json");
|
Map<String, String> opt = new HashMap<String, String>();
|
||||||
|
opt.put("Accept-Encoding", "gzip");
|
||||||
|
setHttpRequestHeaders(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeoJsonTileSource(String url, int zoomMin, int zoomMax) {
|
public GeoJsonTileSource(String url, int zoomMin, int zoomMax) {
|
||||||
super(url, zoomMin, zoomMax);
|
super(url, "/{Z}/{X}/{Y}.json", zoomMin, zoomMax);
|
||||||
setExtension(".json");
|
Map<String, String> opt = new HashMap<String, String>();
|
||||||
|
opt.put("Accept-Encoding", "gzip");
|
||||||
|
setHttpRequestHeaders(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITileDataSource getDataSource() {
|
public ITileDataSource getDataSource() {
|
||||||
Map<String, String> opt = new HashMap<String, String>();
|
|
||||||
opt.put("Accept-Encoding", "gzip");
|
return new UrlTileDataSource(this, new GeoJsonTileDecoder(this), getHttpEngine());
|
||||||
return new UrlTileDataSource(this, new GeoJsonTileDecoder(this), new LwHttp(getUrl(), opt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tag getFeatureTag() {
|
public Tag getFeatureTag() {
|
||||||
|
@ -18,40 +18,41 @@ package org.oscim.tiling.source.mapnik;
|
|||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
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;
|
||||||
|
|
||||||
public class MapnikVectorTileSource extends UrlTileSource {
|
public class MapnikVectorTileSource extends UrlTileSource {
|
||||||
|
|
||||||
public MapnikVectorTileSource() {
|
public MapnikVectorTileSource() {
|
||||||
super("http://d1s11ojcu7opje.cloudfront.net/dev/764e0b8d");
|
super("http://d1s11ojcu7opje.cloudfront.net/dev/764e0b8d", "");
|
||||||
|
setUrlFormatter(new TileUrlFormatter() {
|
||||||
|
@Override
|
||||||
|
public String formatTilePath(UrlTileSource tileSource, Tile tile) {
|
||||||
|
// url formatter for mapbox streets
|
||||||
|
byte[] hexTable = {
|
||||||
|
'0', '1', '2', '3',
|
||||||
|
'4', '5', '6', '7',
|
||||||
|
'8', '9', 'a', 'b',
|
||||||
|
'c', 'd', 'e', 'f'
|
||||||
|
};
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append('/');
|
||||||
|
sb.append(hexTable[(tile.tileX) % 16]);
|
||||||
|
sb.append(hexTable[(tile.tileY) % 16]);
|
||||||
|
sb.append('/');
|
||||||
|
sb.append(tile.zoomLevel);
|
||||||
|
sb.append('/');
|
||||||
|
sb.append(tile.tileX);
|
||||||
|
sb.append('/');
|
||||||
|
sb.append(tile.tileY);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITileDataSource getDataSource() {
|
public ITileDataSource getDataSource() {
|
||||||
return new UrlTileDataSource(this, new TileDecoder(), new LwHttp(getUrl()));
|
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
|
||||||
}
|
|
||||||
|
|
||||||
public int formatTilePath(Tile tile, byte[] path, int pos) {
|
|
||||||
// url formatter for mapbox streets
|
|
||||||
byte[] hexTable = {
|
|
||||||
'0', '1', '2', '3',
|
|
||||||
'4', '5', '6', '7',
|
|
||||||
'8', '9', 'a', 'b',
|
|
||||||
'c', 'd', 'e', 'f'
|
|
||||||
};
|
|
||||||
|
|
||||||
path[pos++] = '/';
|
|
||||||
path[pos++] = hexTable[(tile.tileX) % 16];
|
|
||||||
path[pos++] = hexTable[(tile.tileY) % 16];
|
|
||||||
path[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.zoomLevel, pos, path);
|
|
||||||
path[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.tileX, pos, path);
|
|
||||||
path[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.tileY, pos, path);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package org.oscim.tiling.source.oscimap;
|
package org.oscim.tiling.source.oscimap;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -28,13 +27,11 @@ import org.oscim.tiling.source.UrlTileSource;
|
|||||||
public class OSciMap1TileSource extends UrlTileSource {
|
public class OSciMap1TileSource extends UrlTileSource {
|
||||||
|
|
||||||
public OSciMap1TileSource(String url) {
|
public OSciMap1TileSource(String url) {
|
||||||
super(url);
|
super(url, "/{Z}/{X}/{Y}.osmtile");
|
||||||
setExtension(".osmtile");
|
|
||||||
setMimeType("application/osmtile");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITileDataSource getDataSource() {
|
public ITileDataSource getDataSource() {
|
||||||
return new UrlTileDataSource(this, new TileDecoder(), new LwHttp(getUrl()));
|
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import org.oscim.core.TagSet;
|
|||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.tiling.ITileDataSink;
|
import org.oscim.tiling.ITileDataSink;
|
||||||
import org.oscim.tiling.ITileDataSource;
|
import org.oscim.tiling.ITileDataSource;
|
||||||
import org.oscim.tiling.source.LwHttp;
|
|
||||||
import org.oscim.tiling.source.PbfDecoder;
|
import org.oscim.tiling.source.PbfDecoder;
|
||||||
import org.oscim.tiling.source.UrlTileDataSource;
|
import org.oscim.tiling.source.UrlTileDataSource;
|
||||||
import org.oscim.tiling.source.UrlTileSource;
|
import org.oscim.tiling.source.UrlTileSource;
|
||||||
@ -37,14 +36,12 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class OSciMap2TileSource extends UrlTileSource {
|
public class OSciMap2TileSource extends UrlTileSource {
|
||||||
|
|
||||||
public OSciMap2TileSource(String url) {
|
public OSciMap2TileSource(String url) {
|
||||||
super(url);
|
super(url, "/{Z}/{X}/{Y}.osmtile");
|
||||||
setExtension(".osmtile");
|
|
||||||
setMimeType("application/osmtile");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITileDataSource getDataSource() {
|
public ITileDataSource getDataSource() {
|
||||||
return new UrlTileDataSource(this, new TileDecoder(), new LwHttp(getUrl()));
|
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TileDecoder extends PbfDecoder {
|
static class TileDecoder extends PbfDecoder {
|
||||||
|
16
vtm-tests/build.gradle
Normal file
16
vtm-tests/build.gradle
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'maven'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':vtm')
|
||||||
|
compile 'com.squareup.okhttp:okhttp:1.5.2'
|
||||||
|
testCompile 'junit:junit:4.11'
|
||||||
|
testCompile 'org.mockito:mockito-all:1.9.5'
|
||||||
|
testCompile 'org.easytesting:fest-assert-core:2.0M10'
|
||||||
|
testCompile 'com.squareup.okhttp:mockwebserver:1.5.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs = ['src']
|
||||||
|
test.java.srcDirs = ['test']
|
||||||
|
}
|
93
vtm-tests/test/org/oscim/tiling/source/OkHttpEngineTest.java
Normal file
93
vtm-tests/test/org/oscim/tiling/source/OkHttpEngineTest.java
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package org.oscim.tiling.source;
|
||||||
|
|
||||||
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||||
|
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||||
|
import com.squareup.okhttp.mockwebserver.RecordedRequest;
|
||||||
|
|
||||||
|
public class OkHttpEngineTest {
|
||||||
|
private OkHttpEngine engine;
|
||||||
|
private MockWebServer server;
|
||||||
|
private MockResponse mockResponse;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mockResponse = new MockResponse();
|
||||||
|
mockResponse.setBody("TEST RESPONSE".getBytes());
|
||||||
|
server = new MockWebServer();
|
||||||
|
server.enqueue(mockResponse);
|
||||||
|
server.play();
|
||||||
|
engine = (OkHttpEngine) new OkHttpEngine.OkHttpFactory()
|
||||||
|
.create(new OSciMap4TileSource(server.getUrl("/tiles/vtm").toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
server.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotBeNull() throws Exception {
|
||||||
|
assertThat(engine).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void sendRequest_shouldRejectNullTile() throws Exception {
|
||||||
|
engine.sendRequest(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendRequest_shouldAppendXYZToPath() throws Exception {
|
||||||
|
engine.sendRequest(new Tile(1, 2, new Integer(3).byteValue()));
|
||||||
|
|
||||||
|
RecordedRequest request = server.takeRequest();
|
||||||
|
assertThat(request.getPath()).isEqualTo("/tiles/vtm/3/1/2.vtm");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read_shouldReturnResponseStream() throws Exception {
|
||||||
|
engine.sendRequest(new Tile(1, 2, new Integer(3).byteValue()));
|
||||||
|
|
||||||
|
InputStream responseStream = engine.read();
|
||||||
|
String response = new BufferedReader(new InputStreamReader(responseStream)).readLine();
|
||||||
|
assertThat(response).isEqualTo("TEST RESPONSE");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IOException.class)
|
||||||
|
public void close_shouldCloseInputStream() throws Exception {
|
||||||
|
engine.sendRequest(new Tile(1, 2, new Integer(3).byteValue()));
|
||||||
|
engine.close();
|
||||||
|
|
||||||
|
// Calling read after the stream is closed should throw an exception.
|
||||||
|
InputStream responseStream = engine.read();
|
||||||
|
responseStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IOException.class)
|
||||||
|
public void requestCompleted_shouldCloseInputStream() throws Exception {
|
||||||
|
engine.sendRequest(new Tile(1, 2, new Integer(3).byteValue()));
|
||||||
|
engine.requestCompleted(true);
|
||||||
|
|
||||||
|
// Calling read after the stream is closed should throw an exception.
|
||||||
|
InputStream responseStream = engine.read();
|
||||||
|
responseStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestCompleted_shouldReturnValueGiven() throws Exception {
|
||||||
|
assertThat(engine.requestCompleted(true)).isTrue();
|
||||||
|
assertThat(engine.requestCompleted(false)).isFalse();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package org.oscim.tiling.source;
|
||||||
|
|
||||||
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.oscim.tiling.ITileDataSource;
|
||||||
|
|
||||||
|
public class UrlTileSourceTest {
|
||||||
|
private UrlTileSource tileSource;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
tileSource = new TestTileSource("http://example.org/tiles/vtm", "/{Z}/{X}/{Z}.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.OkHttpFactory());
|
||||||
|
TestTileDataSource dataSource = (TestTileDataSource) tileSource.getDataSource();
|
||||||
|
assertThat(dataSource.getConnection()).isInstanceOf(OkHttpEngine.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestTileSource extends UrlTileSource {
|
||||||
|
public TestTileSource(String urlString, String tilePath) {
|
||||||
|
super(urlString, tilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.oscim.tiling.source.bitmap;
|
||||||
|
|
||||||
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.oscim.tiling.ITileDataSource;
|
||||||
|
import org.oscim.tiling.source.HttpEngine;
|
||||||
|
import org.oscim.tiling.source.LwHttp;
|
||||||
|
import org.oscim.tiling.source.OkHttpEngine;
|
||||||
|
import org.oscim.tiling.source.UrlTileDataSource;
|
||||||
|
import org.oscim.tiling.source.UrlTileSource;
|
||||||
|
|
||||||
|
public class BitmapTileSourceTest {
|
||||||
|
private BitmapTileSource tileSource;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
tileSource = new BitmapTileSource("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(new TestHttpFactory(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(new TestHttpFactory(okHttp));
|
||||||
|
UrlTileDataSource dataSource = (UrlTileDataSource) tileSource.getDataSource();
|
||||||
|
dataSource.destroy();
|
||||||
|
Mockito.verify(okHttp).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test factory that allows the specific {@link HttpEngine} instance to be
|
||||||
|
* set.
|
||||||
|
*/
|
||||||
|
class TestHttpFactory implements HttpEngine.Factory {
|
||||||
|
final HttpEngine engine;
|
||||||
|
|
||||||
|
public TestHttpFactory(HttpEngine engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpEngine create(UrlTileSource tileSource) {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package org.oscim.tiling.source.oscimap4;
|
||||||
|
|
||||||
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.oscim.tiling.ITileDataSource;
|
||||||
|
import org.oscim.tiling.source.HttpEngine;
|
||||||
|
import org.oscim.tiling.source.LwHttp;
|
||||||
|
import org.oscim.tiling.source.OkHttpEngine;
|
||||||
|
import org.oscim.tiling.source.UrlTileSource;
|
||||||
|
|
||||||
|
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(new TestHttpFactory(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(new TestHttpFactory(okHttp));
|
||||||
|
ITileDataSource dataSource = tileSource.getDataSource();
|
||||||
|
dataSource.destroy();
|
||||||
|
Mockito.verify(okHttp).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test factory that allows the specific {@link HttpEngine} instance to be
|
||||||
|
* set.
|
||||||
|
*/
|
||||||
|
class TestHttpFactory implements HttpEngine.Factory {
|
||||||
|
final HttpEngine engine;
|
||||||
|
|
||||||
|
public TestHttpFactory(HttpEngine engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpEngine create(UrlTileSource tileSource) {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,10 @@ package org.oscim.tiling.source;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.layers.tile.MapTile;
|
||||||
|
|
||||||
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
|
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
|
||||||
import com.google.gwt.typedarrays.shared.Uint8Array;
|
import com.google.gwt.typedarrays.shared.Uint8Array;
|
||||||
@ -26,20 +27,15 @@ import com.google.gwt.xhr.client.ReadyStateChangeHandler;
|
|||||||
import com.google.gwt.xhr.client.XMLHttpRequest;
|
import com.google.gwt.xhr.client.XMLHttpRequest;
|
||||||
import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;
|
import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;
|
||||||
|
|
||||||
public class LwHttp {
|
public class LwHttp implements HttpEngine {
|
||||||
//static final Logger log = LoggerFactory.getLogger(LwHttp.class);
|
//static final Logger log = LoggerFactory.getLogger(LwHttp.class);
|
||||||
|
|
||||||
private final String mUrlPath;
|
|
||||||
private final byte[] mRequestBuffer;
|
|
||||||
|
|
||||||
private int mContentLength = -1;
|
|
||||||
private XMLHttpRequest mHttpRequest;
|
private XMLHttpRequest mHttpRequest;
|
||||||
|
|
||||||
private ReadyStateChangeHandler mResponseHandler;
|
private ReadyStateChangeHandler mResponseHandler;
|
||||||
|
|
||||||
public LwHttp(URL url) {
|
public LwHttp(UrlTileSource tileSource) {
|
||||||
mUrlPath = url.toString();
|
mTileSource = tileSource;
|
||||||
mRequestBuffer = new byte[1024];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Buffer extends InputStream {
|
static class Buffer extends InputStream {
|
||||||
@ -63,21 +59,18 @@ public class LwHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (mHttpRequest != null)
|
if (mHttpRequest == null)
|
||||||
mHttpRequest.abort();
|
return;
|
||||||
|
|
||||||
|
mHttpRequest.abort();
|
||||||
|
mHttpRequest = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UrlTileDataSource mDataSource;
|
private UrlTileSource mTileSource;
|
||||||
|
|
||||||
public boolean sendRequest(Tile tile, UrlTileDataSource dataSource) throws IOException {
|
public void sendRequest(MapTile tile, final UrlTileDataSource dataSource) {
|
||||||
mDataSource = dataSource;
|
|
||||||
|
|
||||||
byte[] request = mRequestBuffer;
|
String url = mTileSource.getTileUrl(tile);
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
pos = dataSource.getTileSource().formatTilePath(tile, request, pos);
|
|
||||||
|
|
||||||
String url = mUrlPath + (new String(request, 0, pos));
|
|
||||||
|
|
||||||
mHttpRequest = XMLHttpRequest.create();
|
mHttpRequest = XMLHttpRequest.create();
|
||||||
mHttpRequest.open("GET", url);
|
mHttpRequest.open("GET", url);
|
||||||
@ -91,63 +84,46 @@ public class LwHttp {
|
|||||||
//log.debug(mCurrentUrl + "response " + status + "/" + state);
|
//log.debug(mCurrentUrl + "response " + status + "/" + state);
|
||||||
|
|
||||||
if (state == XMLHttpRequest.DONE) {
|
if (state == XMLHttpRequest.DONE) {
|
||||||
|
if (xhr.getStatus() == 200) {
|
||||||
int status = xhr.getStatus();
|
|
||||||
|
|
||||||
if (status == 200) {
|
|
||||||
Uint8Array buf = Uint8ArrayNative.create(xhr.getResponseArrayBuffer());
|
Uint8Array buf = Uint8ArrayNative.create(xhr.getResponseArrayBuffer());
|
||||||
|
dataSource.process(new Buffer(buf));
|
||||||
mDataSource.process(new Buffer(buf));
|
|
||||||
} else {
|
} else {
|
||||||
mDataSource.process(null);
|
dataSource.process(null);
|
||||||
}
|
}
|
||||||
|
mHttpRequest = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mHttpRequest.setOnReadyStateChange(mResponseHandler);
|
mHttpRequest.setOnReadyStateChange(mResponseHandler);
|
||||||
mHttpRequest.send();
|
mHttpRequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LwHttpFactory implements HttpEngine.Factory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpEngine create(UrlTileSource tileSource) {
|
||||||
|
return new LwHttp(tileSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream read() throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCache(OutputStream os) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestCompleted(boolean success) {
|
||||||
|
// mHttpRequest.clearOnReadyStateChange();
|
||||||
|
// mHttpRequest = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write (positive) integer to byte array
|
@Override
|
||||||
protected static int writeInt(int val, int pos, byte[] buf) {
|
public void sendRequest(Tile tile) throws IOException {
|
||||||
if (val == 0) {
|
|
||||||
buf[pos] = '0';
|
|
||||||
return pos + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (int n = val; n > 0; n = n / 10, i++)
|
|
||||||
buf[pos + i] = (byte) ('0' + n % 10);
|
|
||||||
|
|
||||||
// reverse bytes
|
|
||||||
for (int j = pos, end = pos + i - 1, mid = pos + i / 2; j < mid; j++, end--) {
|
|
||||||
byte tmp = buf[j];
|
|
||||||
buf[j] = buf[end];
|
|
||||||
buf[end] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse (positive) integer from byte array
|
|
||||||
protected static int parseInt(byte[] buf, int pos, int end) {
|
|
||||||
int val = 0;
|
|
||||||
for (; pos < end; pos++)
|
|
||||||
val = val * 10 + (buf[pos]) - '0';
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestCompleted() {
|
|
||||||
|
|
||||||
mHttpRequest.clearOnReadyStateChange();
|
|
||||||
mHttpRequest = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContentLength() {
|
|
||||||
return mContentLength;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,65 +35,52 @@ public class UrlTileDataSource implements ITileDataSource {
|
|||||||
protected final ITileDecoder mTileDecoder;
|
protected final ITileDecoder mTileDecoder;
|
||||||
protected final UrlTileSource mTileSource;
|
protected final UrlTileSource mTileSource;
|
||||||
|
|
||||||
public UrlTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder, LwHttp conn) {
|
|
||||||
mTileSource = tileSource;
|
|
||||||
mTileDecoder = tileDecoder;
|
|
||||||
mConn = conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
UrlTileSource getTileSource() {
|
|
||||||
return mTileSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ITileDataSink mSink;
|
private ITileDataSink mSink;
|
||||||
private MapTile mTile;
|
private MapTile mTile;
|
||||||
|
|
||||||
|
public UrlTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder, HttpEngine conn) {
|
||||||
|
mTileSource = tileSource;
|
||||||
|
mTileDecoder = tileDecoder;
|
||||||
|
mConn = (LwHttp) conn;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void query(MapTile tile, ITileDataSink sink) {
|
public void query(MapTile tile, ITileDataSink sink) {
|
||||||
mTile = tile;
|
mTile = tile;
|
||||||
mSink = sink;
|
mSink = sink;
|
||||||
try {
|
mConn.sendRequest(tile, this);
|
||||||
mConn.sendRequest(tile, this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
///e.printStackTrace();
|
|
||||||
log.error("{} {}", mTile, e.getMessage());
|
|
||||||
sink.completed(FAILED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(final InputStream is) {
|
public void process(final InputStream is) {
|
||||||
TileLoader.postLoadDelay(new LoadDelayTask<InputStream>(mTile, mSink, is) {
|
if (is == null) {
|
||||||
|
log.debug("{} no inputstream", mTile);
|
||||||
|
mSink.completed(FAILED);
|
||||||
|
mTile = null;
|
||||||
|
mSink = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileLoader.postLoadDelay(new LoadDelayTask<InputStream>(mTile, mSink, is) {
|
||||||
@Override
|
@Override
|
||||||
public void continueLoading() {
|
public void continueLoading() {
|
||||||
|
boolean win = false;
|
||||||
if (tile.state(MapTile.State.LOADING)) {
|
if (tile.state(MapTile.State.LOADING)) {
|
||||||
boolean win = false;
|
try {
|
||||||
if (is != null) {
|
win = mTileDecoder.decode(tile, sink, data);
|
||||||
try {
|
} catch (IOException e) {
|
||||||
win = mTileDecoder.decode(tile, sink, data);
|
e.printStackTrace();
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!win)
|
|
||||||
log.debug("{} failed", tile);
|
|
||||||
|
|
||||||
// FIXME
|
|
||||||
mConn.requestCompleted();
|
|
||||||
|
|
||||||
sink.completed(win ? SUCCESS : FAILED);
|
|
||||||
} else {
|
|
||||||
// FIXME
|
|
||||||
mConn.requestCompleted();
|
|
||||||
sink.completed(FAILED);
|
|
||||||
}
|
}
|
||||||
|
if (win) {
|
||||||
mTile = null;
|
sink.completed(SUCCESS);
|
||||||
mSink = null;
|
} else {
|
||||||
|
sink.completed(FAILED);
|
||||||
|
log.debug("{} decode failed", tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mTile = null;
|
||||||
|
mSink = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,9 +31,17 @@ public class BitmapTileSource extends UrlTileSource {
|
|||||||
* Use e.g. setExtension(".jpg") to overide ending or
|
* Use e.g. setExtension(".jpg") to overide ending or
|
||||||
* implement getUrlString() for custom formatting.
|
* implement getUrlString() for custom formatting.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public BitmapTileSource(String url, int zoomMin, int zoomMax) {
|
public BitmapTileSource(String url, int zoomMin, int zoomMax) {
|
||||||
super(url, zoomMin, zoomMax);
|
super(url, "/{Z}/{X}/{Y}.png", zoomMin, zoomMax);
|
||||||
setExtension(".png");
|
}
|
||||||
|
|
||||||
|
public BitmapTileSource(String url, int zoomMin, int zoomMax, String extension) {
|
||||||
|
super(url, "/{Z}/{X}/{Y}" + extension, zoomMin, zoomMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapTileSource(String url, String tilePath, int zoomMin, int zoomMax) {
|
||||||
|
super(url, tilePath, zoomMin, zoomMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,10 +49,9 @@ public class BitmapTileSource extends UrlTileSource {
|
|||||||
return new BitmapTileDataSource(this);
|
return new BitmapTileDataSource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BitmapTileDataSource implements ITileDataSource {
|
public class BitmapTileDataSource implements ITileDataSource {
|
||||||
|
|
||||||
protected final UrlTileSource mTileSource;
|
protected final UrlTileSource mTileSource;
|
||||||
private final byte[] mRequestBuffer = new byte[1024];
|
|
||||||
|
|
||||||
public BitmapTileDataSource(BitmapTileSource bitmapTileSource) {
|
public BitmapTileDataSource(BitmapTileSource bitmapTileSource) {
|
||||||
mTileSource = bitmapTileSource;
|
mTileSource = bitmapTileSource;
|
||||||
@ -53,10 +60,7 @@ public class BitmapTileSource extends UrlTileSource {
|
|||||||
@Override
|
@Override
|
||||||
public void query(final MapTile tile, final ITileDataSink sink) {
|
public void query(final MapTile tile, final ITileDataSink sink) {
|
||||||
|
|
||||||
int pos = mTileSource.formatTilePath(tile, mRequestBuffer, 0);
|
String url = mTileSource.getTileUrl(tile);
|
||||||
|
|
||||||
String url = mTileSource.getUrl()
|
|
||||||
+ (new String(mRequestBuffer, 0, pos));
|
|
||||||
|
|
||||||
SafeUri uri = UriUtils.fromTrustedString(url);
|
SafeUri uri = UriUtils.fromTrustedString(url);
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@ public abstract class GeoJsonTileSource extends UrlTileSource {
|
|||||||
static final Logger log = LoggerFactory.getLogger(GeoJsonTileSource.class);
|
static final Logger log = LoggerFactory.getLogger(GeoJsonTileSource.class);
|
||||||
|
|
||||||
public GeoJsonTileSource(String url) {
|
public GeoJsonTileSource(String url) {
|
||||||
super(url);
|
super(url, "/{Z}/{X}/{Y}.json");
|
||||||
setExtension(".json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,8 +41,6 @@ public class JsonTileDataSource implements ITileDataSource {
|
|||||||
protected final GeoJsonTileDecoder mTileDecoder;
|
protected final GeoJsonTileDecoder mTileDecoder;
|
||||||
protected final UrlTileSource mTileSource;
|
protected final UrlTileSource mTileSource;
|
||||||
|
|
||||||
private final byte[] mRequestBuffer = new byte[1024];
|
|
||||||
|
|
||||||
public JsonTileDataSource(GeoJsonTileSource tileSource) {
|
public JsonTileDataSource(GeoJsonTileSource tileSource) {
|
||||||
mTileSource = tileSource;
|
mTileSource = tileSource;
|
||||||
mTileDecoder = new GeoJsonTileDecoder(tileSource);
|
mTileDecoder = new GeoJsonTileDecoder(tileSource);
|
||||||
@ -61,12 +59,7 @@ public class JsonTileDataSource implements ITileDataSource {
|
|||||||
mSink = sink;
|
mSink = sink;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int pos = mTileSource.formatTilePath(tile, mRequestBuffer, 0);
|
doGet(mTileSource.getTileUrl(tile));
|
||||||
|
|
||||||
String url = mTileSource.getUrl()
|
|
||||||
+ (new String(mRequestBuffer, 0, pos));
|
|
||||||
|
|
||||||
doGet(url);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
sink.completed(FAILED);
|
sink.completed(FAILED);
|
||||||
|
@ -5,6 +5,7 @@ configurations { providedCompile }
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'org.slf4j:slf4j-api:1.7.6'
|
compile 'org.slf4j:slf4j-api:1.7.6'
|
||||||
|
providedCompile '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'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
vtm/src/org/oscim/tiling/source/HttpEngine.java
Normal file
41
vtm/src/org/oscim/tiling/source/HttpEngine.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.tiling.source;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
|
||||||
|
public interface HttpEngine {
|
||||||
|
|
||||||
|
InputStream read() throws IOException;
|
||||||
|
|
||||||
|
void sendRequest(Tile tile) throws IOException;
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void setCache(OutputStream os);
|
||||||
|
|
||||||
|
boolean requestCompleted(boolean success);
|
||||||
|
|
||||||
|
public interface Factory {
|
||||||
|
HttpEngine create(UrlTileSource tileSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package org.oscim.tiling.source;
|
package org.oscim.tiling.source;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -24,7 +24,6 @@ import java.net.InetSocketAddress;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
@ -35,17 +34,13 @@ 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 other 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;
|
||||||
|
|
||||||
private final static byte[] HEADER_HTTP_OK = "200 OK".getBytes();
|
private final static byte[] HEADER_HTTP_OK = "200 OK".getBytes();
|
||||||
//private final static byte[] HEADER_CONTENT_TYPE = "Content-Type".getBytes();
|
|
||||||
private final static byte[] HEADER_CONTENT_LENGTH = "Content-Length".getBytes();
|
private final static byte[] HEADER_CONTENT_LENGTH = "Content-Length".getBytes();
|
||||||
private final static byte[] HEADER_CONNECTION_CLOSE = "Connection: close".getBytes();
|
private final static byte[] HEADER_CONNECTION_CLOSE = "Connection: close".getBytes();
|
||||||
|
|
||||||
@ -58,7 +53,7 @@ public class LwHttp {
|
|||||||
private final String mHost;
|
private final String mHost;
|
||||||
private final int mPort;
|
private final int mPort;
|
||||||
|
|
||||||
private int mMaxReq = 0;
|
private int mMaxRequests = 0;
|
||||||
private Socket mSocket;
|
private Socket mSocket;
|
||||||
private OutputStream mCommandStream;
|
private OutputStream mCommandStream;
|
||||||
private Buffer mResponseStream;
|
private Buffer mResponseStream;
|
||||||
@ -72,39 +67,33 @@ public class LwHttp {
|
|||||||
private final byte[] REQUEST_GET_END;
|
private final byte[] REQUEST_GET_END;
|
||||||
private final byte[] mRequestBuffer;
|
private final byte[] mRequestBuffer;
|
||||||
|
|
||||||
/**
|
private final byte[][] mTilePath;
|
||||||
* @param url
|
private final UrlTileSource mTileSource;
|
||||||
* Base url for tiles
|
|
||||||
*/
|
|
||||||
public LwHttp(URL url) {
|
|
||||||
this(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LwHttp(URL url, Map<String, String> header) {
|
private LwHttp(UrlTileSource tileSource, byte[][] tilePath) {
|
||||||
|
mTilePath = tilePath;
|
||||||
|
mTileSource = tileSource;
|
||||||
|
|
||||||
|
URL url = tileSource.getUrl();
|
||||||
int port = url.getPort();
|
int port = url.getPort();
|
||||||
if (port < 0)
|
if (port < 0)
|
||||||
port = 80;
|
port = 80;
|
||||||
|
|
||||||
String host = url.getHost();
|
String host = url.getHost();
|
||||||
String path = url.getPath();
|
String path = url.getPath();
|
||||||
log.debug("open database: " + host + " " + port + " " + path);
|
//log.debug("open database: {} {} {}", host, port, path);
|
||||||
|
|
||||||
REQUEST_GET_START = ("GET " + path).getBytes();
|
REQUEST_GET_START = ("GET " + path).getBytes();
|
||||||
|
|
||||||
String addRequest = "";
|
StringBuilder opt = new StringBuilder();
|
||||||
if (header != null) {
|
for (Entry<String, String> l : tileSource.getRequestHeader().entrySet())
|
||||||
StringBuffer sb = new StringBuffer();
|
opt.append('\n').append(l.getKey()).append(": ").append(l.getValue());
|
||||||
for (Entry<String, String> l : header.entrySet())
|
|
||||||
sb.append('\n').append(l.getKey()).append(": ").append(l.getValue());
|
|
||||||
addRequest = sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
REQUEST_GET_END = (" HTTP/1.1" +
|
REQUEST_GET_END = (" HTTP/1.1" +
|
||||||
"\nUser-Agent: vtm/0.5.9" +
|
"\nUser-Agent: vtm/0.5.9" +
|
||||||
"\nHost: " + host +
|
"\nHost: " + host +
|
||||||
"\nConnection: Keep-Alive" +
|
"\nConnection: Keep-Alive" +
|
||||||
addRequest +
|
opt.toString() +
|
||||||
"\n\n").getBytes();
|
"\n\n").getBytes();
|
||||||
|
|
||||||
mHost = host;
|
mHost = host;
|
||||||
@ -115,10 +104,7 @@ public class LwHttp {
|
|||||||
mRequestBuffer, 0, REQUEST_GET_START.length);
|
mRequestBuffer, 0, REQUEST_GET_START.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
static final class Buffer extends BufferedInputStream {
|
||||||
// to avoid a copy in PbfDecoder one could manage the buffer
|
|
||||||
// array directly and provide access to it.
|
|
||||||
static class Buffer extends BufferedInputStream {
|
|
||||||
OutputStream cache;
|
OutputStream cache;
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
int bytesWrote;
|
int bytesWrote;
|
||||||
@ -198,6 +184,7 @@ public class LwHttp {
|
|||||||
|
|
||||||
if (marked >= 0)
|
if (marked >= 0)
|
||||||
bytesRead = marked;
|
bytesRead = marked;
|
||||||
|
|
||||||
/* TODO could check if the mark is already invalid */
|
/* TODO could check if the mark is already invalid */
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
@ -212,9 +199,6 @@ public class LwHttp {
|
|||||||
if (data >= 0)
|
if (data >= 0)
|
||||||
bytesRead += 1;
|
bytesRead += 1;
|
||||||
|
|
||||||
//if (dbg)
|
|
||||||
// log.debug("read {} {}", bytesRead, contentLength);
|
|
||||||
|
|
||||||
if (cache != null && bytesRead > bytesWrote) {
|
if (cache != null && bytesRead > bytesWrote) {
|
||||||
bytesWrote = bytesRead;
|
bytesWrote = bytesRead;
|
||||||
cache.write(data);
|
cache.write(data);
|
||||||
@ -289,27 +273,21 @@ public class LwHttp {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (ok) {
|
||||||
/* ignore until end of header */
|
if (first) {
|
||||||
} else if (first) {
|
first = false;
|
||||||
first = false;
|
/* check only for OK ("HTTP/1.? ".length == 9) */
|
||||||
/* check only for OK ("HTTP/1.? ".length == 9) */
|
if (!check(HEADER_HTTP_OK, buf, pos + 9, end))
|
||||||
if (!check(HEADER_HTTP_OK, buf, pos + 9, end))
|
ok = false;
|
||||||
ok = false;
|
|
||||||
|
|
||||||
} else if (check(HEADER_CONTENT_LENGTH, buf, pos, end)) {
|
} else if (check(HEADER_CONTENT_LENGTH, buf, pos, end)) {
|
||||||
/* parse Content-Length */
|
/* parse Content-Length */
|
||||||
contentLength = parseInt(buf, pos +
|
contentLength = parseInt(buf, pos +
|
||||||
HEADER_CONTENT_LENGTH.length + 2, end - 1);
|
HEADER_CONTENT_LENGTH.length + 2, end - 1);
|
||||||
} else if (check(HEADER_CONNECTION_CLOSE, buf, pos, end)) {
|
} else if (check(HEADER_CONNECTION_CLOSE, buf, pos, end)) {
|
||||||
mMustClose = true;
|
mMustClose = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//} else if (check(HEADER_CONTENT_TYPE, buf, pos, end)) {
|
|
||||||
// check that response contains the expected
|
|
||||||
// Content-Type
|
|
||||||
//if (!check(mContentType, buf, pos +
|
|
||||||
// HEADER_CONTENT_TYPE.length + 2, end))
|
|
||||||
// ok = false;
|
|
||||||
|
|
||||||
if (!ok || dbg) {
|
if (!ok || dbg) {
|
||||||
String line = new String(buf, pos, end - pos - 1);
|
String line = new String(buf, pos, end - pos - 1);
|
||||||
@ -332,17 +310,20 @@ public class LwHttp {
|
|||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean sendRequest(UrlTileSource tileSource, Tile tile) throws IOException {
|
@Override
|
||||||
|
public void sendRequest(Tile tile) throws IOException {
|
||||||
|
|
||||||
if (mSocket != null) {
|
if (mSocket != null) {
|
||||||
if (mMaxReq-- <= 0)
|
if (--mMaxRequests < 0)
|
||||||
close();
|
close();
|
||||||
else if (System.nanoTime() - mLastRequest > RESPONSE_TIMEOUT)
|
else if (System.nanoTime() - mLastRequest > RESPONSE_TIMEOUT)
|
||||||
close();
|
close();
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
if (mResponseStream.available() > 0)
|
if (mResponseStream.available() > 0) {
|
||||||
|
log.debug("still bytes available");
|
||||||
close();
|
close();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
close();
|
close();
|
||||||
@ -355,36 +336,32 @@ public class LwHttp {
|
|||||||
lwHttpConnect();
|
lwHttpConnect();
|
||||||
|
|
||||||
/* TODO parse from header */
|
/* TODO parse from header */
|
||||||
mMaxReq = RESPONSE_EXPECTED_LIVES;
|
mMaxRequests = RESPONSE_EXPECTED_LIVES;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] request = mRequestBuffer;
|
|
||||||
int pos = REQUEST_GET_START.length;
|
int pos = REQUEST_GET_START.length;
|
||||||
|
|
||||||
pos = tileSource.formatTilePath(tile, request, pos);
|
|
||||||
|
|
||||||
int len = REQUEST_GET_END.length;
|
int len = REQUEST_GET_END.length;
|
||||||
System.arraycopy(REQUEST_GET_END, 0, request, pos, len);
|
|
||||||
|
pos = formatTilePath(tile, mRequestBuffer, pos);
|
||||||
|
System.arraycopy(REQUEST_GET_END, 0, mRequestBuffer, pos, len);
|
||||||
len += pos;
|
len += pos;
|
||||||
|
|
||||||
if (dbg)
|
if (dbg)
|
||||||
log.debug("request: {}", new String(request, 0, len));
|
log.debug("request: {}", new String(mRequestBuffer, 0, len));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mCommandStream.write(request, 0, len);
|
writeRequest(mRequestBuffer, len);
|
||||||
mCommandStream.flush();
|
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.debug("recreate connection");
|
log.debug("recreate connection");
|
||||||
close();
|
close();
|
||||||
/* might throw IOException */
|
|
||||||
lwHttpConnect();
|
lwHttpConnect();
|
||||||
|
writeRequest(mRequestBuffer, len);
|
||||||
mCommandStream.write(request, 0, len);
|
|
||||||
mCommandStream.flush();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
private void writeRequest(byte[] request, int length) throws IOException {
|
||||||
|
mCommandStream.write(request, 0, length);
|
||||||
|
mCommandStream.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean lwHttpConnect() throws IOException {
|
private boolean lwHttpConnect() throws IOException {
|
||||||
@ -405,6 +382,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 +393,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 +401,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;
|
||||||
@ -430,15 +410,6 @@ public class LwHttp {
|
|||||||
mResponseStream.setCache(null);
|
mResponseStream.setCache(null);
|
||||||
|
|
||||||
if (!mResponseStream.finishedReading()) {
|
if (!mResponseStream.finishedReading()) {
|
||||||
// StringBuffer sb = new StringBuffer();
|
|
||||||
// try {
|
|
||||||
// int val;
|
|
||||||
// while ((val = mResponseStream.read()) >= 0)
|
|
||||||
// sb.append((char) val);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//log.debug("invalid buffer position {}", sb.toString());
|
|
||||||
log.debug("invalid buffer position");
|
log.debug("invalid buffer position");
|
||||||
close();
|
close();
|
||||||
return true;
|
return true;
|
||||||
@ -458,7 +429,7 @@ public class LwHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** write (positive) integer to byte array */
|
/** write (positive) integer to byte array */
|
||||||
public static int writeInt(int val, int pos, byte[] buf) {
|
private static int writeInt(int val, int pos, byte[] buf) {
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
buf[pos] = '0';
|
buf[pos] = '0';
|
||||||
return pos + 1;
|
return pos + 1;
|
||||||
@ -474,7 +445,7 @@ public class LwHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** parse (positive) integer from byte array */
|
/** parse (positive) integer from byte array */
|
||||||
protected static int parseInt(byte[] buf, int pos, int end) {
|
private static int parseInt(byte[] buf, int pos, int end) {
|
||||||
int val = 0;
|
int val = 0;
|
||||||
for (; pos < end; pos++)
|
for (; pos < end; pos++)
|
||||||
val = val * 10 + (buf[pos]) - '0';
|
val = val * 10 + (buf[pos]) - '0';
|
||||||
@ -496,4 +467,61 @@ public class LwHttp {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tile the Tile
|
||||||
|
* @param buf to write url string
|
||||||
|
* @param pos current position
|
||||||
|
* @return new position
|
||||||
|
*/
|
||||||
|
private int formatTilePath(Tile tile, byte[] buf, int pos) {
|
||||||
|
if (mTilePath == null) {
|
||||||
|
String url = mTileSource.getUrlFormatter()
|
||||||
|
.formatTilePath(mTileSource, tile);
|
||||||
|
byte[] b = url.getBytes();
|
||||||
|
System.arraycopy(b, 0, buf, pos, b.length);
|
||||||
|
return pos + b.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (byte[] b : mTilePath) {
|
||||||
|
if (b.length == 1) {
|
||||||
|
if (b[0] == '/') {
|
||||||
|
buf[pos++] = '/';
|
||||||
|
continue;
|
||||||
|
} else if (b[0] == 'X') {
|
||||||
|
pos = writeInt(tile.tileX, pos, buf);
|
||||||
|
continue;
|
||||||
|
} else if (b[0] == 'Y') {
|
||||||
|
pos = writeInt(tile.tileY, pos, buf);
|
||||||
|
continue;
|
||||||
|
} else if (b[0] == 'Z') {
|
||||||
|
pos = writeInt(tile.zoomLevel, pos, buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.arraycopy(b, 0, buf, pos, b.length);
|
||||||
|
pos += b.length;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LwHttpFactory implements HttpEngine.Factory {
|
||||||
|
private byte[][] mTilePath;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpEngine create(UrlTileSource tileSource) {
|
||||||
|
if (tileSource.getUrlFormatter() != UrlTileSource.URL_FORMATTER)
|
||||||
|
return new LwHttp(tileSource, null);
|
||||||
|
|
||||||
|
/* use optimized formatter replacing the default */
|
||||||
|
if (mTilePath == null) {
|
||||||
|
String[] path = tileSource.getTilePath();
|
||||||
|
mTilePath = new byte[path.length][];
|
||||||
|
for (int i = 0; i < path.length; i++)
|
||||||
|
mTilePath[i] = path[i].getBytes();
|
||||||
|
}
|
||||||
|
return new LwHttp(tileSource, mTilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
90
vtm/src/org/oscim/tiling/source/OkHttpEngine.java
Normal file
90
vtm/src/org/oscim/tiling/source/OkHttpEngine.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Charles Greb
|
||||||
|
* Copyright 2014 Hannes Janetzek
|
||||||
|
*
|
||||||
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.tiling.source;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.utils.IOUtils;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
|
|
||||||
|
public class OkHttpEngine implements HttpEngine {
|
||||||
|
private final OkHttpClient mClient;
|
||||||
|
private final UrlTileSource mTileSource;
|
||||||
|
|
||||||
|
public static class OkHttpFactory implements HttpEngine.Factory {
|
||||||
|
private final OkHttpClient mClient;
|
||||||
|
|
||||||
|
public OkHttpFactory() {
|
||||||
|
mClient = new OkHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpEngine create(UrlTileSource tileSource) {
|
||||||
|
return new OkHttpEngine(mClient, tileSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream inputStream;
|
||||||
|
|
||||||
|
public OkHttpEngine(OkHttpClient client, UrlTileSource tileSource) {
|
||||||
|
mClient = client;
|
||||||
|
mTileSource = tileSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream read() throws IOException {
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendRequest(Tile tile) throws IOException {
|
||||||
|
if (tile == null) {
|
||||||
|
throw new IllegalArgumentException("Tile cannot be null.");
|
||||||
|
}
|
||||||
|
URL url = new URL(mTileSource.getTileUrl(tile));
|
||||||
|
HttpURLConnection conn = mClient.open(url);
|
||||||
|
|
||||||
|
for (Entry<String, String> opt : mTileSource.getRequestHeader().entrySet())
|
||||||
|
conn.addRequestProperty(opt.getKey(), opt.getValue());
|
||||||
|
|
||||||
|
inputStream = conn.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
IOUtils.closeQuietly(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCache(OutputStream os) {
|
||||||
|
// TODO: Evaluate OkHttp response cache and determine if additional caching is required.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestCompleted(boolean success) {
|
||||||
|
close();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
@ -74,10 +74,9 @@ public class UrlTileDataSource implements ITileDataSource {
|
|||||||
boolean success = false;
|
boolean success = false;
|
||||||
TileWriter cacheWriter = null;
|
TileWriter cacheWriter = null;
|
||||||
try {
|
try {
|
||||||
InputStream is;
|
mConn.sendRequest(tile);
|
||||||
if (!mConn.sendRequest(mTileSource, tile)) {
|
InputStream is = mConn.read();
|
||||||
log.debug("{} Request failed", tile);
|
if (is == null) {
|
||||||
} else if ((is = mConn.read()) == null) {
|
|
||||||
log.debug("{} Network Error", tile);
|
log.debug("{} Network Error", tile);
|
||||||
} else {
|
} else {
|
||||||
if (mUseCache) {
|
if (mUseCache) {
|
||||||
|
@ -18,29 +18,51 @@ package org.oscim.tiling.source;
|
|||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.tiling.TileSource;
|
import org.oscim.tiling.TileSource;
|
||||||
|
import org.oscim.tiling.source.LwHttp.LwHttpFactory;
|
||||||
|
|
||||||
public abstract class UrlTileSource extends TileSource {
|
public abstract class UrlTileSource extends TileSource {
|
||||||
|
|
||||||
|
public final static TileUrlFormatter URL_FORMATTER = new DefaultTileUrlFormatter();
|
||||||
private final URL mUrl;
|
private final URL mUrl;
|
||||||
private byte[] mExt;
|
private final String[] mTilePath;
|
||||||
|
|
||||||
|
private HttpEngine.Factory mHttpFactory;
|
||||||
|
private Map<String, String> mRequestHeaders = Collections.emptyMap();
|
||||||
|
private TileUrlFormatter mTileUrlFormatter = URL_FORMATTER;
|
||||||
|
|
||||||
|
public interface TileUrlFormatter {
|
||||||
|
public String formatTilePath(UrlTileSource tileSource, Tile tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UrlTileSource(String url, String tilePath, int zoomMin, int zoomMax) {
|
||||||
|
this(url, tilePath);
|
||||||
|
mZoomMin = zoomMin;
|
||||||
|
mZoomMax = zoomMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param urlString 'http://example.com/'
|
||||||
|
* @param tilePath replacement string for tile coordinates,
|
||||||
|
* e.g. '{Z}/{X}/{Y}.png'
|
||||||
|
*/
|
||||||
|
public UrlTileSource(String urlString, String tilePath) {
|
||||||
|
|
||||||
|
if (tilePath == null)
|
||||||
|
throw new IllegalArgumentException("tilePath cannot be null.");
|
||||||
|
|
||||||
public UrlTileSource(String urlString) {
|
|
||||||
URL url = null;
|
URL url = null;
|
||||||
try {
|
try {
|
||||||
url = new URL(urlString);
|
url = new URL(urlString);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
e.printStackTrace();
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
}
|
mTilePath = tilePath.split("\\{|\\}");
|
||||||
|
|
||||||
public UrlTileSource(String url, int zoomMin, int zoomMax) {
|
|
||||||
this(url);
|
|
||||||
mZoomMin = zoomMin;
|
|
||||||
mZoomMax = zoomMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,58 +75,72 @@ public abstract class UrlTileSource extends TileSource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setExtension(String ext) {
|
|
||||||
if (ext == null) {
|
|
||||||
mExt = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mExt = ext.getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setMimeType(String string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create url path for tile
|
|
||||||
*/
|
|
||||||
protected String getTileUrl(Tile tile) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write tile url - the low level, no-allocations method,
|
|
||||||
*
|
|
||||||
* override getTileUrl() for custom url formatting using
|
|
||||||
* Strings
|
|
||||||
*
|
|
||||||
* @param tile the Tile
|
|
||||||
* @param buf to write url string
|
|
||||||
* @param pos current position
|
|
||||||
* @return new position
|
|
||||||
*/
|
|
||||||
public int formatTilePath(Tile tile, byte[] buf, int pos) {
|
|
||||||
String p = getTileUrl(tile);
|
|
||||||
if (p != null) {
|
|
||||||
byte[] b = p.getBytes();
|
|
||||||
System.arraycopy(b, 0, buf, pos, b.length);
|
|
||||||
return pos + b.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.zoomLevel, pos, buf);
|
|
||||||
buf[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.tileX, pos, buf);
|
|
||||||
buf[pos++] = '/';
|
|
||||||
pos = LwHttp.writeInt(tile.tileY, pos, buf);
|
|
||||||
if (mExt == null)
|
|
||||||
return pos;
|
|
||||||
|
|
||||||
System.arraycopy(mExt, 0, buf, pos, mExt.length);
|
|
||||||
return pos + mExt.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public URL getUrl() {
|
public URL getUrl() {
|
||||||
return mUrl;
|
return mUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTileUrl(Tile tile) {
|
||||||
|
return mUrl + mTileUrlFormatter.formatTilePath(this, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpEngine(HttpEngine.Factory httpFactory) {
|
||||||
|
mHttpFactory = httpFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpRequestHeaders(Map<String, String> options) {
|
||||||
|
mRequestHeaders = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRequestHeader() {
|
||||||
|
return mRequestHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getTilePath() {
|
||||||
|
return mTilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setUrlFormatter(TileUrlFormatter formatter) {
|
||||||
|
mTileUrlFormatter = formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileUrlFormatter getUrlFormatter() {
|
||||||
|
return mTileUrlFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpEngine getHttpEngine() {
|
||||||
|
if (mHttpFactory == null) {
|
||||||
|
mHttpFactory = new LwHttpFactory();
|
||||||
|
}
|
||||||
|
return mHttpFactory.create(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DefaultTileUrlFormatter implements TileUrlFormatter {
|
||||||
|
@Override
|
||||||
|
public String formatTilePath(UrlTileSource tileSource, Tile tile) {
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String b : tileSource.getTilePath()) {
|
||||||
|
if (b.length() == 1) {
|
||||||
|
switch (b.charAt(0)) {
|
||||||
|
case 'X':
|
||||||
|
sb.append(tile.tileX);
|
||||||
|
continue;
|
||||||
|
case 'Y':
|
||||||
|
sb.append(tile.tileY);
|
||||||
|
continue;
|
||||||
|
case 'Z':
|
||||||
|
sb.append(tile.zoomLevel);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(b);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,20 @@ public class BitmapTileSource extends UrlTileSource {
|
|||||||
* implement getUrlString() for custom formatting.
|
* implement getUrlString() for custom formatting.
|
||||||
*/
|
*/
|
||||||
public BitmapTileSource(String url, int zoomMin, int zoomMax) {
|
public BitmapTileSource(String url, int zoomMin, int zoomMax) {
|
||||||
super(url, zoomMin, zoomMax);
|
super(url, "/{Z}/{X}/{Y}.png", zoomMin, zoomMax);
|
||||||
setExtension(".png");
|
}
|
||||||
|
|
||||||
|
public BitmapTileSource(String url, int zoomMin, int zoomMax, String extension) {
|
||||||
|
super(url, "/{Z}/{X}/{Y}" + extension, zoomMin, zoomMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapTileSource(String url, String tilePath, int zoomMin, int zoomMax) {
|
||||||
|
super(url, tilePath, zoomMin, zoomMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.oscim.tiling.source.bitmap;
|
package org.oscim.tiling.source.bitmap;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
import org.oscim.layers.tile.bitmap.BitmapTileLayer.FadeStep;
|
import org.oscim.layers.tile.bitmap.BitmapTileLayer.FadeStep;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,15 +34,13 @@ public class DefaultSources {
|
|||||||
|
|
||||||
public static class ImagicoLandcover extends BitmapTileSource {
|
public static class ImagicoLandcover extends BitmapTileSource {
|
||||||
public ImagicoLandcover() {
|
public ImagicoLandcover() {
|
||||||
super("http://www.imagico.de/map/tiles/landcover", 0, 6);
|
super("http://www.imagico.de/map/tiles/landcover", 0, 6, ".jpg");
|
||||||
setExtension(".jpg");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MapQuestAerial extends BitmapTileSource {
|
public static class MapQuestAerial extends BitmapTileSource {
|
||||||
public MapQuestAerial() {
|
public MapQuestAerial() {
|
||||||
super("http://otile1.mqcdn.com/tiles/1.0.0/sat", 0, 8);
|
super("http://otile1.mqcdn.com/tiles/1.0.0/sat", 0, 8, ".jpg");
|
||||||
setExtension(".jpg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -64,38 +61,17 @@ public class DefaultSources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ArcGISWorldShaded extends BitmapTileSource {
|
public static class ArcGISWorldShaded extends BitmapTileSource {
|
||||||
private final StringBuilder sb = new StringBuilder(32);
|
|
||||||
|
|
||||||
public ArcGISWorldShaded() {
|
public ArcGISWorldShaded() {
|
||||||
super("http://server.arcgisonline.com/ArcGIS/rest/services", 0, 13);
|
super("http://server.arcgisonline.com/ArcGIS/rest/services" +
|
||||||
}
|
"/World_Shaded_Relief/MapServer/tile/",
|
||||||
|
"{Z}/{Y}/{X}", 0, 13);
|
||||||
@Override
|
|
||||||
public synchronized String getTileUrl(Tile tile) {
|
|
||||||
sb.setLength(0);
|
|
||||||
//sb.append("/World_Imagery/MapServer/tile/");
|
|
||||||
sb.append("/World_Shaded_Relief/MapServer/tile/");
|
|
||||||
sb.append(tile.zoomLevel);
|
|
||||||
sb.append('/').append(tile.tileY);
|
|
||||||
sb.append('/').append(tile.tileX);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HillShadeHD extends BitmapTileSource {
|
public static class HillShadeHD extends BitmapTileSource {
|
||||||
private final StringBuilder sb = new StringBuilder(32);
|
|
||||||
|
|
||||||
public HillShadeHD() {
|
public HillShadeHD() {
|
||||||
super("http://129.206.74.245:8004/tms_hs.ashx", 2, 16);
|
super("http://129.206.74.245:8004/tms_hs.ashx",
|
||||||
}
|
"?x={X}&y={Y}&z={Z}", 2, 16);
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String getTileUrl(Tile tile) {
|
|
||||||
sb.setLength(0);
|
|
||||||
sb.append("?x=").append(tile.tileX);
|
|
||||||
sb.append("&y=").append(tile.tileY);
|
|
||||||
sb.append("&z=").append(tile.zoomLevel);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,23 +80,8 @@ public class DefaultSources {
|
|||||||
* https://developers.google.com/maps/faq
|
* https://developers.google.com/maps/faq
|
||||||
*/
|
*/
|
||||||
public static class GoogleMaps extends BitmapTileSource {
|
public static class GoogleMaps extends BitmapTileSource {
|
||||||
private final StringBuilder sb = new StringBuilder(60);
|
|
||||||
|
|
||||||
public GoogleMaps(String hostName) {
|
public GoogleMaps(String hostName) {
|
||||||
super(hostName, 1, 20); //jpeg for sat
|
super(hostName, "/vt/x={X}&y={Y}&z={Z}&s=Galileo&scale=2", 1, 20); //jpeg for sat
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String getTileUrl(Tile tile) {
|
|
||||||
sb.setLength(0);
|
|
||||||
sb.append("/vt/x="); //lyrs=y&
|
|
||||||
sb.append(tile.tileX);
|
|
||||||
sb.append("&y=");
|
|
||||||
sb.append(tile.tileY);
|
|
||||||
sb.append("&z=");
|
|
||||||
sb.append(tile.zoomLevel);
|
|
||||||
sb.append("&s=Galileo&scale=2");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -28,12 +27,11 @@ public class OSciMap4TileSource extends UrlTileSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public OSciMap4TileSource(String url) {
|
public OSciMap4TileSource(String url) {
|
||||||
super(url);
|
super(url, "/{Z}/{X}/{Y}.vtm");
|
||||||
setExtension(".vtm");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITileDataSource getDataSource() {
|
public ITileDataSource getDataSource() {
|
||||||
return new UrlTileDataSource(this, new TileDecoder(), new LwHttp(getUrl()));
|
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,39 +19,44 @@ package org.oscim.utils;
|
|||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class with IO-specific helper methods.
|
* A utility class with IO-specific helper methods.
|
||||||
*/
|
*/
|
||||||
public final class IOUtils {
|
public final class IOUtils {
|
||||||
|
final static Logger log = LoggerFactory.getLogger(IOUtils.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the {@link Closeable#close()} method on the given object. If an
|
* Invokes the {@link Closeable#close()} method on the given object. If an
|
||||||
* {@link IOException} occurs during the
|
* {@link IOException} occurs during the
|
||||||
* method call, it will be caught and logged on level {@link Level#WARNING}.
|
* method call, it will be caught and logged.
|
||||||
*
|
*
|
||||||
* @param closeable
|
* @param closeable
|
||||||
* the data source which should be closed (may be null).
|
* the data source which should be closed (may be null).
|
||||||
*/
|
*/
|
||||||
public static void closeQuietly(Closeable closeable) {
|
public static void closeQuietly(Closeable closeable) {
|
||||||
|
if (closeable == null)
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (closeable != null) {
|
closeable.close();
|
||||||
closeable.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//log.debug(e.getMessage() + " " + e);
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for old java versions */
|
/* for old java versions */
|
||||||
public static void closeQuietly(Socket closeable) {
|
public static void closeQuietly(Socket closeable) {
|
||||||
|
if (closeable == null)
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (closeable != null) {
|
closeable.close();
|
||||||
closeable.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//log.debug(e.getMessage() + " " + e);
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user