/** * Copyright 2014-present Liquid Data Intelligence S.A. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.lqd.sdk.model; import android.os.Build; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.zip.GZIPInputStream; import io.lqd.sdk.LQLog; import io.lqd.sdk.Liquid; public class LQNetworkRequest extends LQModel { public static final int HALF_HOUR = 30 * 60 * 1000; private static final long serialVersionUID = 7456534930025458866L; private static final String LOCAL = Locale.getDefault().toString(); private static final String DEVICE = Build.MANUFACTURER + " " + Build.MODEL; private static final String USER_AGENT = "Liquid/" + Liquid.LIQUID_VERSION + " (Android; Android " + Build.VERSION.RELEASE + "; " + LOCAL + "; " + DEVICE + ")"; private String mUrl; private String mHttpMethod; private String mJson; private int mNumberOfTries; private Date mLastTry; private SimpleDateFormat mDateFormat; public LQNetworkRequest(String url, String httpMethod, String json) { mUrl = url; mHttpMethod = httpMethod; mJson = json; mNumberOfTries = 0; mLastTry = null; mDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); } public String getUrl() { return mUrl; } public String getHttpMethod() { return mHttpMethod; } public String getJSON() { return mJson; } public int getNumberOfTries() { return mNumberOfTries; } public void incrementNumberOfTries() { mNumberOfTries++; } public void setLastTry(Date lastTry) { mLastTry = lastTry; } public Date getLastTry() { return mLastTry; } public boolean willFlushAndSet(Date now) { boolean willflush = canFlush(now); if(!willflush) { mLastTry = now; } return willflush; } public boolean canFlush(Date now) { return mLastTry == null || now.getTime() - mLastTry.getTime() >= HALF_HOUR; } @Override public boolean equals(Object o) { return (o instanceof LQNetworkRequest) && ((LQNetworkRequest) o).getHttpMethod().equals(this.getHttpMethod()) && ((LQNetworkRequest) o).getUrl().equals(this.getUrl()) && ((LQNetworkRequest) o).getJSON().equals(this.getJSON()); } public LQNetworkResponse sendRequest(String token) { String response = null; String date = mDateFormat.format(Calendar.getInstance().getTime()); int responseCode = -1; InputStream err = null; BufferedReader boin = null; DataOutputStream outputStream = null; HttpURLConnection connection = null; try { URL url = new URL(this.getUrl()); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(this.getHttpMethod()); connection.setRequestProperty("Date", date); connection.setRequestProperty("Authorization", "Token " + token); connection.setRequestProperty("User-Agent", USER_AGENT); connection.setRequestProperty("Accept", "application/vnd.lqd.v1+json"); connection.setRequestProperty("Content-Type", "application/json"); connection.setRequestProperty("Accept-Encoding", "gzip"); connection.setDoInput(true); if (this.getJSON() != null) { connection.setDoOutput(true); outputStream = new DataOutputStream(connection.getOutputStream()); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8")); writer.write(this.getJSON()); writer.close(); outputStream.close(); } responseCode = connection.getResponseCode(); err = connection.getErrorStream(); GZIPInputStream gzip = new GZIPInputStream(connection.getInputStream()); boin = new BufferedReader(new InputStreamReader(gzip, "UTF-8")); response = boin.readLine(); } catch (IOException e) { LQLog.http("Failed due to " + e + " responseCode " + responseCode); LQLog.http("Error " + inputStreamToString(err)); } finally { if(connection != null) connection.disconnect(); try { if(outputStream != null) outputStream.close(); } catch (IOException e) {} try { if(err != null) err.close(); } catch (IOException e) {} try { if (boin != null) boin.close(); } catch (IOException e) {} } if ((response != null) || ((responseCode >= 200) && (responseCode < 300))) { LQLog.http("HTTP Success " + response); return new LQNetworkResponse(responseCode, response); } return new LQNetworkResponse(responseCode); } private static String inputStreamToString(final InputStream stream) { if(stream == null) { return ""; } try { BufferedReader br = new BufferedReader(new InputStreamReader( new GZIPInputStream(stream))); StringBuilder sb = new StringBuilder(); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } br.close(); return sb.toString(); } catch (IOException e) { return ""; } } public static LQModel fromJSON(JSONObject jsonObject) { LQNetworkRequest lqNetworkRequest = null; try { String mUrl = jsonObject.getString("mUrl"); String mHttpMethod = jsonObject.getString("mHttpMethod"); String mJson = jsonObject.getString("mJson"); lqNetworkRequest = new LQNetworkRequest(mUrl, mHttpMethod, mJson); } catch (JSONException e) { e.printStackTrace(); } return lqNetworkRequest; } @Override public JSONObject toJSON() { JSONObject json = new JSONObject(); try { json.put("mUrl", mUrl); json.put("mHttpMethod", mHttpMethod); json.put("mJson", mJson); json.put("mNumberOfTries", mNumberOfTries); json.put("mLastTry", mLastTry); return json; } catch (JSONException e) { e.printStackTrace(); } return null; } }