/* * HttpConnection * Connect SDK * * Copyright (c) 2015 LG Electronics. * Created by Oleksii Frolov on 20 Apr 2015 * * 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 com.connectsdk.etc.helper; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.ProtocolException; import java.net.Socket; import java.net.URI; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; /** * HTTP connection implementation based on this article * http://android-developers.blogspot.com/2011/09/androids-http-clients.html * Also DefaultHttpClient has been deprecated since Android 5.1 */ public abstract class HttpConnection { public static HttpConnection newInstance(URI uri) throws IOException { return new HttpURLConnectionClient(uri); } public static HttpConnection newSubscriptionInstance(URI uri) throws IOException { return new CustomConnectionClient(uri); } public abstract void setMethod(Method method) throws ProtocolException; public abstract int getResponseCode() throws IOException; public abstract String getResponseString() throws IOException; public abstract void execute() throws IOException; public abstract void setPayload(String payload); public abstract void setPayload(byte[] payload); public abstract void setHeader(String name, String value); public abstract String getResponseHeader(String name); public enum Method { GET, POST, PUT, DELETE, SUBSCRIBE, UNSUBSCRIBE } private static class HttpURLConnectionClient extends HttpConnection { private final HttpURLConnection connection; private byte[] payload; private String response; private int responseCode; private HttpURLConnectionClient(URI uri) throws IOException { this.connection = (HttpURLConnection) uri.toURL().openConnection(); } @Override public void setMethod(Method method) throws ProtocolException { connection.setRequestMethod(method.name()); } @Override public int getResponseCode() throws IOException { return responseCode; } @Override public String getResponseString() throws IOException { return response; } @Override public void execute() throws IOException { try { if (payload != null) { BufferedOutputStream writer = new BufferedOutputStream(connection.getOutputStream()); writer.write(payload); writer.flush(); writer.close(); } try { BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; StringBuilder sb = new StringBuilder(); while (null != (line = reader.readLine())) { sb.append(line); sb.append("\r\n"); } reader.close(); this.response = sb.toString(); } catch (Exception e) { // it's OK, we have a response code } responseCode = connection.getResponseCode(); } finally { connection.disconnect(); } } @Override public void setPayload(String payload) { this.payload = payload.getBytes(); connection.setDoOutput(true); } @Override public void setPayload(byte[] payload) { this.payload = payload; connection.setDoOutput(true); } @Override public void setHeader(String name, String value) { connection.setRequestProperty(name, value); } @Override public String getResponseHeader(String name) { return connection.getHeaderField(name); } } private static class CustomConnectionClient extends HttpConnection { private final URI uri; private Method method; private String payload; private Map<String, String> headers = new LinkedHashMap<String, String>(); private int code; private String response; private Map<String, String> responseHeaders = new HashMap<String, String>(); private CustomConnectionClient(URI uri) { this.uri = uri; } @Override public void setMethod(Method method) throws ProtocolException { this.method = method; } @Override public int getResponseCode() throws IOException { return code; } @Override public String getResponseString() throws IOException { return response; } @Override public void execute() throws IOException { int port = uri.getPort() > 0 ? uri.getPort() : 80; Socket socket = new Socket(uri.getHost(), port); PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // send request writer.print(method.name()); writer.print(" "); writer.print(uri.getPath()); writer.print(uri.getQuery().isEmpty() ? "" : "?" + uri.getQuery()); writer.print(" HTTP/1.1\r\n"); writer.print("Host:"); writer.print(uri.getHost()); writer.print(":"); writer.print(port); writer.print("\r\n"); for (Map.Entry<String, String> pair : headers.entrySet()) { writer.print(pair.getKey()); writer.print(":"); writer.print(pair.getValue()); writer.print("\r\n"); } writer.print("\r\n"); if (payload != null) { writer.print(payload); } writer.flush(); // receive response StringBuilder sb = new StringBuilder(); String line; line = reader.readLine(); if (line != null) { String[] tokens = line.split(" "); if (tokens.length > 2) { code = Integer.parseInt(tokens[1]); } } while (null != (line = reader.readLine())) { if (line.isEmpty()) { break; } String[] pair = line.split(":", 2); if (pair != null && pair.length == 2) { responseHeaders.put(pair[0].trim(), pair[1].trim()); } } while (null != (line = reader.readLine())) { sb.append(line); sb.append("\r\n"); } response = sb.toString(); socket.close(); } @Override public void setPayload(String payload) { this.payload = payload; } @Override public void setPayload(byte[] payload) { throw new UnsupportedOperationException(); } @Override public void setHeader(String name, String value) { if (name != null && value != null) { this.headers.put(name.trim(), value.trim()); } } @Override public String getResponseHeader(String name) { return responseHeaders.get(name); } } }