1b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/* 2b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Copyright 2008 Sean Sullivan 3b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 4b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Licensed under the Apache License, Version 2.0 (the "License"); 5b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * you may not use this file except in compliance with the License. 6b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * You may obtain a copy of the License at 7b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 8b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * http://www.apache.org/licenses/LICENSE-2.0 9b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 10b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Unless required by applicable law or agreed to in writing, software 11b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * distributed under the License is distributed on an "AS IS" BASIS, 12b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * See the License for the specific language governing permissions and 14b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * limitations under the License. 15b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */ 16b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 17b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpackage net.oauth.client.httpclient4; 18b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 19b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.IOException; 20b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.InputStream; 21b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.net.URL; 22b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.util.Map; 23b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.client.ExcerptInputStream; 24b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.http.HttpMessage; 25b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.http.HttpResponseMessage; 26b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.HttpResponse; 27b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.HttpClient; 28b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpDelete; 29b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpEntityEnclosingRequestBase; 30b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpGet; 31b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpPost; 32b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpPut; 33b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.methods.HttpRequestBase; 34b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.client.params.ClientPNames; 35b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.conn.ClientConnectionManager; 36b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.entity.InputStreamEntity; 37b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.impl.client.DefaultHttpClient; 38b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 39b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport org.apache.http.params.HttpParams; 40b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 41b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/** 42b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Utility methods for an OAuth client based on the <a 43b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * href="http://hc.apache.org">Apache HttpClient</a>. 44b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * 45b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @author Sean Sullivan 46b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @hide 47b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */ 48b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpublic class HttpClient4 implements net.oauth.http.HttpClient { 49b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 50b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien public HttpClient4() { 51b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien this(SHARED_CLIENT); 52b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 53b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 54b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien public HttpClient4(HttpClientPool clientPool) { 55b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien this.clientPool = clientPool; 56b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 57b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 58b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private final HttpClientPool clientPool; 59b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 60b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien public HttpResponseMessage execute(HttpMessage request) throws IOException { 61b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final String method = request.method; 62b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final String url = request.url.toExternalForm(); 63b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final InputStream body = request.getBody(); 64b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final boolean isDelete = DELETE.equalsIgnoreCase(method); 65b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final boolean isPost = POST.equalsIgnoreCase(method); 66b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien final boolean isPut = PUT.equalsIgnoreCase(method); 67b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien byte[] excerpt = null; 68b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpRequestBase httpRequest; 69b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (isPost || isPut) { 70b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpEntityEnclosingRequestBase entityEnclosingMethod = 71b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien isPost ? new HttpPost(url) : new HttpPut(url); 72b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (body != null) { 73b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien ExcerptInputStream e = new ExcerptInputStream(body); 74b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien excerpt = e.getExcerpt(); 75b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien String length = request.removeHeaders(HttpMessage.CONTENT_LENGTH); 76b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien entityEnclosingMethod.setEntity(new InputStreamEntity(e, 77b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien (length == null) ? -1 : Long.parseLong(length))); 78b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 79b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien httpRequest = entityEnclosingMethod; 80b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else if (isDelete) { 81b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien httpRequest = new HttpDelete(url); 82b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } else { 83b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien httpRequest = new HttpGet(url); 84b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 85b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien for (Map.Entry<String, String> header : request.headers) { 86b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien httpRequest.addHeader(header.getKey(), header.getValue()); 87b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 88b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpClient client = clientPool.getHttpClient(new URL(httpRequest.getURI().toString())); 89b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); 90b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpResponse httpResponse = client.execute(httpRequest); 91b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return new HttpMethodResponse(httpRequest, httpResponse, excerpt, request.getContentCharset()); 92b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 93b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 94b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private static final HttpClientPool SHARED_CLIENT = new SingleClient(); 95b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 96b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien /** 97b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * A pool that simply shares a single HttpClient. An HttpClient owns a pool 98b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * of TCP connections. So, callers that share an HttpClient will share 99b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * connections. Sharing improves performance (by avoiding the overhead of 100b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * creating connections) and uses fewer resources in the client and its 101b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * servers. 102b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */ 103b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private static class SingleClient implements HttpClientPool 104b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien { 105b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien SingleClient() 106b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien { 107b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpClient client = new DefaultHttpClient(); 108b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien ClientConnectionManager mgr = client.getConnectionManager(); 109b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien if (!(mgr instanceof ThreadSafeClientConnManager)) { 110b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien HttpParams params = client.getParams(); 111b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, 112b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien mgr.getSchemeRegistry()), params); 113b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 114b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien this.client = client; 115b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 116b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 117b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien private final HttpClient client; 118b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 119b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien public HttpClient getHttpClient(URL server) 120b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien { 121b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien return client; 122b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 123b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien } 124b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien 125b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien} 126