package com.apigee.sdk.apm.android; import android.net.http.AndroidHttpClient; import com.apigee.sdk.AppIdentification; import com.apigee.sdk.apm.http.impl.client.cache.CachingHttpClient; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.BasicHttpProcessor; import org.apache.http.protocol.HttpContext; import java.io.IOException; import java.util.Properties; /** * @y.exclude */ public class HttpClientWrapper implements HttpClient { public static final String ATTR_DELEGATE_EXCEPTION = "delegate_exception"; public static final String ATTR_DELEGATE_EXCEPTION_OCCURRED = "delegate_exception_occurred"; public static final String ATTR_OVERRIDDEN_RESPONSE = "overridden_response"; public static final String ATTR_SKIP_PROCESSING = "skip_processing"; private HttpClient delgatedHttpClientImpl; private AppIdentification appIdentification; private NetworkMetricsCollectorService metricsCollector; private ApigeeActiveSettings activeSettings; BasicHttpProcessor httpproc = new BasicHttpProcessor(); CachingHttpClient cachingClient; public CachingHttpClient getCachingClient() { return cachingClient; } // Added constructor to make this look closer to Apache's HttpClient constructors public HttpClientWrapper(AppIdentification appIdentification, NetworkMetricsCollectorService metricsCollector, ApigeeActiveSettings activeSettings) { HttpClient delegateClient = AndroidHttpClient.newInstance(appIdentification.getApplicationId()); initialize(appIdentification, metricsCollector, activeSettings, delegateClient); } public HttpClientWrapper(HttpClient delegateClient, AppIdentification appIdentification, NetworkMetricsCollectorService metricsCollector, ApigeeActiveSettings activeSettings) { initialize(appIdentification, metricsCollector, activeSettings, delegateClient); } /** * * * @return HttpProcessor with WebManager specific clients */ protected BasicHttpProcessor createHttpProcessor() { BasicHttpProcessor httpproc = new BasicHttpProcessor(); /** * In this section, add interceptors */ PerformanceMonitoringInterceptor performanceMonitoringInterceptor = new PerformanceMonitoringInterceptor(); performanceMonitoringInterceptor .setMetricsCollector(this.metricsCollector); httpproc.addInterceptor((HttpRequestInterceptor) performanceMonitoringInterceptor); httpproc.addInterceptor((HttpResponseInterceptor) performanceMonitoringInterceptor); return httpproc; } protected void initialize(AppIdentification appIdentification, NetworkMetricsCollectorService metricsCollector, ApigeeActiveSettings activeSettings, HttpClient delegateClient) { this.appIdentification = appIdentification; this.metricsCollector = metricsCollector; this.activeSettings = activeSettings; // Initialize the default http client // TODO: Need to read the props for default client connection parameter delgatedHttpClientImpl = delegateClient; if (activeSettings.getCachingEnabled()) { cachingClient = new CachingHttpClient(delegateClient,activeSettings.getCacheConfig()); delgatedHttpClientImpl = cachingClient; } httpproc = createHttpProcessor(); } public ApigeeActiveSettings getActiveSettings() { return activeSettings; } public NetworkMetricsCollectorService getMetricsCollector() { return metricsCollector; } public String getAppId() { return appIdentification.getApplicationId(); } protected void captureRequest(HttpUriRequest request, HttpContext context) throws IOException { try { httpproc.process(request, context); } catch (HttpException e) { throw new ClientProtocolException(e); } } protected void captureRequest(HttpRequest request, HttpContext context) throws IOException { try { httpproc.process(request, context); } catch (HttpException e) { throw new ClientProtocolException(e); } } protected void captureResponse(HttpResponse response, HttpContext context) throws IOException { try { httpproc.process(response, context); } catch (HttpException e) { throw new ClientProtocolException(e); } } @Override public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException { return execute(request, new BasicHttpContext()); } @Override public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException, ClientProtocolException { //TODO: should we be using the startTime? //long startTime = System.currentTimeMillis(); boolean errorOccurred = false; // Pre-Process requests captureRequest(request, context); HttpResponse response = null; try { if ((context != null) && (context.getAttribute(ATTR_SKIP_PROCESSING) != null) && (Boolean) context.getAttribute(ATTR_SKIP_PROCESSING)) { response = (HttpResponse) context .getAttribute(ATTR_OVERRIDDEN_RESPONSE); } else { response = delgatedHttpClientImpl.execute(request); } } catch (ClientProtocolException e) { errorOccurred = true; if (context != null) { context.setAttribute(ATTR_DELEGATE_EXCEPTION_OCCURRED, errorOccurred); context.setAttribute(ATTR_DELEGATE_EXCEPTION, e); } throw e; } catch (IOException e) { errorOccurred = true; if (context != null) { context.setAttribute(ATTR_DELEGATE_EXCEPTION_OCCURRED, errorOccurred); context.setAttribute(ATTR_DELEGATE_EXCEPTION, e); } throw e; } finally { captureResponse(response, context); } return response; } @Override public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException { final HttpContext context = new BasicHttpContext(); return execute(request, responseHandler, context); } @Override public <T> T execute(HttpUriRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException { // Pre-Process requests ResponseHandler<? extends T> wrappedHandler = new ResponseHandler<T>() { @Override public T handleResponse(HttpResponse theResponse) throws ClientProtocolException, IOException { captureResponse(theResponse, context); return responseHandler.handleResponse(theResponse); } }; captureRequest(request, context); HttpResponse response; if ((context != null) && (context.getAttribute(ATTR_SKIP_PROCESSING) != null) && (Boolean) context.getAttribute(ATTR_SKIP_PROCESSING)) { response = (HttpResponse) context .getAttribute(ATTR_OVERRIDDEN_RESPONSE); T result; result = wrappedHandler.handleResponse(response); return result; } else { // TODO: Need to add proper error handling. Really need to put in // the correct wrapper T result = delgatedHttpClientImpl.execute(request, wrappedHandler); return result; } } @Override public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException, ClientProtocolException { HttpContext context = null; return execute(target, request, context); } @Override public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException, ClientProtocolException { boolean errorOccurred = false; if (context == null) { context = new BasicHttpContext(); } // Pre-Process requests captureRequest(request, context); HttpResponse response = null; try { if ((context.getAttribute(ATTR_SKIP_PROCESSING) != null) && (Boolean) context.getAttribute(ATTR_SKIP_PROCESSING)) { response = (HttpResponse) context .getAttribute(ATTR_OVERRIDDEN_RESPONSE); } else { response = delgatedHttpClientImpl.execute(target, request, context); } } catch (ClientProtocolException e) { errorOccurred = true; context.setAttribute(ATTR_DELEGATE_EXCEPTION_OCCURRED, errorOccurred); context.setAttribute(ATTR_DELEGATE_EXCEPTION, e); throw e; } catch (IOException e) { errorOccurred = true; context.setAttribute(ATTR_DELEGATE_EXCEPTION_OCCURRED, errorOccurred); context.setAttribute(ATTR_DELEGATE_EXCEPTION, e); throw e; } finally { captureResponse(response, context); } return response; } @Override public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException { HttpContext context = new BasicHttpContext(); return execute(target, request, responseHandler, context); } @Override public <T> T execute(HttpHost target, HttpRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException { ResponseHandler<? extends T> wrappedHandler = new ResponseHandler<T>() { @Override public T handleResponse(HttpResponse theResponse) throws ClientProtocolException, IOException { captureResponse(theResponse, context); return responseHandler.handleResponse(theResponse); } }; captureRequest(request, context); HttpResponse response; if ((context != null) && (context.getAttribute(ATTR_SKIP_PROCESSING) != null) && (Boolean) context.getAttribute(ATTR_SKIP_PROCESSING)) { response = (HttpResponse) context .getAttribute(ATTR_OVERRIDDEN_RESPONSE); T result; result = wrappedHandler.handleResponse(response); return result; } else { // TODO: Need to add proper error handling. Really need to put in // the correct wrapper T result = delgatedHttpClientImpl.execute(target, request, wrappedHandler, context); return result; } } @Override public ClientConnectionManager getConnectionManager() { return delgatedHttpClientImpl.getConnectionManager(); } @Override public HttpParams getParams() { return delgatedHttpClientImpl.getParams(); } /** * @return the delgatedHttpClientImpl */ public HttpClient getDelgatedHttpClientImpl() { return delgatedHttpClientImpl; } /** * Still in progress */ /** * * This function basically kills the existing HTTP Client and initializes * the HTTP Client with a new set of parameters. * * * * * @param properties * - */ public void initializeHttpClient(Properties properties) { // Shutdown existing httpClient ClientConnectionManager connectionManager = this.delgatedHttpClientImpl .getConnectionManager(); connectionManager.shutdown(); } }