Java tutorial
/* * Copyright (c) 2014, KJFrameForAndroid (kymjs123@gmail.com). * * 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.mike.aframe.http; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.UnknownHostException; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.WeakHashMap; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.zip.GZIPInputStream; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.ClientContext; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.params.ConnPerRouteBean; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.SyncBasicHttpContext; import android.content.Context; import com.mike.aframe.MKException; import com.mike.aframe.core.KJThreadExecutors; import com.mike.aframe.http.cache.HttpCache; import com.mike.aframe.http.downloader.FileDownLoader; import com.mike.aframe.http.downloader.I_FileLoader; import com.mike.aframe.http.utils.KJTaskExecutor; import com.mike.aframe.utils.FileUtils; import com.mike.aframe.utils.StringUtils; /** * update log * 1.1 httpUrlConnection? * 1.2 httpUrlConnection? * 1.3 httpClientpost?get?put? * 1.4 httpjson()? * 1.5 Http?cookie * 1.6 cache? */ /** * The HttpLibrary's core classes<br> * * <b></b> 2014-7-14<br> * <b></b> 2014-9-19 * * @author kymjs(kymjs123@gmail.com) * @version 1.5 */ public class KJHttp { private HttpConfig config; /** * ??httpLibrary */ public KJHttp(HttpConfig config) { this.config = config; if (config.isUseCache() && config.getCacher() == null) { // json??I_HttpCache??? this.config.setCacher(HttpCache.create()); } // httpClient?? initHttpClient(); } /** * http?httpLibrary */ public KJHttp() { this(new HttpConfig()); } /*********************** HttpURLConnection get *************************/ /** * HttpURLConnection??get * * @param url * ? * @param params * ?,?KJFileParams?KJStringParams * @param callback * ?FileCallBack?StringCallBack */ public void urlGet(String url, KJStringParams params, I_HttpRespond callback) { if (params != null) { StringBuilder str = new StringBuilder(url); str.append("?").append(params.toString()); url = str.toString(); } urlGet(url, callback); } /** * HttpURLConnection??get * * @param url * ? * @param callback * ?FileCallBack?StringCallBack */ public void urlGet(String url, I_HttpRespond callback) { new HttpUrlGetTask(callback, url).execute(); } /** * HttpUrlGet */ private class HttpUrlGetTask extends KJTaskExecutor<Void, Object, Object> { private I_HttpRespond callback; private String _url; private int code; public HttpUrlGetTask(I_HttpRespond callback, String _url) { this.callback = callback; this._url = _url; } @Override protected Object doInBackground(Void... params) { String res = null; if (config.isUseCache()) { res = config.getCacher().get(_url); } if (res != null) { // return res; } else { InputStream input = null; BufferedReader reader = null; StringBuilder respond = null; try { URL url = new URL(_url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setUseCaches(config.isUseCache()); conn.setReadTimeout(config.getReadTimeout()); conn.setConnectTimeout(config.getConnectTimeOut()); conn.setRequestProperty("Charset", config.getCharSet()); conn.setRequestMethod("GET"); String cookie = config.getCookie(); if (!StringUtils.isEmpty(cookie)) { conn.setRequestProperty("Cookie", cookie); } for (Map.Entry<String, String> entry : config.getHeader().entrySet()) { conn.setRequestProperty(entry.getKey(), entry.getValue()); } input = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(input)); int i = 0, current = 0; int count = conn.getContentLength(); char[] buf = new char[1024]; respond = new StringBuilder(); while ((i = reader.read(buf)) != -1) { respond.append(buf, 0, i); if (callback.isProgress()) { current += i; // ? publishProgress(count, current); } } code = conn.getResponseCode(); conn.disconnect(); } catch (MalformedURLException e) { return e; } catch (IOException e) { return e; } finally { FileUtils.closeIO(input, reader); } return respond; } } @Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); callback.onLoading((Long) values[0], (Long) values[1]); } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); if (result instanceof MalformedURLException) { callback.onFailure((Throwable) result, 3721, "URL"); } else if (result instanceof IOException) { callback.onFailure((Throwable) result, code, "IO"); } else { callback.onSuccess(result); if (config.isUseCache()) { config.getCacher().add(_url, result.toString()); } } } } /*********************** HttpURLConnection post *************************/ /** * HttpURLConnection??post * * @param url * ? * @param params * ?,?KJFileParams?KJStringParams * @param callback * ?FileCallBack?StringCallBack */ public void urlPost(String url, I_HttpParams params, I_HttpRespond callback) { if (params instanceof KJStringParams) { new HttpUrlPostTask(params, callback, url).execute(); } else if (params instanceof KJFileParams) { new HttpUrlFileTask((KJFileParams) params, callback).execute(url); } } /** * HttpUrlFile */ private class HttpUrlFileTask extends KJTaskExecutor<Object, Object, Object> { private I_HttpRespond callback; private KJFileParams params; private int code; public HttpUrlFileTask(KJFileParams param, I_HttpRespond callback) { this.callback = callback; this.params = param; } @Override protected Object doInBackground(Object... urls) { OutputStream out = null; DataInputStream in = null; BufferedReader reader = null; StringBuilder respond = null; String BOUNDARY = "---------7d4a6d158c9"; // ? try { URL url = new URL(urls[0].toString()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // ??POST conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod("GET"); conn.setReadTimeout(config.getReadTimeout()); conn.setConnectTimeout(config.getConnectTimeOut()); conn.setRequestProperty("Charset", config.getCharSet()); conn.setInstanceFollowRedirects(true); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); String cookie = config.getCookie(); if (!StringUtils.isEmpty(cookie)) { conn.setRequestProperty("Cookie", cookie); } for (Map.Entry<String, String> entry : config.getHeader().entrySet()) { conn.setRequestProperty(entry.getKey(), entry.getValue()); } out = new DataOutputStream(conn.getOutputStream()); byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// ?? int leng = params.fileParams.size(); for (int i = 0; i < leng; i++) { StringBuilder sb = new StringBuilder(); sb.append("--").append(BOUNDARY).append("\r\nContent-Disposition: form-data;name=\"") .append(HttpConfig.FileParamsKey).append(i).append("\";filename=\"") .append(HttpConfig.FileParamsName) .append("\"\r\nContent-Type:application/octet-stream\r\n\r\n"); byte[] data = sb.toString().getBytes(); out.write(data); in = new DataInputStream(params.fileParams.get(i)); int bytes = 0; byte[] buf = new byte[1024]; while ((bytes = in.read(buf)) != -1) { out.write(buf, 0, bytes); } out.write("\r\n".getBytes()); // } out.write(end_data); out.flush(); code = conn.getResponseCode(); reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); respond = new StringBuilder(); int i = 0; int current = 0; int count = conn.getContentLength(); char[] buf = new char[512]; while ((i = reader.read(buf)) != -1) { respond.append(buf, 0, i); if (callback.isProgress()) { current += i; // ? publishProgress(count, current); } } conn.disconnect(); } catch (MalformedURLException e) { return e; } catch (IOException e) { return e; } finally { FileUtils.closeIO(out, in, reader); } return respond; } @Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); callback.onLoading((Long) values[0], (Long) values[1]); } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); if (result instanceof MalformedURLException) { callback.onFailure((Throwable) result, 3721, "URL"); } else if (result instanceof IOException) { callback.onFailure((Throwable) result, code, "IO"); } else { callback.onSuccess(result); } } } /** * HttpUrlPost */ private class HttpUrlPostTask extends KJTaskExecutor<Void, Object, Object> { private I_HttpRespond callback; private I_HttpParams params; private String _url; private int code; public HttpUrlPostTask(I_HttpParams param, I_HttpRespond callback, String _url) { this.callback = callback; this.params = param; this._url = _url; } @Override protected Object doInBackground(Void... _void) { String res = null; if (config.isUseCache()) { res = config.getCacher().get(_url); } if (res != null) { // return res; } else { DataOutputStream out = null; InputStream input = null; BufferedReader reader = null; StringBuilder respond = null; try { URL url = new URL(_url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(config.getReadTimeout()); conn.setConnectTimeout(config.getConnectTimeOut()); conn.setRequestProperty("Charset", config.getCharSet()); conn.setRequestProperty("Content-Type", config.getContentType()); conn.setInstanceFollowRedirects(true); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestMethod("POST"); conn.setUseCaches(false); String cookie = config.getCookie(); if (!StringUtils.isEmpty(cookie)) { conn.setRequestProperty("Cookie", cookie); } for (Map.Entry<String, String> entry : config.getHeader().entrySet()) { conn.setRequestProperty(entry.getKey(), entry.getValue()); } conn.connect(); if (params != null) { out = new DataOutputStream(conn.getOutputStream()); out.writeBytes(params.toString()); out.flush(); } code = conn.getResponseCode(); input = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(input)); respond = new StringBuilder(); int i = 0; int current = 0; int count = conn.getContentLength(); char[] buf = new char[1024]; while ((i = reader.read(buf)) != -1) { respond.append(buf, 0, i); if (callback.isProgress()) { current += i; // ? publishProgress(count, current); } } conn.disconnect(); } catch (MalformedURLException e) { return e; } catch (IOException e) { return e; } finally { FileUtils.closeIO(out, input, reader); } return respond; } } @Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); callback.onLoading((Long) values[0], (Long) values[1]); } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); if (result instanceof MalformedURLException) { callback.onFailure((Throwable) result, 3721, "URL"); } else if (result instanceof IOException) { callback.onFailure((Throwable) result, code, "IO"); } else { callback.onSuccess(result); if (config.isUseCache()) { config.getCacher().add(_url, result.toString()); } } } } /*********************** HttpURLConnection *************************/ /** * HttpURLConnection?? * * @param url * URL * @param saveFile * ? * @param callback * ???FileCallBack */ public void urlDownload(String url, File saveFile, I_HttpRespond callback) { urlDownload(url, saveFile, true, callback); } /** * HttpURLConnection?? * * @param url * URL * @param absFilePath * ? * @param callback * ???FileCallBack */ public void urlDownload(String url, String absFilePath, I_HttpRespond callback) { urlDownload(url, absFilePath, true, callback); } /** * HttpURLConnection???? * * @param url * URL * @param absFilePath * ? * @param open * ?? * @param callback * ???FileCallBack */ private void urlDownload(String url, String absFilePath, boolean open, I_HttpRespond callback) { int s = absFilePath.lastIndexOf(File.separator); String dir = null; if (s > 0) { dir = absFilePath.substring(0, s); File file = new File(dir); file.mkdirs(); file = new File(absFilePath); try { file.createNewFile(); urlDownload(url, file, open, callback); } catch (IOException e) { throw new MKException("can not create file"); } } else { throw new MKException("can not create file dir"); } } /** * HttpURLConnection???? * * @param url * URL * @param saveFile * ? * @param open * ?? * @param callback * ???FileCallBack */ private void urlDownload(String url, File saveFile, boolean open, I_HttpRespond callback) { if (open) { new FileDownloadTask(saveFile, callback).execute(url); } else { } } /** * HttpUrl(?BUG?) */ private class FileDownloadTask extends KJTaskExecutor<Object, Object, Object> { private File saveFile; private I_HttpRespond callback; public FileDownloadTask(File saveFile, I_HttpRespond callback) { this.saveFile = saveFile; this.callback = callback; } @Override protected Object doInBackground(Object... urls) { try { // ?I_FileLoaderI_MulThreadLoader??? I_FileLoader result = config.getDownloader(); if (result == null) { result = new FileDownLoader(urls[0].toString(), saveFile, config.getDownThreadCount()); } result.download(callback); return result; } catch (MKException e) { return e; } } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); if (callback != null) { if (result instanceof I_FileLoader) { callback.onSuccess(this.saveFile); } else { MKException e = ((MKException) result); callback.onFailure(e, 3721, e.getMessage()); } } } } /**************************** HttpClient method ******************************/ private DefaultHttpClient httpClient; private ThreadPoolExecutor threadPool; private HttpContext httpContext; private Map<Context, List<WeakReference<Future<?>>>> requestMap; /** * ?httpClient */ private void initHttpClient() { BasicHttpParams httpParams = new BasicHttpParams(); ConnManagerParams.setTimeout(httpParams, config.getConnectTimeOut()); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(config.getMaxConnections())); ConnManagerParams.setMaxTotalConnections(httpParams, config.getMaxConnections()); HttpConnectionParams.setSoTimeout(httpParams, config.getConnectTimeOut()); HttpConnectionParams.setConnectionTimeout(httpParams, config.getConnectTimeOut()); HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpConnectionParams.setSocketBufferSize(httpParams, config.getSocketBuffer()); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setUserAgent(httpParams, "KJLibrary"); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry); httpContext = new SyncBasicHttpContext(new BasicHttpContext()); httpClient = new DefaultHttpClient(cm, httpParams); httpClient.addRequestInterceptor(new HttpRequestInterceptor() { @Override public void process(HttpRequest request, HttpContext context) { if (!request.containsHeader("Accept-Encoding")) { request.addHeader("Accept-Encoding", "gzip"); } for (Entry<String, String> entry : config.getHeader().entrySet()) { request.addHeader(entry.getKey(), entry.getValue()); } } }); httpClient.addResponseInterceptor(new HttpResponseInterceptor() { @Override public void process(HttpResponse response, HttpContext context) { final HttpEntity entity = response.getEntity(); if (entity == null) { return; } final Header encoding = entity.getContentEncoding(); if (encoding != null) { for (HeaderElement element : encoding.getElements()) { if (element.getName().equalsIgnoreCase("gzip")) { response.setEntity(new InflatingEntity(response.getEntity())); break; } } } } }); threadPool = (ThreadPoolExecutor) KJThreadExecutors.newCachedThreadPool(); httpClient.setHttpRequestRetryHandler(new RetryHandler(config.getReadTimeout())); requestMap = new WeakHashMap<Context, List<WeakReference<Future<?>>>>(); } /************************* HttpClient config method *************************/ /** * ?cookie * * @param cookieStore * The CookieStore implementation to use, usually an instance of * PersistentCookieStore */ public void setCookieStore(CookieStore cookieStore) { httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); } /** * ? * * @param userAgent * ? */ public void setUserAgent(String userAgent) { HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent); } /** * 10s * * @param timeout */ public void setTimeout(int timeout) { config.setReadTimeout(timeout); config.setConnectTimeOut(timeout); final HttpParams httpParams = this.httpClient.getParams(); ConnManagerParams.setTimeout(httpParams, timeout); HttpConnectionParams.setSoTimeout(httpParams, timeout); HttpConnectionParams.setConnectionTimeout(httpParams, timeout); } /** * https? * * @param sslSocketFactory */ public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { this.httpClient.getConnectionManager().getSchemeRegistry() .register(new Scheme("https", sslSocketFactory, 443)); } /** * http * * @param header * @param value */ public void addHeader(String header, String value) { config.getHeader().put(header, value); } /** * Sets basic authentication for the request. Uses AuthScope.ANY. This is * the same as setBasicAuth('username','password',AuthScope.ANY) * * @param user * @param pass */ public void setBasicAuth(String user, String pass) { AuthScope scope = AuthScope.ANY; setBasicAuth(user, pass, scope); } /** * Sets basic authentication for the request. You should pass in your * AuthScope for security. It should be like this * setBasicAuth("username","password", new * AuthScope("host",port,AuthScope.ANY_REALM)) * * @param user * @param pass * @param scope * - an AuthScope object * */ public void setBasicAuth(String user, String pass, AuthScope scope) { UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, pass); this.httpClient.getCredentialsProvider().setCredentials(scope, credentials); } /** * Cancels any pending (or potentially active) requests associated with the * passed Context. * <p> * <b>Note:</b> This will only affect requests which were created with a * non-null android Context. This method is intended to be used in the * onDestroy method of your android activities to destroy all requests which * are no longer required. * * @param context * the android Context instance associated to the request. * @param mayInterruptIfRunning * specifies if active requests should be cancelled along with * pending requests. */ public void cancelRequests(Context context, boolean mayInterruptIfRunning) { List<WeakReference<Future<?>>> requestList = requestMap.get(context); if (requestList != null) { for (WeakReference<Future<?>> requestRef : requestList) { Future<?> request = requestRef.get(); if (request != null) { request.cancel(mayInterruptIfRunning); } } } requestMap.remove(context); } /************************* HttpClient get *************************/ public void get(String url, HttpCallBack callback) { get(null, url, null, callback); } public void get(String url, KJStringParams params, HttpCallBack callback) { get(null, url, params, callback); } public void get(Context context, String url, HttpCallBack callback) { get(context, url, null, callback); } public void get(Context context, String url, KJStringParams params, HttpCallBack callback) { if (params != null) { StringBuilder str = new StringBuilder(url); str.append("?").append(params.toString()); url = str.toString(); } String res = null; if (config.isUseCache()) { res = config.getCacher().get(url); } if (res != null && callback != null) { // callback.onSuccess(res); } else { sendRequest(httpClient, httpContext, new HttpGet(url), null, callback, context); } } /************************* HttpClient post *************************/ public void post(String url, HttpCallBack callback) { post(null, url, null, callback); } public void post(String url, I_HttpParams params, HttpCallBack callback) { post(null, url, params, callback); } public void post(Context context, String url, I_HttpParams params, HttpCallBack callback) { post(context, url, paramsToEntity(params), null, callback); } public void post(Context context, String url, HttpEntity entity, String contentType, HttpCallBack callback) { String res = null; if (config.isUseCache()) { res = config.getCacher().get(url); } if (res != null && callback != null) { // callback.onSuccess(res); } else { sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPost(url), entity), contentType, callback, context); } } /************************* HttpClient post *************************/ public void put(String url, HttpCallBack callback) { put(null, url, null, callback); } public void put(String url, I_HttpParams params, HttpCallBack callback) { put(null, url, params, callback); } public void put(Context context, String url, I_HttpParams params, HttpCallBack callback) { put(context, url, paramsToEntity(params), null, callback); } public void put(Context context, String url, HttpEntity entity, String contentType, HttpCallBack callback) { String res = null; if (config.isUseCache()) { res = config.getCacher().get(url); } if (res != null && callback != null) { // callback.onSuccess(res); } else { sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPut(url), entity), contentType, callback, context); } } /************************ httpClient core method *******************************/ /** * ?? * * @param client * httpClient * @param callback * Http? * @param context */ protected void sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, HttpCallBack callback, Context context) { if (contentType != null) { uriRequest.addHeader("Content-Type", contentType); } Future<?> request = threadPool.submit(new AsyncHttpRequest(client, httpContext, uriRequest, callback)); if (context != null) { // List<WeakReference<Future<?>>> requestList = requestMap.get(context); if (requestList == null) { requestList = new LinkedList<WeakReference<Future<?>>>(); requestMap.put(context, requestList); } requestList.add(new WeakReference<Future<?>>(request)); } } /** * http???HttpEntity? * * @param params * @return */ private HttpEntity paramsToEntity(I_HttpParams params) { HttpEntity entity = null; if (params != null) { entity = params.getEntity(); } return entity; } private HttpEntityEnclosingRequestBase addEntityToRequestBase(HttpEntityEnclosingRequestBase requestBase, HttpEntity entity) { if (entity != null) { requestBase.setEntity(entity); } return requestBase; } /** * httpClient??? * * @author kymjs(kymjs123@gmail.com) * @version 1.0 * @created 2014-8-14 */ private static class InflatingEntity extends HttpEntityWrapper { public InflatingEntity(HttpEntity wrapped) { super(wrapped); } @Override public InputStream getContent() throws IOException { return new GZIPInputStream(wrappedEntity.getContent()); } @Override public long getContentLength() { return -1; } } /** * http * * @author kymjs(kymjs123@gmail.com) */ private class AsyncHttpRequest implements Runnable { private final AbstractHttpClient client; private final HttpContext context; private final HttpUriRequest request; private final HttpCallBack callback; private int executionCount; public AsyncHttpRequest(AbstractHttpClient client, HttpContext context, HttpUriRequest request, HttpCallBack callback) { this.client = client; this.context = context; this.request = request; this.callback = callback; } /** * */ private void makeRequest() throws IOException { if (!Thread.currentThread().isInterrupted()) { try { HttpResponse response = client.execute(request, context); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { if (!Thread.currentThread().isInterrupted() && callback != null) { callback.sendResponseMessage(request.getRequestLine().getUri(), config, response); } } else { if (callback != null) { callback.sendFailureMessage( new IOException("server respond " + response.getStatusLine().getStatusCode()), "http respond error"); } } } catch (IOException e) { if (!Thread.currentThread().isInterrupted()) { throw e; } } } } /** * ??? */ private void makeRequestWithRetries() throws ConnectException { boolean retry = true; IOException cause = null; HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler(); while (retry) { try { makeRequest(); return; } catch (UnknownHostException e) { if (callback != null) { callback.sendFailureMessage(e, "can't resolve host"); } return; } catch (SocketException e) { if (callback != null) { callback.sendFailureMessage(e, "can't resolve host"); } return; } catch (SocketTimeoutException e) { if (callback != null) { callback.sendFailureMessage(e, "socket time out"); } return; } catch (IOException e) { cause = e; retry = retryHandler.retryRequest(cause, ++executionCount, context); } catch (NullPointerException e) { cause = new IOException("NPE in HttpClient" + e.getMessage()); retry = retryHandler.retryRequest(cause, ++executionCount, context); } } ConnectException ex = new ConnectException(); ex.initCause(cause); throw ex; } @Override public void run() { try { makeRequestWithRetries(); } catch (IOException e) { if (callback != null) { callback.sendFailureMessage(e, "ConnectException"); } } } } }