Java tutorial
/* * Copyright (C) 2001-2016 Food and Agriculture Organization of the * United Nations (FAO-UN), United Nations World Food Programme (WFP) * and United Nations Environment Programme (UNEP) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, * Rome - Italy. email: geonetwork@osgeo.org */ package org.fao.geonet.utils; import com.google.common.base.Function; import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpClientConnection; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.config.SocketConfig; import org.apache.http.conn.ConnectionRequest; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.LaxRedirectStrategy; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.springframework.http.HttpHeaders; import org.springframework.http.client.AbstractClientHttpResponse; import org.springframework.http.client.ClientHttpResponse; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.PreDestroy; /** * Factory interface for making different kinds of requests. This is an interface so that tests can * mock their own implementations. * * User: Jesse Date: 10/18/13 Time: 4:16 PM */ public class GeonetHttpRequestFactory { private int numberOfConcurrentRequests = 20; private PoolingHttpClientConnectionManager connectionManager; private volatile HttpClientConnectionManager nonShutdownableConnectionManager; @PreDestroy public synchronized void shutdown() { if (connectionManager != null) { connectionManager.shutdown(); } connectionManager = null; } public synchronized void setNumberOfConcurrentRequests(int numberOfConcurrentRequests) { shutdown(); this.numberOfConcurrentRequests = numberOfConcurrentRequests; } /** * Create a default XmlRequest. */ public final XmlRequest createXmlRequest() { return createXmlRequest(null, 80, "http"); } /** * Create a default XmlRequest. */ public XmlRequest createXmlRequest(String host, int port, String protocol) { return new XmlRequest(host, port, protocol, this); } /** * Create a default XmlRequest. */ public final XmlRequest createXmlRequest(String host) { return createXmlRequest(host, 80, "http"); } /** * Create a default XmlRequest. */ public final XmlRequest createXmlRequest(String host, int port) { String protocol = "http"; if (port == 443) { protocol = "https"; } return createXmlRequest(host, port, protocol); } /** * Ceate an XmlRequest from a url. * * @param url the url of the request. * @return the XmlRequest. */ public final XmlRequest createXmlRequest(URL url) { final int port = url.getPort(); final XmlRequest request = createXmlRequest(url.getHost(), port, url.getProtocol()); request.setAddress(url.getPath()); request.setQuery(url.getQuery()); request.setFragment(url.getRef()); request.setUserInfo(url.getUserInfo()); request.setCookieStore(new BasicCookieStore()); return request; } public ClientHttpResponse execute(HttpUriRequest request) throws IOException { final Function<HttpClientBuilder, Void> noop = new Function<HttpClientBuilder, Void>() { @Nullable @Override public Void apply(@Nullable HttpClientBuilder input) { return null; } }; return execute(request, noop); } public ClientHttpResponse execute(HttpUriRequest request, final Credentials credentials, final AuthScope authScope) throws IOException { final Function<HttpClientBuilder, Void> setCredentials = new Function<HttpClientBuilder, Void>() { @Nullable @Override public Void apply(@Nonnull HttpClientBuilder input) { final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(authScope, credentials); input.setDefaultCredentialsProvider(credentialsProvider); return null; } }; return execute(request, setCredentials); } public ClientHttpResponse execute(HttpUriRequest request, Function<HttpClientBuilder, Void> configurator) throws IOException { final HttpClientBuilder clientBuilder = getDefaultHttpClientBuilder(); configurator.apply(clientBuilder); CloseableHttpClient httpClient = clientBuilder.build(); return new AdaptingResponse(httpClient, httpClient.execute(request)); } public ClientHttpResponse execute(HttpUriRequest request, Function<HttpClientBuilder, Void> configurator, AbstractHttpRequest r) throws IOException { final HttpClientBuilder clientBuilder = getDefaultHttpClientBuilder(); configurator.apply(clientBuilder); CloseableHttpClient httpClient = clientBuilder.build(); if (r.isPreemptiveBasicAuth() || r.getHttpClientContext() != null) { return new AdaptingResponse(httpClient, httpClient.execute(request, r.getHttpClientContext())); } else { return new AdaptingResponse(httpClient, httpClient.execute(request)); } } public HttpClientBuilder getDefaultHttpClientBuilder() { final HttpClientBuilder builder = HttpClientBuilder.create(); builder.setRedirectStrategy(new LaxRedirectStrategy()); builder.disableContentCompression(); synchronized (this) { if (connectionManager == null) { connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(this.numberOfConcurrentRequests); nonShutdownableConnectionManager = new HttpClientConnectionManager() { public void closeExpiredConnections() { connectionManager.closeExpiredConnections(); } public ConnectionRequest requestConnection(HttpRoute route, Object state) { return connectionManager.requestConnection(route, state); } public void releaseConnection(HttpClientConnection managedConn, Object state, long keepalive, TimeUnit tunit) { connectionManager.releaseConnection(managedConn, state, keepalive, tunit); } public void connect(HttpClientConnection managedConn, HttpRoute route, int connectTimeout, HttpContext context) throws IOException { connectionManager.connect(managedConn, route, connectTimeout, context); } public void upgrade(HttpClientConnection managedConn, HttpRoute route, HttpContext context) throws IOException { connectionManager.upgrade(managedConn, route, context); } public void routeComplete(HttpClientConnection managedConn, HttpRoute route, HttpContext context) throws IOException { connectionManager.routeComplete(managedConn, route, context); } public void shutdown() { // don't shutdown pool } public void closeIdleConnections(long idleTimeout, TimeUnit tunit) { connectionManager.closeIdleConnections(idleTimeout, tunit); } }; } connectionManager.setDefaultSocketConfig( SocketConfig.custom().setSoTimeout((int) TimeUnit.MINUTES.toMillis(3)).build()); builder.setConnectionManager(nonShutdownableConnectionManager); } return builder; } private static class AdaptingResponse extends AbstractClientHttpResponse { private final CloseableHttpResponse _response; private final CloseableHttpClient _client; public AdaptingResponse(CloseableHttpClient client, CloseableHttpResponse response) { this._response = response; this._client = client; } @Override public int getRawStatusCode() throws IOException { return _response.getStatusLine().getStatusCode(); } @Override public String getStatusText() throws IOException { return _response.getStatusLine().getReasonPhrase(); } @Override public void close() { IOUtils.closeQuietly(_response); IOUtils.closeQuietly(_client); } @Override public InputStream getBody() throws IOException { return _response.getEntity().getContent(); } @Override public HttpHeaders getHeaders() { final HttpHeaders httpHeaders = new HttpHeaders(); final Header[] headers = _response.getAllHeaders(); for (Header header : headers) { final HeaderElement[] elements = header.getElements(); for (HeaderElement element : elements) { httpHeaders.add(header.getName(), element.getValue()); } } return httpHeaders; } } }