AndroidHttpClient.java revision d2dcd7ada3e864de879dd64fbebd3a857b1bc181
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornpackage android.net.http; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 197cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilsonimport com.android.internal.http.HttpDateTime; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.Header; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpEntity; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpEntityEnclosingRequest; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpException; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpHost; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpRequest; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpRequestInterceptor; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpResponse; 28992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport org.apache.http.entity.AbstractHttpEntity; 29992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport org.apache.http.entity.ByteArrayEntity; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.HttpClient; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.ResponseHandler; 32992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport org.apache.http.client.ClientProtocolException; 33992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport org.apache.http.client.protocol.ClientContext; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.methods.HttpUriRequest; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.params.HttpClientParams; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.conn.ClientConnectionManager; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.conn.scheme.PlainSocketFactory; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.conn.scheme.Scheme; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.conn.scheme.SchemeRegistry; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.impl.client.DefaultHttpClient; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.impl.client.RequestWrapper; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.params.BasicHttpParams; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.params.HttpConnectionParams; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.params.HttpParams; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.params.HttpProtocolParams; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.protocol.BasicHttpProcessor; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.protocol.HttpContext; 49992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport org.apache.http.protocol.BasicHttpContext; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream; 53992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport java.io.ByteArrayOutputStream; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.zip.GZIPInputStream; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.zip.GZIPOutputStream; 57992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport java.net.URI; 58992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom 59992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.content.Context; 60992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.content.ContentResolver; 61992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.net.SSLCertificateSocketFactory; 62992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.net.SSLSessionCache; 63992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.os.Looper; 64992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.util.Base64; 65992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstromimport android.util.Log; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 687b91b31e28097b468db4cc2c6ac1a8e4064d8027Elliott Hughes * Implementation of the Apache {@link DefaultHttpClient} that is configured with 69d2dcd7ada3e864de879dd64fbebd3a857b1bc181Elliott Hughes * reasonable default settings and registered schemes for Android. 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't create this directly, use the {@link #newInstance} factory method. 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This client processes cookies but does not retain them by default. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To retain cookies, simply add a cookie store to the HttpContext:</p> 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre> 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class AndroidHttpClient implements HttpClient { 7860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Gzip of data shorter than this probably won't be worthwhile 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard // Default connection and socket timeout of 60 seconds. Tweak to taste. 83d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000; 84d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AndroidHttpClient"; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert private static String[] textContentTypes = new String[] { 88d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert "text/", 89d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert "application/xml", 90d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert "application/json" 91d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert }; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Interceptor throws an exception if the executing thread is blocked */ 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final HttpRequestInterceptor sThreadCheckInterceptor = 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HttpRequestInterceptor() { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void process(HttpRequest request, HttpContext context) { 977762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook // Prevent the HttpRequest from being sent on the main thread 987762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook if (Looper.myLooper() != null && Looper.myLooper() == Looper.getMainLooper() ) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("This thread forbids HTTP requests"); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new HttpClient with reasonable defaults (which you can update). 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @param userAgent to report in your HTTP requests 10860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor * @param context to use for caching SSL sessions (may be null for no caching) 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return AndroidHttpClient for you to use for all your requests. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor public static AndroidHttpClient newInstance(String userAgent, Context context) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpParams params = new BasicHttpParams(); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Turn off stale checking. Our connections break all the time anyway, 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and it's not worth it to pay the penalty of checking every time. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpConnectionParams.setStaleCheckingEnabled(params, false); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 118d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT); 119d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpConnectionParams.setSocketBufferSize(params, 8192); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't handle redirects -- return them to the caller. Our code 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // often wants to re-POST after a redirect, which we must do ourselves. 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpClientParams.setRedirecting(params, false); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12660586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor // Use a session cache for SSL sockets 12760586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context); 12860586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the specified user agent and register standard protocols. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpProtocolParams.setUserAgent(params, userAgent); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SchemeRegistry schemeRegistry = new SchemeRegistry(); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project schemeRegistry.register(new Scheme("http", 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PlainSocketFactory.getSocketFactory(), 80)); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project schemeRegistry.register(new Scheme("https", 135d39fd5a97c6f56794a6ed7ac1dfb0bbf585becf1Henrik Baard SSLCertificateSocketFactory.getHttpSocketFactory( 136992f238d13fff7c21b60ef6958784a4ed2156784Brian Carlstrom SOCKET_OPERATION_TIMEOUT, sessionCache), 443)); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientConnectionManager manager = 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new ThreadSafeClientConnManager(params, schemeRegistry); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We use a factory method to modify superclass initialization 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // parameters without the funny call-a-static-method dance. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new AndroidHttpClient(manager, params); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new HttpClient with reasonable defaults (which you can update). 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param userAgent to report in your HTTP requests. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return AndroidHttpClient for you to use for all your requests. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static AndroidHttpClient newInstance(String userAgent) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return newInstance(userAgent, null /* session cache */); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HttpClient delegate; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private RuntimeException mLeakedException = new IllegalStateException( 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "AndroidHttpClient created and never closed"); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.delegate = new DefaultHttpClient(ccm, params) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected BasicHttpProcessor createHttpProcessor() { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add interceptor to prevent making requests from main thread. 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BasicHttpProcessor processor = super.createHttpProcessor(); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project processor.addRequestInterceptor(sThreadCheckInterceptor); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project processor.addRequestInterceptor(new CurlLogger()); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return processor; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected HttpContext createHttpContext() { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Same as DefaultHttpClient.createHttpContext() minus the 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cookie store. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpContext context = new BasicHttpContext(); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.setAttribute( 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientContext.AUTHSCHEME_REGISTRY, 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getAuthSchemes()); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.setAttribute( 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientContext.COOKIESPEC_REGISTRY, 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getCookieSpecs()); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.setAttribute( 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientContext.CREDS_PROVIDER, 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getCredentialsProvider()); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return context; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLeakedException != null) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Leak found", mLeakedException); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLeakedException = null; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Modifies a request to indicate to the server that we would like a 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gzipped response. (Uses the "Accept-Encoding" HTTP header.) 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param request the request to modify 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #getUngzippedContent 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void modifyRequestToAcceptGzipResponse(HttpRequest request) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project request.addHeader("Accept-Encoding", "gzip"); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the input stream from a response entity. If the entity is gzipped 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then this will get a stream over the uncompressed data. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param entity the entity whose content should be read 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the input stream to read from 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static InputStream getUngzippedContent(HttpEntity entity) 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project InputStream responseStream = entity.getContent(); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (responseStream == null) return responseStream; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Header header = entity.getContentEncoding(); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (header == null) return responseStream; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String contentEncoding = header.getValue(); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (contentEncoding == null) return responseStream; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (contentEncoding.contains("gzip")) responseStream 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new GZIPInputStream(responseStream); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return responseStream; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Release resources associated with this client. You must call this, 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or significant resources (sockets and memory) may be leaked. 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLeakedException != null) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getConnectionManager().shutdown(); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLeakedException = null; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HttpParams getParams() { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.getParams(); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ClientConnectionManager getConnectionManager() { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.getConnectionManager(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HttpResponse execute(HttpUriRequest request) throws IOException { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(request); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HttpResponse execute(HttpUriRequest request, HttpContext context) 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(request, context); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HttpResponse execute(HttpHost target, HttpRequest request) 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(target, request); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HttpResponse execute(HttpHost target, HttpRequest request, 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpContext context) throws IOException { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(target, request, context); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T execute(HttpUriRequest request, 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResponseHandler<? extends T> responseHandler) 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException, ClientProtocolException { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(request, responseHandler); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T execute(HttpUriRequest request, 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResponseHandler<? extends T> responseHandler, HttpContext context) 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException, ClientProtocolException { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(request, responseHandler, context); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T execute(HttpHost target, HttpRequest request, 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResponseHandler<? extends T> responseHandler) throws IOException, 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientProtocolException { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(target, request, responseHandler); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T execute(HttpHost target, HttpRequest request, 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResponseHandler<? extends T> responseHandler, HttpContext context) 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException, ClientProtocolException { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return delegate.execute(target, request, responseHandler, context); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compress data to send to server. 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a Http Entity holding the gzipped data. 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The data will not be compressed if it is too short. 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param data The bytes to compress 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Entity holding the data 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver) 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AbstractHttpEntity entity; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data.length < getMinGzipSize(resolver)) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entity = new ByteArrayEntity(data); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ByteArrayOutputStream arr = new ByteArrayOutputStream(); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OutputStream zipper = new GZIPOutputStream(arr); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project zipper.write(data); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project zipper.close(); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entity = new ByteArrayEntity(arr.toByteArray()); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entity.setContentEncoding("gzip"); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return entity; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves the minimum size for compressing data. 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shorter data will not be compressed. 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getMinGzipSize(ContentResolver resolver) { 32160586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor return DEFAULT_SYNC_MIN_GZIP_BYTES; // For now, this is just a constant. 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* cURL logging support. */ 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Logging tag and level. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class LoggingConfiguration { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final String tag; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int level; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LoggingConfiguration(String tag, int level) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.tag = tag; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.level = level; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns true if logging is turned on for this configuration. 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isLoggable() { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Log.isLoggable(tag, level); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prints a message using this configuration. 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void println(String message) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.println(level, tag, message); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** cURL logging configuration. */ 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private volatile LoggingConfiguration curlConfiguration; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables cURL request logging for this client. 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name to log messages with 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param level at which to log messages (see {@link android.util.Log}) 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void enableCurlLogging(String name, int level) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == null) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NullPointerException("name"); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (level < Log.VERBOSE || level > Log.ASSERT) { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Level is out of range [" 369d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert + Log.VERBOSE + ".." + Log.ASSERT + "]"); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project curlConfiguration = new LoggingConfiguration(name, level); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Disables cURL logging for this client. 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void disableCurlLogging() { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project curlConfiguration = null; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Logs cURL commands equivalent to requests. 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class CurlLogger implements HttpRequestInterceptor { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void process(HttpRequest request, HttpContext context) 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws HttpException, IOException { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LoggingConfiguration configuration = curlConfiguration; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (configuration != null 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && configuration.isLoggable() 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && request instanceof HttpUriRequest) { 39260586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor // Never print auth token -- we used to check ro.secure=0 to 39360586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor // enable that, but can't do that in unbundled code. 39460586f2ec65d16d185767fce4311d3ed0e9112acDan Egnor configuration.println(toCurl((HttpUriRequest) request, false)); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Generates a cURL command equivalent to the given request. 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder builder = new StringBuilder(); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append("curl "); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Header header: request.getAllHeaders()) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!logAuthToken 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (header.getName().equals("Authorization") || 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header.getName().equals("Cookie"))) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append("--header \""); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append(header.toString().trim()); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append("\" "); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project URI uri = request.getURI(); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this is a wrapped request, use the URI from the original 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // request instead. getURI() on the wrapper seems to return a 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // relative URI. We want an absolute URI. 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (request instanceof RequestWrapper) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpRequest original = ((RequestWrapper) request).getOriginal(); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (original instanceof HttpUriRequest) { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uri = ((HttpUriRequest) original).getURI(); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append("\""); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append(uri); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append("\""); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (request instanceof HttpEntityEnclosingRequest) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpEntityEnclosingRequest entityRequest = 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (HttpEntityEnclosingRequest) request; 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HttpEntity entity = entityRequest.getEntity(); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entity != null && entity.isRepeatable()) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entity.getContentLength() < 1024) { 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ByteArrayOutputStream stream = new ByteArrayOutputStream(); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entity.writeTo(stream); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 443d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert if (isBinaryContent(request)) { 444d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert String base64 = Base64.encodeToString(stream.toByteArray(), Base64.NO_WRAP); 445d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert builder.insert(0, "echo '" + base64 + "' | base64 -d > /tmp/$$.bin; "); 446d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert builder.append(" --data-binary @/tmp/$$.bin"); 447d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } else { 448d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert String entityString = stream.toString(); 449d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert builder.append(" --data-ascii \"") 450d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert .append(entityString) 451d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert .append("\""); 452d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.append(" [TOO MUCH DATA TO INCLUDE]"); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return builder.toString(); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4617cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson 462d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert private static boolean isBinaryContent(HttpUriRequest request) { 463d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert Header[] headers; 464d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert headers = request.getHeaders(Headers.CONTENT_ENCODING); 465d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert if (headers != null) { 466d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert for (Header header : headers) { 467d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert if ("gzip".equalsIgnoreCase(header.getValue())) { 468d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert return true; 469d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 470d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 471d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 472d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert 473d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert headers = request.getHeaders(Headers.CONTENT_TYPE); 474d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert if (headers != null) { 475d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert for (Header header : headers) { 476d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert for (String contentType : textContentTypes) { 477d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert if (header.getValue().startsWith(contentType)) { 478d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert return false; 479d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 480d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 481d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 482d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 483d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert return true; 484d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert } 485d81689aefcf57cfb692b73161b1a00511a90ee1eAlon Albert 4867cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson /** 4877cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * Returns the date of the given HTTP date string. This method can identify 4887cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * and parse the date formats emitted by common HTTP servers, such as 4897cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>, 4907cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * <a href="http://www.ietf.org/rfc/rfc0850.txt">RFC 850</a>, 4917cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * <a href="http://www.ietf.org/rfc/rfc1036.txt">RFC 1036</a>, 4927cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</a> and 4937cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/asctime.html">ANSI 4947cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * C's asctime()</a>. 4957cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * 4967cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * @return the number of milliseconds since Jan. 1, 1970, midnight GMT. 4977cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * @throws IllegalArgumentException if {@code dateString} is not a date or 4987cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson * of an unsupported format. 4997cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson */ 5007cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson public static long parseDate(String dateString) { 5017cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson return HttpDateTime.parse(dateString); 5027cfa90fee54f44831ac492891d1c123601c2a262Jesse Wilson } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 504