summaryrefslogtreecommitdiff
path: root/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/http/HTTPContext.java
blob: 4558bbfe348706452f8c8d4a95800c971566f949 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.mapbox.mapboxgl.http;

import com.mapbox.mapboxgl.constants.MapboxConstants;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ProtocolException;
import java.net.SocketException;
import java.net.UnknownHostException;

import javax.net.ssl.SSLException;

class HTTPContext {

    private static final int CONNECTION_ERROR = 0;
    private static final int TEMPORARY_ERROR = 1;
    private static final int PERMANENT_ERROR = 2;

    private static HTTPContext mInstance = null;

    private OkHttpClient mClient;

    private HTTPContext() {
        super();
        mClient = new OkHttpClient();
    }

    public static HTTPContext getInstance() {
        if (mInstance == null) {
            mInstance = new HTTPContext();
        }

        return mInstance;
    }

    public HTTPRequest createRequest(long nativePtr, String resourceUrl, String userAgent, String etag, String modified) {
        return new HTTPRequest(nativePtr, resourceUrl, userAgent, etag, modified);
    }

    public class HTTPRequest implements Callback {
        private long mNativePtr = 0;

        private Call mCall;
        private Request mRequest;

        private native void nativeOnFailure(long nativePtr, int type, String message);
        private native void nativeOnResponse(long nativePtr, int code, String message, String etag, String modified, String cacheControl, String expires, byte[] body);

        private HTTPRequest(long nativePtr, String resourceUrl, String userAgent, String etag, String modified) {
            mNativePtr = nativePtr;
            Request.Builder builder = new Request.Builder().url(resourceUrl).tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)).addHeader("User-Agent", userAgent);
            if (etag.length() > 0) {
                builder = builder.addHeader("If-None-Match", etag);
            } else if (modified.length() > 0) {
                builder = builder.addHeader("If-Modified-Since", modified);
            }
            mRequest = builder.build();
        }

        public void start() {
            mCall = HTTPContext.getInstance().mClient.newCall(mRequest);
            mCall.enqueue(this);
        }

        public void cancel() {
            mCall.cancel();
        }

        @Override
        public void onFailure(Request request, IOException e) {
            int type = PERMANENT_ERROR;
            if ((e instanceof UnknownHostException) || (e instanceof SocketException) || (e instanceof ProtocolException) || (e instanceof SSLException)) {
                type = CONNECTION_ERROR;
            } else if ((e instanceof InterruptedIOException)) {
                type = TEMPORARY_ERROR;
            }
            nativeOnFailure(mNativePtr, type, e.getMessage());
        }

        @Override
        public void onResponse(Response response) throws IOException {
            byte[] body;
            try {
                body = response.body().bytes();
            } catch (IOException e) {
                onFailure(mRequest, e);
                return;
            } finally {
                response.body().close();
            }

            nativeOnResponse(mNativePtr, response.code(), response.message(), response.header("ETag"), response.header("Last-Modified"), response.header("Cache-Control"), response.header("Expires"), body);
        }
    }
}