package eu.musesproject.client.connectionmanager; /* * #%L * MUSES Client * %% * Copyright (C) 2013 - 2014 Sweden Connectivity * %% * 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. * #L% */ import android.util.Log; import eu.musesproject.client.ui.DebugFileLog; import org.apache.http.Header; import org.apache.http.HttpResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; /** * Handles http response and updates the other module using callbacks * * @author Yasir Ali * @version Jan 27, 2014 */ public class HttpResponseHandler { private static final String TAG = HttpResponseHandler.class.getSimpleName(); private static final String APP_TAG = "APP_TAG"; private String receivedHttpResponseData = null; private HttpResponse httpResponse = null; private boolean isNewSession = false; private String requestType; private int dataId; private int sessionUpdateReason = 0; /** * Constructor initialise with httpResponse and request type (connect,data,poll etc) * @param httpResponse * @param requestType * @return void */ public HttpResponseHandler(HttpResponse httpResponse, String requestType, int dataId) { this.httpResponse = httpResponse; this.requestType = requestType; this.dataId = dataId; } public HttpResponseHandler(String requestType, int dataId) { this.requestType = requestType; this.dataId = dataId; } /** * Check response and call appropriate callback methods * @return void */ public synchronized void checkHttpResponse(){ if (httpResponse != null) { switch(getStatusCodeResponse(httpResponse)){ case DetailedStatuses.SUCCESS: // Only send if Success in connection int detailedOnlineStatus = DetailedStatuses.SUCCESS; Statuses.CURRENT_STATUS = Statuses.ONLINE; if (isNewSession){ isNewSession = false; if (Statuses.CURRENT_STATUS == Statuses.ONLINE){ setServerStatusAndCallBack(Statuses.NEW_SESSION_CREATED, sessionUpdateReason, dataId); } } if (isPollRequest(requestType)) { setServerStatusAndCallBack(Statuses.ONLINE, detailedOnlineStatus, dataId); if (isPayloadInData(httpResponse)) { Log.d(APP_TAG, "ConnManager=> Poll request=>Server responded with JSON: " + receivedHttpResponseData); DebugFileLog.write(APP_TAG+ " ConnManager=> Poll request=>Server responded with JSON: " + receivedHttpResponseData); sendDataToFunctionalLayer(); sendAcktoServer(); } if (isMorePackets(httpResponse)){ doPollForAnExtraPacket(); } } else if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.ONLINE, detailedOnlineStatus, dataId); setServerStatusAndCallBack(Statuses.DATA_SEND_OK, DetailedStatuses.SUCCESS, dataId); if (isPayloadInData(httpResponse)) { Log.d(APP_TAG, "ConnManager=> SendData request=> Server responded with JSON: " + receivedHttpResponseData); DebugFileLog.write(APP_TAG+ " ConnManager=> SendData request=> Server responded with JSON: " + receivedHttpResponseData); sendDataToFunctionalLayer(); } if (isMorePackets(httpResponse) || AlarmReceiver.getCurrentPollInterval()>AlarmReceiver.DEFAULT_POLL_INTERVAL){ doPollForAnExtraPacket(); } } else if (isAckRequest(requestType)) { setServerStatusAndCallBack(Statuses.ONLINE, detailedOnlineStatus, dataId); Log.d(APP_TAG, "Ack by the server"); DebugFileLog.write(APP_TAG+ " Ack by the server"); } else if (isConnectRequest(requestType)){ setServerStatusAndCallBack(Statuses.ONLINE, detailedOnlineStatus, dataId); setServerStatusAndCallBack(Statuses.CONNECTION_OK, DetailedStatuses.SUCCESS, dataId); } else if (isDisonnectRequest(requestType)){ setServerStatusAndCallBack(Statuses.DISCONNECTED, DetailedStatuses.SUCCESS, dataId); Log.d(APP_TAG, "ConnManager=> Disconnect request=> Server responded with JSON: " + receivedHttpResponseData != null ? receivedHttpResponseData : "empty"); DebugFileLog.write(APP_TAG+ " ConnManager=> Disconnect request=> Server responded with JSON: " + receivedHttpResponseData != null ? receivedHttpResponseData : "empty"); } AlarmReceiver.resetExponentialPollTime(); break; case DetailedStatuses.INCORRECT_URL: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Incorrect URL"); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.INCORRECT_URL, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.INCORRECT_URL, dataId); AlarmReceiver.increasePollTime(); break; case DetailedStatuses.NOT_ALLOWED_FROM_SERVER_UNAUTHORIZED: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Request not allowed from Server.."); DebugFileLog.write(APP_TAG+ " Server is OFFLINE .. Request not allowed from Server.."); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.NOT_ALLOWED_FROM_SERVER_UNAUTHORIZED, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.NOT_ALLOWED_FROM_SERVER_UNAUTHORIZED, dataId); AlarmReceiver.increasePollTime(); break; case DetailedStatuses.NOT_FOUND: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Error: Not found"); DebugFileLog.write(APP_TAG+ " Server is OFFLINE .. Error: Not found"); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.NOT_FOUND, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.NOT_FOUND, dataId); AlarmReceiver.increasePollTime(); break; case DetailedStatuses.INTERNAL_SERVER_ERROR: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Internal Server Error"); DebugFileLog.write(APP_TAG+ " Server is OFFLINE .. Internal Server Error"); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.INTERNAL_SERVER_ERROR, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.INTERNAL_SERVER_ERROR, dataId); AlarmReceiver.increasePollTime(); break; case DetailedStatuses.SERVER_NOT_AVAIABLE: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Server not available"); DebugFileLog.write(APP_TAG+ " Server is OFFLINE .. Server not available"); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.SERVER_NOT_AVAIABLE, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.SERVER_NOT_AVAIABLE, dataId); AlarmReceiver.increasePollTime(); break; default: Statuses.CURRENT_STATUS = Statuses.OFFLINE; Log.d(APP_TAG, "Server is OFFLINE .. Unknown Error:"+getStatusCodeResponse(httpResponse)); DebugFileLog.write(APP_TAG+ " Server is OFFLINE .. Unknown Error:"+getStatusCodeResponse(httpResponse)); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.UNKNOWN_ERROR, dataId); } setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.UNKNOWN_ERROR, dataId); AlarmReceiver.increasePollTime(); break; } } else { Statuses.CURRENT_STATUS = Statuses.OFFLINE; setServerStatusAndCallBack(Statuses.OFFLINE, DetailedStatuses.UNKNOWN_ERROR, dataId); if (isSendDataRequest(requestType)){ setServerStatusAndCallBack(Statuses.DATA_SEND_FAILED, DetailedStatuses.UNKNOWN_ERROR, dataId); } if (isConnectRequest(requestType)){ setServerStatusAndCallBack(Statuses.CONNECTION_FAILED, DetailedStatuses.UNKNOWN_ERROR, dataId); /* Depending on error Polling shall be stopped, but difficult to know if error is recoverable */ } Log.d(APP_TAG, "Server is OFFLINE, HttpResponse is null, check network connectivity or address of server!"); DebugFileLog.write(APP_TAG+ " Server is OFFLINE, HttpResponse is null, check network connectivity or address of server!"); } } private boolean isMorePackets(HttpResponse httpResponse) { Header [] dataReceived = httpResponse.getAllHeaders(); for (Header responseHedar : dataReceived){ if (responseHedar.getName().equals("more-packets")){ if (responseHedar.getValue().equalsIgnoreCase("YES")){ return true; } } } return false; } private void doPollForAnExtraPacket(){ if (NetworkChecker.isInternetConnected){ ConnectionManager connectionManager = new ConnectionManager(); connectionManager.poll(); } } /** * Send data to functional module * @return void */ private void sendDataToFunctionalLayer(){ ConnectionManager.callBacks.receiveCb(receivedHttpResponseData); } /** * Calls the connection manager ack method to send the ack to the server */ private void sendAcktoServer() { ConnectionManager connectionManager = new ConnectionManager(); connectionManager.ack(); } /** * Check if the http request is for polling * @param requestType * @return */ private boolean isPollRequest(String requestType) { if (requestType.equalsIgnoreCase(ConnectionManager.POLL)) { return true; } return false; } /** * Check if the http request is for data * @param requestType * @return */ private boolean isSendDataRequest(String requestType) { if (requestType.equalsIgnoreCase(ConnectionManager.DATA)) { return true; } return false; } /** * Check if the http request is for acknowledgment for the last data sent * @param requestType * @return */ private boolean isAckRequest(String requestType) { if (requestType.equalsIgnoreCase(ConnectionManager.ACK)) { return true; } return false; } /** * Check if the http request is was a connect request * @param requestType * @return */ private boolean isConnectRequest(String requestType) { if (requestType.equalsIgnoreCase(ConnectionManager.CONNECT)) { return true; } return false; } /** * Check if the http request is was a disconnect request * @param requestType * @return */ private boolean isDisonnectRequest(String requestType) { if (requestType.equalsIgnoreCase(ConnectionManager.DISCONNECT)) { return true; } return false; } /** * Check if the http response has any payload of data * @param HttpResponse * @return */ private boolean isPayloadInData(HttpResponse httpResponse){ String data = reteiveDataFromHttpResponseHeader(httpResponse); if ( data == null || data.equalsIgnoreCase("")){ return false; } else return true; } /** * Sets curent status of the Server in terms of ONLINE/OFFLINE using callbacks * @param status * @return void */ private void setServerStatusAndCallBack(int status, int detailedStatus, int dataId) { if (status == Statuses.OFFLINE || status == Statuses.ONLINE) { ConnectionManager.sendServerStatus(status, detailedStatus, dataId); } else { ConnectionManager.callBacks.statusCb(status, detailedStatus, dataId); } } /** * Get response code from status code * @param httpResponse * @return void */ private int getStatusCodeResponse(HttpResponse httpResponse){ int statusCode = httpResponse.getStatusLine().getStatusCode(); switch(statusCode){ case 200 : return DetailedStatuses.SUCCESS; case 400 : return DetailedStatuses.INCORRECT_URL; case 401 : return DetailedStatuses.NOT_ALLOWED_FROM_SERVER_UNAUTHORIZED; case 404 : return DetailedStatuses.NOT_FOUND; case 500 : return DetailedStatuses.INTERNAL_SERVER_ERROR; case 503 : return DetailedStatuses.SERVER_NOT_AVAIABLE; default : return DetailedStatuses.UNKNOWN_ERROR; } } /** * Retrieve Data from http response from the Server * @param response * @return receivedHttpResponseData * @throws IOException * @throws IllegalStateException * @throws UnsupportedEncodingException */ private String reteiveDataFromHttpResponseHeader(HttpResponse response) { BufferedReader reader; String json = ""; try { reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); json = reader.readLine(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } receivedHttpResponseData = json; return receivedHttpResponseData; } public void setNewSession(boolean isNewSession, int reason) { this.isNewSession = isNewSession; sessionUpdateReason = reason; } public void setResponse(HttpResponse httpResponse) { // TODO Auto-generated method stub this.httpResponse = httpResponse; } public String getDataLength() { String dataLength = "0"; if (httpResponse != null){ Header header = httpResponse.getFirstHeader("data"); if (header!=null){ if (header.getValue().contains("sensor-config")) { Log.d(APP_TAG, "Sensor-Config"); DebugFileLog.write(APP_TAG+ " Sensor-Config"); dataLength = Integer.toString(header.getValue().length()); } } } // new implementation as data header is not used anymore dataLength = Integer.toString(receivedHttpResponseData.length() ); return dataLength; } }