/* * org.openmicroscopy.shoola.svc.transport.BasicChannel * *------------------------------------------------------------------------------ * Copyright (C) 2006-2015 University of Dundee. All rights reserved. * * * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.svc.transport; import java.security.cert.X509Certificate; import java.util.Arrays; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.apache.http.HttpHost; import org.apache.http.client.config.AuthSchemes; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; /** * Creates a basic <code>HttpChannel</code>. * In order to enforce a connection per request model, the same channel * may not be shared by concurrent invocations of the exchange method. For * this reason we create a new HttpClient every time -- using a synch object * would imply serializing all requests, thus defeating any potential * benefit of concurrency. Note that HttpClient can be configured with a * thread-safe connection pool (see documents), but in this case connections are * recycled and possibly waited on, so we wouldn't have a connection per * request if we were to use the HttpClient built-in capabilities. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ class BasicChannel extends HttpChannel { /** The default value for the time out. */ static final int DEF_CONN_TIMEOUT = 10000; /** The requested path. */ private final String requestPath; /** The time before being disconnected. */ private final int connTimeout; /** * Creates a connection. * * @return See above * @throws TransportException Thrown if an error occurred while creating the * SSL context. */ private SSLConnectionSocketFactory createSSLConnection() throws TransportException { SSLContext sslcontext = SSLContexts.createSystemDefault(); final TrustManager trustEverything = new X509TrustManager() { private final X509Certificate[] acceptedIssuers = new X509Certificate[0]; @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return this.acceptedIssuers; } }; TrustManager[] managers = {trustEverything}; try { sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, managers, null); } catch (Exception e) { new TransportException("Cannot create security context", e); } return new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } /** * Creates a new instance. * * @param url The server's URL. * @param connTimeout The time before being disconnected. * @throws IllegalArgumentException If the specified URL is not valid. */ BasicChannel(String url, int connTimeout) throws IllegalArgumentException { requestPath = url; this.connTimeout = (connTimeout < 0 ? DEF_CONN_TIMEOUT : connTimeout); } /** * Creates a <code>HttpClient</code> to communicate. * @see HttpChannel#getCommunicationLink() */ protected CloseableHttpClient getCommunicationLink() throws TransportException { //Default connection configuration RequestConfig.Builder builder = RequestConfig.custom(); builder.setCookieSpec(CookieSpecs.BEST_MATCH) .setExpectContinueEnabled(true) .setStaleConnectionCheckEnabled(true) .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)) .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)); builder.setConnectTimeout(connTimeout); String proxyHost = System.getProperty(HttpChannel.PROXY_HOST); String proxyPort = System.getProperty(HttpChannel.PROXY_PORT); if (CommonsLangUtils.isNotBlank(proxyHost) && CommonsLangUtils.isNotBlank(proxyPort)) { builder.setProxy(new HttpHost(proxyHost, Integer.parseInt(proxyPort))); } HttpClientBuilder httpBuilder = HttpClients.custom(); httpBuilder.setDefaultRequestConfig(builder.build()); String value = requestPath; if (value.toLowerCase().startsWith("https")) httpBuilder.setSSLSocketFactory(createSSLConnection()); return httpBuilder.build(); } /** * Returns the requested path. * @see HttpChannel#getRequestPath() */ protected String getRequestPath() { return requestPath; } }