package com.rakuten.tech.mobile.perf.core.wrappers; import android.os.Build; import com.rakuten.tech.mobile.perf.core.Analytics; import com.rakuten.tech.mobile.perf.core.Tracker; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ProtocolException; import java.net.URL; import java.security.Permission; import java.util.List; import java.util.Map; public class HttpURLConnectionWrapper extends HttpURLConnection { private final int NOT_STARTED = 0; private final int STARTED = 1; private final int ENDED = 2; private final int INPUT = 3; private final HttpURLConnection _conn; private int _state; private int _id; public HttpURLConnectionWrapper(HttpURLConnection conn) { super(conn.getURL()); _conn = conn; } // HttpURLConnection @Override public void disconnect() { _conn.disconnect(); if (_state == STARTED) { Tracker.endUrl(_id, 0, null, 0); _state = ENDED; } } @Override public InputStream getErrorStream() { return _conn.getErrorStream(); } @Override public boolean getInstanceFollowRedirects() { return _conn.getInstanceFollowRedirects(); } @Override public String getRequestMethod() { return _conn.getRequestMethod(); } @Override public int getResponseCode() throws IOException { if (_state == NOT_STARTED) { _id = Tracker.startUrl(url, _conn.getRequestMethod()); _state = STARTED; } int result = _conn.getResponseCode(); if ((_state == STARTED) && (!getDoInput())) { Tracker.endUrl(_id, result, _conn.getHeaderField(Analytics.CDN_HEADER), getContentLengthLongCompat(_conn)); _state = ENDED; } return result; } @Override public String getResponseMessage() throws IOException { if (_state == NOT_STARTED) { _id = Tracker.startUrl(url, _conn.getRequestMethod()); _state = STARTED; } String result = _conn.getResponseMessage(); if ((_state == STARTED) && (!getDoInput())) { Tracker.endUrl(_id, _conn.getResponseCode(), _conn.getHeaderField(Analytics.CDN_HEADER), getContentLengthLongCompat(_conn)); _state = ENDED; } return result; } @Override public void setChunkedStreamingMode(int chunklen) { _conn.setChunkedStreamingMode(chunklen); } @Override public void setFixedLengthStreamingMode(int contentLength) { _conn.setFixedLengthStreamingMode(contentLength); } @Override public void setInstanceFollowRedirects(boolean followRedirects) { _conn.setInstanceFollowRedirects(followRedirects); } @Override public void setRequestMethod(String method) throws ProtocolException { _conn.setRequestMethod(method); } @Override public boolean usingProxy() { return _conn.usingProxy(); } // URLConnection @Override public void addRequestProperty(String key, String value) { _conn.addRequestProperty(key, value); } @Override public void connect() throws IOException { if (_state == NOT_STARTED) { _id = Tracker.startUrl(url, _conn.getRequestMethod()); _state = STARTED; } _conn.connect(); } @Override public boolean getAllowUserInteraction() { return _conn.getAllowUserInteraction(); } @Override public int getConnectTimeout() { return _conn.getConnectTimeout(); } @Override public Object getContent() throws IOException { return _conn.getContent(); } @Override public Object getContent(Class[] classes) throws IOException { return _conn.getContent(classes); } @Override public String getContentEncoding() { return _conn.getContentEncoding(); } @Override public int getContentLength() { return _conn.getContentLength(); } @Override public String getContentType() { return _conn.getContentType(); } @Override public long getDate() { return _conn.getDate(); } @Override public boolean getDefaultUseCaches() { return _conn.getDefaultUseCaches(); } @Override public boolean getDoInput() { return _conn.getDoInput(); } @Override public boolean getDoOutput() { return _conn.getDoOutput(); } @Override public long getExpiration() { return _conn.getExpiration(); } @Override public String getHeaderField(String name) { return _conn.getHeaderField(name); } @Override public String getHeaderField(int n) { return _conn.getHeaderField(n); } @Override public long getHeaderFieldDate(String name, long Default) { return _conn.getHeaderFieldDate(name, Default); } @Override public int getHeaderFieldInt(String name, int Default) { return _conn.getHeaderFieldInt(name, Default); } @Override public String getHeaderFieldKey(int n) { return _conn.getHeaderFieldKey(n); } @Override public Map<String, List<String>> getHeaderFields() { return _conn.getHeaderFields(); } @Override public long getIfModifiedSince() { return _conn.getIfModifiedSince(); } @Override public InputStream getInputStream() throws IOException { if (_state == NOT_STARTED) { _id = Tracker.startUrl(url, _conn.getRequestMethod()); _state = STARTED; } int statusCode = _conn.getResponseCode(); String cdnHeader = _conn.getHeaderField(Analytics.CDN_HEADER); long contentLength = getContentLengthLongCompat(_conn); try { InputStream stream = _conn.getInputStream(); if (stream == null) { if (_state == STARTED) { Tracker.endUrl(_id, statusCode, cdnHeader, contentLength); _state = ENDED; } return null; } if (_state == STARTED) { _state = INPUT; } return new HttpInputStreamWrapper(stream, _id, statusCode, cdnHeader, contentLength); } catch (IOException e) { if (_state == STARTED) { Tracker.endUrl(_id, statusCode, cdnHeader, contentLength); _state = ENDED; } throw e; } } @Override public long getLastModified() { return _conn.getLastModified(); } @Override public OutputStream getOutputStream() throws IOException { return _conn.getOutputStream(); } @Override public Permission getPermission() throws IOException { return _conn.getPermission(); } @Override public int getReadTimeout() { return _conn.getReadTimeout(); } @Override public Map<String, List<String>> getRequestProperties() { return _conn.getRequestProperties(); } @Override public String getRequestProperty(String key) { return _conn.getRequestProperty(key); } @Override public URL getURL() { return _conn.getURL(); } @Override public boolean getUseCaches() { return _conn.getUseCaches(); } @Override public void setAllowUserInteraction(boolean allowuserinteraction) { _conn.setAllowUserInteraction(allowuserinteraction); } @Override public void setConnectTimeout(int timeout) { _conn.setConnectTimeout(timeout); } @Override public void setDefaultUseCaches(boolean defaultusecaches) { _conn.setDefaultUseCaches(defaultusecaches); } @Override public void setDoInput(boolean doinput) { _conn.setDoInput(doinput); } @Override public void setDoOutput(boolean dooutput) { _conn.setDoOutput(dooutput); } @Override public void setIfModifiedSince(long ifmodifiedsince) { _conn.setIfModifiedSince(ifmodifiedsince); } @Override public void setReadTimeout(int timeout) { _conn.setReadTimeout(timeout); } @Override public void setRequestProperty(String key, String value) { _conn.setRequestProperty(key, value); } @Override public void setUseCaches(boolean usecaches) { _conn.setUseCaches(usecaches); } @Override public String toString() { return _conn.toString(); } private static long getContentLengthLongCompat(HttpURLConnection conn) { return Build.VERSION.SDK_INT < 24 ? (long) conn.getContentLength() : conn.getContentLengthLong(); } }