View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions Copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2009 Sun Microsystems Inc.
15   * Portions Copyright 2010–2011 ApexIdentity Inc.
16   * Portions Copyright 2011-2015 ForgeRock AS.
17   */
18  
19  package org.forgerock.http.apache.sync;
20  
21  import static java.util.concurrent.TimeUnit.MILLISECONDS;
22  import static org.forgerock.http.handler.HttpClientHandler.OPTION_CONNECT_TIMEOUT;
23  import static org.forgerock.http.handler.HttpClientHandler.OPTION_HOSTNAME_VERIFIER;
24  import static org.forgerock.http.handler.HttpClientHandler.OPTION_KEY_MANAGERS;
25  import static org.forgerock.http.handler.HttpClientHandler.OPTION_MAX_CONNECTIONS;
26  import static org.forgerock.http.handler.HttpClientHandler.OPTION_RETRY_REQUESTS;
27  import static org.forgerock.http.handler.HttpClientHandler.OPTION_REUSE_CONNECTIONS;
28  import static org.forgerock.http.handler.HttpClientHandler.OPTION_SO_TIMEOUT;
29  import static org.forgerock.http.handler.HttpClientHandler.OPTION_SSLCONTEXT_ALGORITHM;
30  import static org.forgerock.http.handler.HttpClientHandler.OPTION_SSL_CIPHER_SUITES;
31  import static org.forgerock.http.handler.HttpClientHandler.OPTION_SSL_ENABLED_PROTOCOLS;
32  import static org.forgerock.http.handler.HttpClientHandler.OPTION_TEMPORARY_STORAGE;
33  import static org.forgerock.http.handler.HttpClientHandler.OPTION_TRUST_MANAGERS;
34  import static org.forgerock.http.util.Lists.asArrayOrNull;
35  
36  import java.security.GeneralSecurityException;
37  import java.util.List;
38  
39  import javax.net.ssl.HostnameVerifier;
40  import javax.net.ssl.SSLContext;
41  
42  import org.apache.http.client.config.RequestConfig;
43  import org.apache.http.conn.ssl.DefaultHostnameVerifier;
44  import org.apache.http.conn.ssl.NoopHostnameVerifier;
45  import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
46  import org.apache.http.impl.NoConnectionReuseStrategy;
47  import org.apache.http.impl.client.HttpClientBuilder;
48  import org.forgerock.http.HttpApplicationException;
49  import org.forgerock.http.apache.NoAuthenticationStrategy;
50  import org.forgerock.http.io.Buffer;
51  import org.forgerock.http.spi.HttpClient;
52  import org.forgerock.http.spi.HttpClientProvider;
53  import org.forgerock.util.Factory;
54  import org.forgerock.util.Options;
55  import org.forgerock.util.time.Duration;
56  
57  /**
58   * An HTTP client implementation provider for Apache HttpClient.
59   */
60  public final class SyncHttpClientProvider implements HttpClientProvider {
61  
62      @Override
63      public HttpClient newHttpClient(final Options options) throws HttpApplicationException {
64          final Factory<Buffer> storage = options.get(OPTION_TEMPORARY_STORAGE);
65  
66          final HttpClientBuilder builder = HttpClientBuilder.create();
67  
68          // Connection pooling.
69          final int maxConnections = options.get(OPTION_MAX_CONNECTIONS);
70          builder.setMaxConnTotal(maxConnections);
71          builder.setMaxConnPerRoute(maxConnections);
72          if (!options.get(OPTION_REUSE_CONNECTIONS)) {
73              builder.setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE);
74          }
75          if (!options.get(OPTION_RETRY_REQUESTS)) {
76              builder.disableAutomaticRetries();
77          }
78  
79          // Timeouts.
80          final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
81          final Duration soTimeout = options.get(OPTION_SO_TIMEOUT);
82          requestConfigBuilder.setSocketTimeout(soTimeout.isUnlimited() ? 0 : (int) soTimeout
83                  .to(MILLISECONDS));
84          final Duration connectTimeout = options.get(OPTION_CONNECT_TIMEOUT);
85          requestConfigBuilder.setConnectTimeout(connectTimeout.isUnlimited() ? 0
86                  : (int) connectTimeout.to(MILLISECONDS));
87          builder.setDefaultRequestConfig(requestConfigBuilder.build());
88  
89          // FIXME: where is this setting in HttpClient 4.x?
90          // HttpProtocolParams.setVersion(parameters, HttpVersion.HTTP_1_1);
91  
92          builder.disableRedirectHandling();
93  
94          // SSL
95          final SSLContext context;
96          try {
97              context = SSLContext.getInstance(options.get(OPTION_SSLCONTEXT_ALGORITHM));
98              context.init(options.get(OPTION_KEY_MANAGERS), options.get(OPTION_TRUST_MANAGERS), null);
99          } catch (final GeneralSecurityException e) {
100             throw new HttpApplicationException(e);
101         }
102 
103         final HostnameVerifier hostnameVerifier;
104         switch (options.get(OPTION_HOSTNAME_VERIFIER)) {
105         case ALLOW_ALL:
106             hostnameVerifier = NoopHostnameVerifier.INSTANCE;
107             break;
108         default:
109             hostnameVerifier = new DefaultHostnameVerifier();
110             break;
111         }
112 
113         List<String> protocols = options.get(OPTION_SSL_ENABLED_PROTOCOLS);
114         List<String> ciphers = options.get(OPTION_SSL_CIPHER_SUITES);
115 
116         builder.setSSLSocketFactory(new SSLConnectionSocketFactory(context, asArrayOrNull(protocols),
117                 asArrayOrNull(ciphers), hostnameVerifier));
118 
119         // FIXME: is this equivalent to original OpenIG config?
120         builder.disableCookieManagement();
121         builder.setProxyAuthenticationStrategy(NoAuthenticationStrategy.INSTANCE);
122         builder.setTargetAuthenticationStrategy(NoAuthenticationStrategy.INSTANCE);
123 
124         return new SyncHttpClient(builder.build(), storage);
125     }
126 }