package com.jasonchen.microlang.utils.http;
import android.text.TextUtils;
import com.jasonchen.microlang.BuildConfig;
import com.jasonchen.microlang.R;
import com.jasonchen.microlang.debug.AppLogger;
import com.jasonchen.microlang.exception.WeiboException;
import com.jasonchen.microlang.utils.GlobalContext;
import com.jasonchen.microlang.utils.Utility;
import com.jasonchen.microlang.utils.file.FileDownloaderHttpHelper;
import com.jasonchen.microlang.utils.file.FileManager;
import com.jasonchen.microlang.utils.file.FileUploaderHttpHelper;
import com.jasonchen.microlang.utils.image.ImageUtility;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* jasonchen
* 2015/04/10
*/
public class JavaHttpUtility {
private static final int CONNECT_TIMEOUT = 10 * 1000;
private static final int READ_TIMEOUT = 10 * 1000;
private static final int DOWNLOAD_CONNECT_TIMEOUT = 15 * 1000;
private static final int DOWNLOAD_READ_TIMEOUT = 60 * 1000;
private static final int UPLOAD_CONNECT_TIMEOUT = 15 * 1000;
private static final int UPLOAD_READ_TIMEOUT = 5 * 60 * 1000;
public class NullHostNameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
private TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
public JavaHttpUtility() {
//allow Android to use an untrusted certificate for SSL/HTTPS connection
//so that when you debug app, you can use Fiddler http://fiddler2.com to logs all HTTPS traffic
try {
if (BuildConfig.DEBUG) {
HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
} catch (Exception e) {
}
}
public String executeNormalTask(HttpMethod httpMethod, String url, Map<String, String> param)
throws WeiboException {
switch (httpMethod) {
case Post:
return doPost(url, param);
case Get:
return doGet(url, param);
}
return "";
}
private static Proxy getProxy() {
String proxyHost = System.getProperty("http.proxyHost");
String proxyPort = System.getProperty("http.proxyPort");
if (!TextUtils.isEmpty(proxyHost) && !TextUtils.isEmpty(proxyPort)) {
return new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyHost, Integer.valueOf(proxyPort)));
} else {
return null;
}
}
public String doPost(String urlAddress, Map<String, String> param) throws WeiboException {
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
globalContext = null;
try {
URL url = new URL(urlAddress);
Proxy proxy = getProxy();
HttpsURLConnection uRLConnection;
if (proxy != null) {
uRLConnection = (HttpsURLConnection) url.openConnection(proxy);
} else {
uRLConnection = (HttpsURLConnection) url.openConnection();
}
uRLConnection.setDoInput(true);
uRLConnection.setDoOutput(true);
uRLConnection.setRequestMethod("POST");
uRLConnection.setUseCaches(false);
uRLConnection.setConnectTimeout(CONNECT_TIMEOUT);
uRLConnection.setReadTimeout(READ_TIMEOUT);
uRLConnection.setInstanceFollowRedirects(false);
uRLConnection.setRequestProperty("Connection", "Keep-Alive");
uRLConnection.setRequestProperty("Charset", "UTF-8");
uRLConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
uRLConnection.connect();
DataOutputStream out = new DataOutputStream(uRLConnection.getOutputStream());
out.write(Utility.encodeUrl(param).getBytes());
out.flush();
out.close();
return handleResponse(uRLConnection);
} catch (IOException e) {
e.printStackTrace();
throw new WeiboException(errorStr, e);
}
}
private String handleResponse(HttpURLConnection httpURLConnection) throws WeiboException {
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
globalContext = null;
int status = 0;
try {
status = httpURLConnection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
httpURLConnection.disconnect();
throw new WeiboException(errorStr, e);
}
if (status != HttpURLConnection.HTTP_OK) {
return handleError(httpURLConnection);
}
return readResult(httpURLConnection);
}
private String handleError(HttpURLConnection urlConnection) throws WeiboException {
String result = readError(urlConnection);
String err = null;
int errCode = 0;
try {
AppLogger.e("error=" + result);
JSONObject json = new JSONObject(result);
err = json.optString("error_description", "");
if (TextUtils.isEmpty(err)) {
err = json.getString("error");
}
errCode = json.getInt("error_code");
WeiboException exception = new WeiboException();
exception.setError_code(errCode);
exception.setOriError(err);
/*if (errCode == ErrorCode.EXPIRED_TOKEN || errCode == ErrorCode.INVALID_TOKEN) {
Utility.showExpiredTokenDialogOrNotification();
}*/
throw exception;
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
private String readResult(HttpURLConnection urlConnection) throws WeiboException {
InputStream is = null;
BufferedReader buffer = null;
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
globalContext = null;
try {
is = urlConnection.getInputStream();
String content_encode = urlConnection.getContentEncoding();
if (!TextUtils.isEmpty(content_encode) && content_encode
.equals("gzip")) {
is = new GZIPInputStream(is);
}
buffer = new BufferedReader(new InputStreamReader(is));
StringBuilder strBuilder = new StringBuilder();
String line;
while ((line = buffer.readLine()) != null) {
strBuilder.append(line);
}
// AppLogger.d("result=" + strBuilder.toString());
return strBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
throw new WeiboException(errorStr, e);
} finally {
Utility.closeSilently(is);
Utility.closeSilently(buffer);
urlConnection.disconnect();
}
}
private String readError(HttpURLConnection urlConnection) throws WeiboException {
InputStream is = null;
BufferedReader buffer = null;
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
try {
is = urlConnection.getErrorStream();
if (is == null) {
errorStr = globalContext.getString(R.string.unknown_sina_network_error);
throw new WeiboException(errorStr);
}
String content_encode = urlConnection.getContentEncoding();
if (!TextUtils.isEmpty(content_encode) && content_encode
.equals("gzip")) {
is = new GZIPInputStream(is);
}
buffer = new BufferedReader(new InputStreamReader(is));
StringBuilder strBuilder = new StringBuilder();
String line;
while ((line = buffer.readLine()) != null) {
strBuilder.append(line);
}
AppLogger.d("error result=" + strBuilder.toString());
return strBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
throw new WeiboException(errorStr, e);
} finally {
Utility.closeSilently(is);
Utility.closeSilently(buffer);
urlConnection.disconnect();
globalContext = null;
}
}
public String doGet(String urlStr, Map<String, String> param) throws WeiboException {
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
globalContext = null;
InputStream is = null;
try {
StringBuilder urlBuilder = new StringBuilder(urlStr);
urlBuilder.append("?").append(Utility.encodeUrl(param));
URL url = new URL(urlBuilder.toString());
AppLogger.d("get request" + url);
Proxy proxy = getProxy();
HttpURLConnection urlConnection;
if (proxy != null) {
urlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
urlConnection = (HttpURLConnection) url.openConnection();
}
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
urlConnection.setReadTimeout(READ_TIMEOUT);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
urlConnection.connect();
return handleResponse(urlConnection);
} catch (IOException e) {
e.printStackTrace();
throw new WeiboException(errorStr, e);
}
}
public boolean doGetSaveFile(String urlStr, String path,
FileDownloaderHttpHelper.DownloadListener downloadListener) {
File file = FileManager.createNewFileInSDCard(path);
if (file == null) {
return false;
}
boolean result = false;
BufferedOutputStream out = null;
InputStream in = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(urlStr);
AppLogger.d("download request=" + urlStr);
Proxy proxy = getProxy();
if (proxy != null) {
urlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
urlConnection = (HttpURLConnection) url.openConnection();
}
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.setConnectTimeout(DOWNLOAD_CONNECT_TIMEOUT);
urlConnection.setReadTimeout(DOWNLOAD_READ_TIMEOUT);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
urlConnection.connect();
int status = urlConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
return false;
}
int bytetotal = (int) urlConnection.getContentLength();
int bytesum = 0;
int byteread = 0;
out = new BufferedOutputStream(new FileOutputStream(file));
InputStream is = urlConnection.getInputStream();
String content_encode = urlConnection.getContentEncoding();
if (!TextUtils.isEmpty(content_encode) &&
content_encode.equals("gzip")) {
is = new GZIPInputStream(is);
}
in = new BufferedInputStream(is);
final Thread thread = Thread.currentThread();
byte[] buffer = new byte[1444];
while ((byteread = in.read(buffer)) != -1) {
if (thread.isInterrupted()) {
if (((float) bytesum / (float) bytetotal) < 0.8f) {
file.delete();
throw new InterruptedIOException();
}
}
bytesum += byteread;
out.write(buffer, 0, byteread);
if (downloadListener != null && bytetotal > 0) {
downloadListener.pushProgress(bytesum, bytetotal);
}
}
if (downloadListener != null) {
downloadListener.completed();
}
AppLogger.v("download request= " + urlStr + " download finished");
result = true;
} catch (IOException e) {
e.printStackTrace();
AppLogger.v("download request= " + urlStr + " download failed");
} finally {
Utility.closeSilently(in);
Utility.closeSilently(out);
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return result && ImageUtility.isThisBitmapCanRead(path);
}
private static String getBoundry() {
StringBuffer _sb = new StringBuffer();
for (int t = 1; t < 12; t++) {
long time = System.currentTimeMillis() + t;
if (time % 3 == 0) {
_sb.append((char) time % 9);
} else if (time % 3 == 1) {
_sb.append((char) (65 + time % 26));
} else {
_sb.append((char) (97 + time % 26));
}
}
return _sb.toString();
}
private String getBoundaryMessage(String boundary, Map params, String fileField,
String fileName, String fileType) {
StringBuffer res = new StringBuffer("--").append(boundary).append("\r\n");
Iterator keys = params.keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
String value = (String) params.get(key);
res.append("Content-Disposition: form-data; name=\"")
.append(key).append("\"\r\n").append("\r\n")
.append(value).append("\r\n").append("--")
.append(boundary).append("\r\n");
}
res.append("Content-Disposition: form-data; name=\"").append(fileField)
.append("\"; filename=\"").append(fileName)
.append("\"\r\n").append("Content-Type: ")
.append(fileType).append("\r\n\r\n");
return res.toString();
}
public boolean doUploadFile(String urlStr, Map<String, String> param, String path,
String imageParamName, final FileUploaderHttpHelper.ProgressListener listener)
throws WeiboException {
String BOUNDARYSTR = getBoundry();
File targetFile = new File(path);
byte[] barry = null;
int contentLength = 0;
String sendStr = "";
try {
barry = ("--" + BOUNDARYSTR + "--\r\n").getBytes("UTF-8");
sendStr = getBoundaryMessage(BOUNDARYSTR, param, imageParamName,
new File(path).getName(), "image/png");
contentLength = sendStr.getBytes("UTF-8").length + (int) targetFile.length()
+ 2 * barry.length;
} catch (UnsupportedEncodingException e) {
}
int totalSent = 0;
String lenstr = Integer.toString(contentLength);
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
FileInputStream fis = null;
GlobalContext globalContext = GlobalContext.getInstance();
String errorStr = globalContext.getString(R.string.timeout);
globalContext = null;
try {
URL url = null;
url = new URL(urlStr);
Proxy proxy = getProxy();
if (proxy != null) {
urlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
urlConnection = (HttpURLConnection) url.openConnection();
}
urlConnection.setConnectTimeout(UPLOAD_CONNECT_TIMEOUT);
urlConnection.setReadTimeout(UPLOAD_READ_TIMEOUT);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Content-type",
"multipart/form-data;boundary=" + BOUNDARYSTR);
urlConnection.setRequestProperty("Content-Length", lenstr);
((HttpURLConnection) urlConnection).setFixedLengthStreamingMode(contentLength);
urlConnection.connect();
out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write(sendStr.getBytes("UTF-8"));
totalSent += sendStr.getBytes("UTF-8").length;
fis = new FileInputStream(targetFile);
int bytesRead;
int bytesAvailable;
int bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024;
bytesAvailable = fis.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fis.read(buffer, 0, bufferSize);
long transferred = 0;
final Thread thread = Thread.currentThread();
while (bytesRead > 0) {
if (thread.isInterrupted()) {
targetFile.delete();
throw new InterruptedIOException();
}
out.write(buffer, 0, bufferSize);
bytesAvailable = fis.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fis.read(buffer, 0, bufferSize);
transferred += bytesRead;
if (transferred % 50 == 0) {
out.flush();
}
if (listener != null) {
listener.transferred(transferred);
}
}
out.write(barry);
totalSent += barry.length;
out.write(barry);
totalSent += barry.length;
out.flush();
out.close();
if (listener != null) {
listener.waitServerResponse();
}
int status = urlConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
String error = handleError(urlConnection);
throw new WeiboException(error);
}
targetFile.delete();
} catch (IOException e) {
e.printStackTrace();
throw new WeiboException(errorStr, e);
} finally {
Utility.closeSilently(fis);
Utility.closeSilently(out);
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return true;
}
}