My apologies, this change got pushed along with my other changeset that cleans up some unit tests to use junit 4 annotations...
Pending review I'll leave it in, but will happily revert if anyone has a -1 on it. ---------- Forwarded message ---------- From: <lind...@apache.org> Date: Mon, Feb 1, 2010 at 3:05 PM Subject: svn commit: r905439 - in /incubator/shindig/trunk: ./ java/common/src/main/java/org/apache/shindig/common/cache/ java/gadgets/ java/gadgets/src/main/java/org/apache/shindig/gadgets/http/ java/samples/ java/social-api/ java/social-api/src/main/java/org/... To: shindig-comm...@incubator.apache.org Author: lindner Date: Mon Feb 1 23:05:43 2010 New Revision: 905439 URL: http://svn.apache.org/viewvc?rev=905439&view=rev Log: httpclient 4.0 upgrade Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/cache/LruCacheProvider.java incubator/shindig/trunk/java/gadgets/pom.xml incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java incubator/shindig/trunk/java/samples/pom.xml incubator/shindig/trunk/java/social-api/pom.xml incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/sample/service/SampleContainerHandler.java incubator/shindig/trunk/pom.xml Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/cache/LruCacheProvider.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/cache/LruCacheProvider.java?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/cache/LruCacheProvider.java (original) +++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/cache/LruCacheProvider.java Mon Feb 1 23:05:43 2010 @@ -84,12 +84,12 @@ public <K, V> Cache<K, V> createCache(String name) { int capacity = getCapacity(name); if (name == null) { - LOG.info("Creating anonymous cache"); + LOG.fine("Creating anonymous cache"); return new LruCache<K, V>(capacity); } else { Cache<K, V> cache = (Cache<K, V>) caches.get(name); if (cache == null) { - LOG.info("Creating cache named " + name); + LOG.fine("Creating cache named " + name); cache = new LruCache<K, V>(capacity); caches.put(name, cache); } Modified: incubator/shindig/trunk/java/gadgets/pom.xml URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/pom.xml?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/pom.xml (original) +++ incubator/shindig/trunk/java/gadgets/pom.xml Mon Feb 1 23:05:43 2010 @@ -143,7 +143,7 @@ </dependency> <dependency> <groupId>net.oauth.core</groupId> - <artifactId>oauth-httpclient3</artifactId> + <artifactId>oauth-httpclient4</artifactId> </dependency> <dependency> <groupId>com.google.collections</groupId> @@ -208,8 +208,9 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.0.1</version> </dependency> <!-- test --> Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java Mon Feb 1 23:05:43 2010 @@ -17,259 +17,386 @@ */ package org.apache.shindig.gadgets.http; -import com.google.inject.internal.Preconditions; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.methods.DeleteMethod; -import org.apache.commons.httpclient.methods.EntityEnclosingMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.HeadMethod; -import org.apache.commons.httpclient.methods.InputStreamRequestEntity; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.PutMethod; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.shindig.common.uri.Uri; - -import com.google.common.collect.Maps; +import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Singleton; +import com.google.inject.internal.Preconditions; import com.google.inject.name.Named; -import java.io.ByteArrayInputStream; +import org.apache.commons.lang.StringUtils; +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpRequestInterceptor; +import org.apache.http.HttpResponseInterceptor; +import org.apache.http.HttpVersion; +import org.apache.http.NoHttpResponseException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +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.params.ClientPNames; +import org.apache.http.client.params.HttpClientParams; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.ConnectionPoolTimeoutException; +import org.apache.http.conn.HttpHostConnectException; +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.entity.InputStreamEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.conn.ProxySelectorRoutePlanner; +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.HttpContext; +import org.apache.http.util.EntityUtils; + import java.io.IOException; import java.io.InputStream; -import java.net.InetSocketAddress; -import java.net.Proxy; import java.net.ProxySelector; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; /** - * A very primitive HTTP fetcher implementation. Not recommended for production deployments until + * A simple HTTP fetcher implementation based on Apache httpclient. Not recommended for production deployments until * the following issues are addressed: - * + * <p/> * 1. This class potentially allows access to resources behind an organization's firewall. - * 2. This class does not handle most advanced HTTP functionality correctly (SSL, etc.) - * 3. This class does not enforce any limits on what is fetched from remote hosts. + * 2. This class does not enforce any limits on what is fetched from remote hosts. */ @Singleton public class BasicHttpFetcher implements HttpFetcher { private static final int DEFAULT_CONNECT_TIMEOUT_MS = 5000; + private static final int DEFAULT_READ_TIMEOUT_MS = 5000; private static final int DEFAULT_MAX_OBJECT_SIZE = 0; // no limit - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + private static final long DEFAULT_SLOW_RESPONSE_WARNING = 10000; + + protected final HttpClient FETCHER; // mutable fields must be volatile - private volatile int maxObjSize; - private volatile int connectionTimeoutMs; + private volatile int maxObjSize; + private volatile long slowResponseWarning; - /** - * Creates a new fetcher for fetching HTTP objects. Not really suitable - * for production use. Use of an HTTP proxy for security is also necessary - * for production deployment. - * - * @param maxObjSize Maximum size, in bytes, of the object we will fetch, 0 if no limit.. - * @param connectionTimeoutMs timeout, in milliseconds, for requests. - */ - public BasicHttpFetcher(int maxObjSize, int connectionTimeoutMs) { - setMaxObjectSizeBytes(maxObjSize); - setConnectionTimeoutMs(connectionTimeoutMs); - } + private static final Logger LOG = Logger.getLogger(BasicHttpFetcher.class.getName()); + + private final Set<Class<?>> TIMEOUT_EXCEPTIONS = ImmutableSet.<Class<?>>of(ConnectionPoolTimeoutException.class, + SocketTimeoutException.class, SocketException.class, HttpHostConnectException.class, NoHttpResponseException.class, + InterruptedException.class, UnknownHostException.class); /** * Creates a new fetcher using the default maximum object size and timeout -- * no limit and 5 seconds. */ public BasicHttpFetcher() { - this(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_CONNECT_TIMEOUT_MS); + this(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_READ_TIMEOUT_MS); } - /** - * Change the global maximum fetch size (in bytes) for all fetches. - * - * @param maxObjectSizeBytes value for maximum number of bytes, or 0 for no limit - */ - @Inject(optional = true) - public void setMaxObjectSizeBytes(@Named("shindig.http.client.max-object-size-bytes") int maxObjectSizeBytes) { - this.maxObjSize = maxObjectSizeBytes; + @Deprecated + public BasicHttpFetcher(int maxObjSize, int connectionTimeoutMs) { + this(maxObjSize, connectionTimeoutMs, DEFAULT_READ_TIMEOUT_MS); } /** - * Change the global connection timeout for all fetchs. + * Creates a new fetcher for fetching HTTP objects. Not really suitable + * for production use. Use of an HTTP proxy for security is also necessary + * for production deployment. * - * @param connectionTimeoutMs new connection timeout in milliseconds + * @param maxObjSize Maximum size, in bytes, of the object we will fetch, 0 if no limit.. + * @param connectionTimeoutMs timeout, in milliseconds, for connecting to hosts. + * @param readTimeoutMs timeout, in millseconds, for unresponsive connections */ - @Inject(optional = true) - public void setConnectionTimeoutMs(@Named("shindig.http.client.connection-timeout-ms") int connectionTimeoutMs) { - Preconditions.checkArgument(connectionTimeoutMs > 0, "connection-timeout-ms must be greater than 0"); - this.connectionTimeoutMs = connectionTimeoutMs; - } + public BasicHttpFetcher(int maxObjSize, int connectionTimeoutMs, int readTimeoutMs) { + // Create and initialize HTTP parameters + setMaxObjectSizeBytes(maxObjSize); + setSlowResponseWarning(DEFAULT_SLOW_RESPONSE_WARNING); - /** - * @param httpMethod - * @param responseCode - * @return A HttpResponse object made by consuming the response of the - * given HttpMethod. - * @throws java.io.IOException - */ - private HttpResponse makeResponse(HttpMethod httpMethod, int responseCode) throws IOException { - Map<String, String> headers = Maps.newHashMap(); + HttpParams params = new BasicHttpParams(); + + ConnManagerParams.setTimeout(params, connectionTimeoutMs); + + // These are probably overkill for most sites. + ConnManagerParams.setMaxTotalConnections(params, 1152); + ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(256)); - if (httpMethod.getResponseHeaders() != null) { - for (Header h : httpMethod.getResponseHeaders()) { - headers.put(h.getName(), h.getValue()); + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); + HttpProtocolParams.setUserAgent(params, "Apache Shindig"); + HttpProtocolParams.setContentCharset(params, "UTF-8"); + + HttpConnectionParams.setConnectionTimeout(params, connectionTimeoutMs); + HttpConnectionParams.setSoTimeout(params, readTimeoutMs); + HttpConnectionParams.setStaleCheckingEnabled(params, true); + + HttpClientParams.setRedirecting(params, true); + HttpClientParams.setAuthenticating(params, false); + + // Create and initialize scheme registry + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); + + ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); + + DefaultHttpClient client = new DefaultHttpClient(cm, params); + + // try resending the request once + client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(1, true)); + + // Add hooks for gzip/deflate + client.addRequestInterceptor(new HttpRequestInterceptor() { + public void process( + final org.apache.http.HttpRequest request, + final HttpContext context) throws HttpException, IOException { + if (!request.containsHeader("Accept-Encoding")) { + request.addHeader("Accept-Encoding", "gzip, deflate"); + } } - } + }); + client.addResponseInterceptor(new HttpResponseInterceptor() { + public void process( + final org.apache.http.HttpResponse response, + final HttpContext context) throws HttpException, IOException { + HttpEntity entity = response.getEntity(); + if (entity != null) { + Header ceheader = entity.getContentEncoding(); + if (ceheader != null) { + for (HeaderElement codec : ceheader.getElements()) { + String codecname = codec.getName(); + if ("gzip".equalsIgnoreCase(codecname)) { + response.setEntity( + new GzipDecompressingEntity(response.getEntity())); + return; + } else if ("deflate".equals(codecname)) { + response.setEntity(new DeflateDecompressingEntity(response.getEntity())); + return; + } + } + } + } + } + }); + client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler() ); - // The first header is always null here to provide the response body. - headers.remove(null); + // Use Java's built-in proxy logic + ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner( + client.getConnectionManager().getSchemeRegistry(), + ProxySelector.getDefault()); + client.setRoutePlanner(routePlanner); - // Find the response stream - the error stream may be valid in cases - // where the input stream is not. - InputStream responseBodyStream = null; - try { - responseBodyStream = httpMethod.getResponseBodyAsStream(); - } catch (IOException e) { - // normal for 401, 403 and 404 responses, for example... - } + FETCHER = client; + } - if (responseBodyStream == null) { - // Fall back to zero length response. - responseBodyStream = new ByteArrayInputStream(ArrayUtils.EMPTY_BYTE_ARRAY); + static class GzipDecompressingEntity extends HttpEntityWrapper { + public GzipDecompressingEntity(final HttpEntity entity) { + super(entity); } - String encoding = headers.get("Content-Encoding"); + public InputStream getContent() throws IOException, IllegalStateException { + // the wrapped entity's getContent() decides about repeatability + InputStream wrappedin = wrappedEntity.getContent(); - // Create the appropriate stream wrapper based on the encoding type. - InputStream is = responseBodyStream; - if (encoding == null) { - is = responseBodyStream; - } else if (encoding.equalsIgnoreCase("gzip")) { - is = new GZIPInputStream(responseBodyStream); - } else if (encoding.equalsIgnoreCase("deflate")) { - Inflater inflater = new Inflater(true); - is = new InflaterInputStream(responseBodyStream, inflater); + return new GZIPInputStream(wrappedin); } - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - int totalBytesRead = 0; - int currentBytesRead; - - while ((currentBytesRead = is.read(buffer)) != -1) { - output.write(buffer, 0, currentBytesRead); - totalBytesRead += currentBytesRead; - - if(maxObjSize > 0 && totalBytesRead > maxObjSize) { - IOUtils.closeQuietly(is); - IOUtils.closeQuietly(output); - // Exceeded max # of bytes - return HttpResponse.badrequest("Exceeded maximum number of bytes - " + this.maxObjSize); - } + public long getContentLength() { + // length of ungzipped content is not known + return -1; } - - return new HttpResponseBuilder() - .setHttpStatusCode(responseCode) - .setResponse(output.toByteArray()) - .addHeaders(headers) - .create(); } - /** {...@inheritdoc} */ - public HttpResponse fetch(HttpRequest request) { - HttpClient httpClient = new HttpClient(); - HttpMethod httpMethod; - String methodType = request.getMethod(); - String requestUri = request.getUri().toString(); - - // Select a proxy based on the URI. May be Proxy.NO_PROXY - Proxy proxy = ProxySelector.getDefault().select(request.getUri().toJavaUri()).get(0); - - if (proxy != Proxy.NO_PROXY) { - InetSocketAddress address = (InetSocketAddress) proxy.address(); - httpClient.getHostConfiguration().setProxy(address.getHostName(), address.getPort()); + static class DeflateDecompressingEntity extends HttpEntityWrapper { + public DeflateDecompressingEntity(final HttpEntity entity) { + super(entity); } + public InputStream getContent() + throws IOException, IllegalStateException { - // true for non-HEAD requests - boolean requestCompressedContent = true; + // the wrapped entity's getContent() decides about repeatability + InputStream wrappedin = wrappedEntity.getContent(); - if ("POST".equals(methodType) || "PUT".equals(methodType)) { - EntityEnclosingMethod enclosingMethod = ("POST".equals(methodType)) - ? new PostMethod(requestUri) - : new PutMethod(requestUri); - - if (request.getPostBodyLength() > 0) { - enclosingMethod.setRequestEntity(new InputStreamRequestEntity(request.getPostBody())); - enclosingMethod.setRequestHeader("Content-Length", - String.valueOf(request.getPostBodyLength())); - } - httpMethod = enclosingMethod; - } else if ("DELETE".equals(methodType)) { - httpMethod = new DeleteMethod(requestUri); - } else if ("HEAD".equals(methodType)) { - httpMethod = new HeadMethod(requestUri); - } else { - httpMethod = new GetMethod(requestUri); + return new InflaterInputStream(wrappedin, new Inflater(true)); } - httpMethod.setFollowRedirects(false); - httpMethod.getParams().setSoTimeout(connectionTimeoutMs); + public long getContentLength() { + // length of ungzipped content is not known + return -1; + } + } - if (requestCompressedContent) - httpMethod.setRequestHeader("Accept-Encoding", "gzip, deflate"); + public HttpResponse fetch(org.apache.shindig.gadgets.http.HttpRequest request) { + HttpUriRequest httpMethod = null; + Preconditions.checkNotNull(request); + final String methodType = request.getMethod(); + final String requestUri = request.getUri().toString(); - for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) { - httpMethod.setRequestHeader(entry.getKey(), StringUtils.join(entry.getValue(), ',')); - } + final org.apache.http.HttpResponse response; + final long started = System.currentTimeMillis(); try { + if ("POST".equals(methodType) || "PUT".equals(methodType)) { + HttpEntityEnclosingRequestBase enclosingMethod = ("POST".equals(methodType)) + ? new HttpPost(requestUri) + : new HttpPut(requestUri); + + if (request.getPostBodyLength() > 0) { + enclosingMethod.setEntity(new InputStreamEntity(request.getPostBody(), request.getPostBodyLength())); + } + httpMethod = enclosingMethod; + } else if ("GET".equals(methodType)) { + httpMethod = new HttpGet(requestUri); + } else if ("HEAD".equals(methodType)) { + httpMethod = new HttpHead(requestUri); + } else if ("DELETE".equals(methodType)) { + httpMethod = new HttpDelete(requestUri); + } + for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) { + httpMethod.addHeader(entry.getKey(), StringUtils.join(entry.getValue(), ',')); + } - int statusCode = httpClient.executeMethod(httpMethod); + if (!request.getFollowRedirects()) + httpMethod.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); + + response = FETCHER.execute(httpMethod); - // Handle redirects manually - if (request.getFollowRedirects() && - ((statusCode == HttpStatus.SC_MOVED_TEMPORARILY) || - (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || - (statusCode == HttpStatus.SC_SEE_OTHER) || - (statusCode == HttpStatus.SC_TEMPORARY_REDIRECT))) { - - Header header = httpMethod.getResponseHeader("location"); - if (header != null) { - String redirectUri = header.getValue(); + if (response == null) + throw new IOException("Unknown problem with request"); - if ((redirectUri == null) || (redirectUri.equals(""))) { - redirectUri = "/"; - } - // Url can be relative to original: - redirectUri = request.getUri().resolve(Uri.parse(redirectUri)).toString(); - - httpMethod.releaseConnection(); - httpMethod = new GetMethod(redirectUri); + if (response.getEntity() == null) { + throw new IOException("Cannot retrieve " + request.getUri() + " reason " + response.getStatusLine().getReasonPhrase()); + } - statusCode = httpClient.executeMethod(httpMethod); - } + long now = System.currentTimeMillis(); + if (now - started > slowResponseWarning) { + slowResponseWarning(request, started, now); } - return makeResponse(httpMethod, statusCode); + return makeResponse(response); - } catch (IOException e) { - if (e instanceof java.net.SocketTimeoutException || - e instanceof java.net.SocketException) { + } catch (Exception e) { + long now = System.currentTimeMillis(); + + // Find timeout exceptions, respond accordingly + if (TIMEOUT_EXCEPTIONS.contains(e.getClass())) { + LOG.warning("Timeout for " + request.getUri() + " Exception: " + e.getClass().getName() + " - " + e.getMessage() + " - " + (now - started) + "ms"); return HttpResponse.timeout(); } - return HttpResponse.error(); + LOG.log(Level.WARNING, "Got Exception fetching " + request.getUri() + " - " + (now - started) + "ms", e); + return HttpResponse.error(); } finally { - httpMethod.releaseConnection(); + // cleanup any outstanding resources.. + if (httpMethod != null) try { + httpMethod.abort(); + } catch (Exception e) { + // ignore + } + } + } + + /** + * Called when a request takes too long. Consider subclassing this if you want to do something other than logging + * a warning . + * + * @param request the request that generated the slowrequest + * @param started the time the request started, in milliseconds. + * @param finished the time the request finished, in milliseconds. + */ + protected void slowResponseWarning(HttpRequest request, long started, long finished) { + LOG.warning("Slow response from " + request.getUri() + ' ' + (finished - started) + "ms"); + } + + /** + * Change the global maximum fetch size (in bytes) for all fetches. + * + * @param maxObjectSizeBytes value for maximum number of bytes, or 0 for no limit + */ + @Inject(optional = true) + public void setMaxObjectSizeBytes(@Named("shindig.http.client.max-object-size-bytes") int maxObjectSizeBytes) { + this.maxObjSize = maxObjectSizeBytes; + } + + /** + * Change the global threshold for warning about slow responses + * + * @param slowResponseWarning time in milliseconds after we issue a warning + */ + + @Inject(optional = true) + public void setSlowResponseWarning(@Named("shindig.http.client.slow-response-warning") long slowResponseWarning) { + this.slowResponseWarning = slowResponseWarning; + } + + /** + * Change the global connection timeout for all new fetchs. + * + * @param connectionTimeoutMs new connection timeout in milliseconds + */ + @Inject(optional = true) + public void setConnectionTimeoutMs(@Named("shindig.http.client.connection-timeout-ms") int connectionTimeoutMs) { + Preconditions.checkArgument(connectionTimeoutMs > 0, "connection-timeout-ms must be greater than 0"); + FETCHER.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, connectionTimeoutMs); + } + + /** + * Change the global read timeout for all new fetchs. + * + * @param connectionTimeoutMs new connection timeout in milliseconds + */ + @Inject(optional = true) + public void setReadTimeoutMs(@Named("shindig.http.client.read-timeout-ms") int connectionTimeoutMs) { + Preconditions.checkArgument(connectionTimeoutMs > 0, "connection-timeout-ms must be greater than 0"); + FETCHER.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT, connectionTimeoutMs); + } + + + /** + * @param response The response to parse + * @return A HttpResponse object made by consuming the response of the + * given HttpMethod. + * @throws IOException when problems occur processing the body content + */ + private HttpResponse makeResponse(org.apache.http.HttpResponse response) throws IOException { + HttpResponseBuilder builder = new HttpResponseBuilder(); + + if (response.getAllHeaders() != null) { + for (Header h : response.getAllHeaders()) { + if (h.getName() != null) + builder.addHeader(h.getName(), h.getValue()); + } } + + HttpEntity entity = Preconditions.checkNotNull(response.getEntity()); + + if (maxObjSize > 0 && entity.getContentLength() > maxObjSize) { + return HttpResponse.badrequest("Exceeded maximum number of bytes - " + maxObjSize); + } + + return builder + .setHttpStatusCode(response.getStatusLine().getStatusCode()) + .setResponse(EntityUtils.toByteArray(entity)) + .create(); } } Modified: incubator/shindig/trunk/java/samples/pom.xml URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/samples/pom.xml?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/samples/pom.xml (original) +++ incubator/shindig/trunk/java/samples/pom.xml Mon Feb 1 23:05:43 2010 @@ -142,7 +142,7 @@ </dependency> <dependency> <groupId>net.oauth.core</groupId> - <artifactId>oauth-httpclient3</artifactId> + <artifactId>oauth-httpclient4</artifactId> </dependency> <!-- Hibernate --> Modified: incubator/shindig/trunk/java/social-api/pom.xml URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/pom.xml?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/social-api/pom.xml (original) +++ incubator/shindig/trunk/java/social-api/pom.xml Mon Feb 1 23:05:43 2010 @@ -59,6 +59,12 @@ <groupId>org.apache.shindig</groupId> <artifactId>shindig-common</artifactId> </dependency> + + <dependency> + <groupId>org.apache.shindig</groupId> + <artifactId>shindig-gadgets</artifactId> + </dependency> + <dependency> <groupId>org.apache.shindig</groupId> <artifactId>shindig-common</artifactId> @@ -99,7 +105,7 @@ </dependency> <dependency> <groupId>net.oauth.core</groupId> - <artifactId>oauth-httpclient3</artifactId> + <artifactId>oauth-httpclient4</artifactId> </dependency> <!-- may only be needed for JDK < 1.6 --> @@ -124,8 +130,8 @@ <artifactId>commons-io</artifactId> </dependency> <dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>xml-apis</groupId> Modified: incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/sample/service/SampleContainerHandler.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/sample/service/SampleContainerHandler.java?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/sample/service/SampleContainerHandler.java (original) +++ incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/sample/service/SampleContainerHandler.java Mon Feb 1 23:05:43 2010 @@ -18,10 +18,8 @@ package org.apache.shindig.social.sample.service; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; import org.apache.shindig.common.util.ImmediateFuture; +import org.apache.shindig.common.uri.Uri; import org.apache.shindig.protocol.Operation; import org.apache.shindig.protocol.ProtocolException; import org.apache.shindig.protocol.RequestItem; @@ -29,6 +27,11 @@ import org.apache.shindig.social.sample.spi.JsonDbOpensocialService; import org.json.JSONException; import org.json.JSONObject; +import org.apache.shindig.gadgets.GadgetException; +import org.apache.shindig.gadgets.http.HttpFetcher; +import org.apache.shindig.gadgets.http.HttpRequest; +import org.apache.shindig.gadgets.http.HttpResponse; + import java.io.IOException; import java.util.concurrent.Future; @@ -42,10 +45,11 @@ public class SampleContainerHandler { private final JsonDbOpensocialService service; - + private final HttpFetcher fetcher; @Inject - public SampleContainerHandler(JsonDbOpensocialService dbService) { + public SampleContainerHandler(JsonDbOpensocialService dbService, HttpFetcher fetcher) { this.service = dbService; + this.fetcher = fetcher; } /** @@ -93,19 +97,14 @@ String errorMessage = "The json state file " + stateFileLocation + " could not be fetched and parsed."; - HttpMethod jsonState = new GetMethod(stateFileLocation); - HttpClient client = new HttpClient(); try { - client.executeMethod(jsonState); - - if (jsonState.getStatusCode() != 200) { + HttpResponse response = fetcher.fetch(new HttpRequest(Uri.parse(stateFileLocation))); + if (response.getHttpStatusCode() != 200) { throw new RuntimeException(errorMessage); } - return jsonState.getResponseBodyAsString(); - } catch (IOException e) { + return response.getResponseAsString(); + } catch (GadgetException e) { throw new RuntimeException(errorMessage, e); - } finally { - jsonState.releaseConnection(); } } } Modified: incubator/shindig/trunk/pom.xml URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml?rev=905439&r1=905438&r2=905439&view=diff ============================================================================== --- incubator/shindig/trunk/pom.xml (original) +++ incubator/shindig/trunk/pom.xml Mon Feb 1 23:05:43 2010 @@ -1385,7 +1385,7 @@ </dependency> <dependency> <groupId>net.oauth.core</groupId> - <artifactId>oauth-httpclient3</artifactId> + <artifactId>oauth-httpclient4</artifactId> <version>20090531</version> <scope>compile</scope> </dependency> @@ -1524,9 +1524,9 @@ <version>1.3.04</version> </dependency> <dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> - <version>3.1</version> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.0.1</version> </dependency> <dependency> <groupId>org.jsecurity</groupId>