001package com.gigya.android.sdk.network.adapter; 002 003import android.os.AsyncTask; 004 005import com.gigya.android.sdk.api.GigyaApiRequest; 006import com.gigya.android.sdk.api.GigyaApiHttpRequest; 007import com.gigya.android.sdk.api.IApiRequestFactory; 008import com.gigya.android.sdk.network.GigyaError; 009 010import java.io.BufferedReader; 011import java.io.IOException; 012import java.io.InputStream; 013import java.io.InputStreamReader; 014import java.io.OutputStreamWriter; 015import java.net.HttpURLConnection; 016import java.net.URL; 017import java.util.Iterator; 018import java.util.Queue; 019import java.util.concurrent.ConcurrentLinkedQueue; 020import java.util.zip.GZIPInputStream; 021 022public class HttpNetworkProvider extends NetworkProvider { 023 024 private Queue<HttpTask> _queue = new ConcurrentLinkedQueue<>(); 025 026 public HttpNetworkProvider(IApiRequestFactory requestFactory) { 027 super(requestFactory); 028 } 029 030 @Override 031 public void addToQueue(GigyaApiRequest request, IRestAdapterCallback networkCallbacks) { 032 if (_blocked) { 033 _queue.add(new HttpTask(_requestFactory, new GigyaNetworkAsyncTask(networkCallbacks), request)); 034 return; 035 } 036 // If not blocked send the request. 037 new GigyaNetworkAsyncTask(networkCallbacks).execute(_requestFactory.sign(request)); 038 } 039 040 @Override 041 public void sendBlocking(GigyaApiRequest request, IRestAdapterCallback networkCallbacks) { 042 _requestFactory.sign(request); 043 new GigyaNetworkAsyncTask(networkCallbacks).execute(_requestFactory.sign(request)); 044 _blocked = true; 045 } 046 047 @Override 048 public void release() { 049 super.release(); 050 if (_queue.isEmpty()) { 051 return; 052 } 053 054 HttpTask queued = _queue.poll(); 055 // Requests need to be re-signed when released from the blocking queue. 056 _requestFactory.sign(queued.getRequest()); 057 058 while (queued != null) { 059 queued.run(); 060 queued = _queue.poll(); 061 } 062 } 063 064 @Override 065 public void cancel(String tag) { 066 if (tag == null) { 067 _queue.clear(); 068 // Unable to cancel already sent requests. 069 } 070 if (!_queue.isEmpty()) { 071 Iterator it = _queue.iterator(); 072 while (it.hasNext()) { 073 final HttpTask task = (HttpTask) it.next(); 074 final String requestTag = task.request.getTag(); 075 if (requestTag.equals(tag)) { 076 it.remove(); 077 } 078 } 079 } 080 } 081 082 // Async implementation. 083 084 private static class AsyncResult { 085 private int code; 086 private String result; 087 private String date; 088 089 AsyncResult(int code, String result, String date) { 090 this.code = code; 091 this.result = result; 092 this.date = date; 093 } 094 095 public int getCode() { 096 return code; 097 } 098 } 099 100 private static class HttpTask { 101 102 private GigyaNetworkAsyncTask asyncTask; 103 private GigyaApiRequest request; 104 private IApiRequestFactory requestFactory; 105 106 public GigyaApiRequest getRequest() { 107 return request; 108 } 109 110 public void setRequest(GigyaApiRequest request) { 111 this.request = request; 112 } 113 114 HttpTask(IApiRequestFactory requestFactory, GigyaNetworkAsyncTask asyncTask, GigyaApiRequest request) { 115 this.requestFactory = requestFactory; 116 this.asyncTask = asyncTask; 117 this.request = request; 118 } 119 120 void run() { 121 final GigyaApiHttpRequest signedRequest = this.requestFactory.sign(request); 122 this.asyncTask.execute(signedRequest); 123 } 124 } 125 126 private static class GigyaNetworkAsyncTask extends AsyncTask<GigyaApiHttpRequest, Void, AsyncResult> { 127 128 private IRestAdapterCallback networkCallbacks; 129 130 GigyaNetworkAsyncTask(IRestAdapterCallback networkCallbacks) { 131 this.networkCallbacks = networkCallbacks; 132 } 133 134 @Override 135 protected AsyncResult doInBackground(GigyaApiHttpRequest... gigyaApiRequests) { 136 GigyaApiHttpRequest request = gigyaApiRequests[0]; 137 if (request != null) { 138 HttpURLConnection connection = null; 139 OutputStreamWriter outputStreamWriter = null; 140 BufferedReader bufferedReader = null; 141 StringBuilder response = new StringBuilder(); 142 try { 143 URL url = new URL(request.getUrl()); 144 connection = (HttpURLConnection) url.openConnection(); 145 connection.setUseCaches(false); 146 connection.setConnectTimeout(10000); 147 connection.setRequestProperty("Accept-Encoding", "gzip"); 148 connection.setRequestProperty("connection", "close"); 149 150 connection.setRequestMethod(request.getHttpMethod().intValue() == 0 ? "GET" : "POST"); 151 if (request.getHttpMethod().intValue() == 1) { 152 connection.setDoOutput(true); 153 outputStreamWriter = new OutputStreamWriter(connection.getOutputStream()); 154 outputStreamWriter.write(request.getEncodedParams()); 155 outputStreamWriter.flush(); 156 } 157 int responseStatusCode = connection.getResponseCode(); 158 boolean badRequest = (responseStatusCode >= HttpURLConnection.HTTP_BAD_REQUEST); 159 InputStream input; 160 if (badRequest) 161 input = connection.getErrorStream(); 162 else 163 input = connection.getInputStream(); 164 if ("gzip".equals(connection.getContentEncoding())) { 165 input = new GZIPInputStream(input); 166 } 167 bufferedReader = new BufferedReader(new InputStreamReader(input, "UTF-8")); 168 String line; 169 while ((line = bufferedReader.readLine()) != null) { 170 response.append(line); 171 } 172 173 final String dateHeader = connection.getHeaderField("Date"); 174 175 return new AsyncResult(responseStatusCode, response.toString(), dateHeader); 176 } catch (Exception ex) { 177 ex.printStackTrace(); 178 } finally { 179 if (outputStreamWriter != null) { 180 try { 181 outputStreamWriter.close(); 182 } catch (IOException ignored) { 183 } 184 } 185 if (bufferedReader != null) { 186 try { 187 bufferedReader.close(); 188 } catch (IOException ignored) { 189 } 190 } 191 if (connection != null) { 192 connection.disconnect(); 193 } 194 } 195 } 196 return null; 197 } 198 199 @Override 200 protected void onPostExecute(AsyncResult asyncResult) { 201 if (networkCallbacks == null) { 202 return; 203 } 204 if (asyncResult == null) { 205 networkCallbacks.onError(GigyaError.generalError()); 206 return; 207 } 208 209 boolean badRequest = asyncResult.getCode() >= HttpURLConnection.HTTP_BAD_REQUEST; 210 if (badRequest) { 211 // Generate gigya error. 212 final GigyaError gigyaError = new GigyaError(asyncResult.code, asyncResult.result, null); 213 networkCallbacks.onError(gigyaError); 214 return; 215 } 216 217 networkCallbacks.onResponse(asyncResult.result, asyncResult.date); 218 } 219 } 220 221 //endregion 222 223}