HTTPCLIENT-1778: [OSGi] simplify handling of ManagedService based configurations

- simplify TrustedHostsConfiguration handling

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1763263 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Julian Sedding 2016-10-04 11:29:36 +00:00
parent e9f8c5b315
commit 71d0567376
4 changed files with 53 additions and 89 deletions

View File

@ -31,13 +31,11 @@ import java.util.List;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
import org.apache.hc.client5.http.osgi.services.TrustedHostsConfiguration;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedService;
import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
@ -50,12 +48,11 @@ final class HttpClientBuilderConfigurator {
private final Registry<ConnectionSocketFactory> socketFactoryRegistry;
HttpClientBuilderConfigurator(
final BundleContext bundleContext,
final List<ProxyConfiguration> proxyConfigurations,
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
final TrustedHostsConfiguration trustedHostsConfiguration) {
credentialsProvider = new OSGiCredentialsProvider(proxyConfigurations);
routePlanner = new OSGiHttpRoutePlanner(proxyConfigurations);
socketFactoryRegistry = createSocketFactoryRegistry(bundleContext, trustedHostsConfiguration);
socketFactoryRegistry = createSocketFactoryRegistry(trustedHostsConfiguration);
}
<T extends HttpClientBuilder> T configure(final T clientBuilder) {
@ -67,17 +64,15 @@ final class HttpClientBuilderConfigurator {
}
private Registry<ConnectionSocketFactory> createSocketFactoryRegistry(
final BundleContext bundleContext,
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
final TrustedHostsConfiguration trustedHostsConfiguration) {
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", createSocketFactory(bundleContext, trustedHostsConfiguration))
.register("https", createSocketFactory(trustedHostsConfiguration))
.build();
}
private ConnectionSocketFactory createSocketFactory(
final BundleContext bundleContext,
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
return new RelaxedLayeredConnectionSocketFactory(bundleContext, trustedHostsConfiguration, getSocketFactory());
final TrustedHostsConfiguration trustedHostsConfiguration) {
return new RelaxedLayeredConnectionSocketFactory(trustedHostsConfiguration, getSocketFactory());
}
}

View File

@ -108,12 +108,11 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
props.put(Constants.SERVICE_PID, TRUSTED_HOSTS_PID);
props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR));
props.put(Constants.SERVICE_DESCRIPTION, TRUSTED_HOSTS_SERVICE_NAME);
trustedHostConfiguration = context.registerService(ManagedService.class,
new OSGiTrustedHostsConfiguration(),
props);
final OSGiTrustedHostsConfiguration trustedHosts = new OSGiTrustedHostsConfiguration();
trustedHostConfiguration = context.registerService(ManagedService.class, trustedHosts, props);
final HttpClientBuilderConfigurator configurator =
new HttpClientBuilderConfigurator(context, proxyConfigurations, trustedHostConfiguration);
new HttpClientBuilderConfigurator(proxyConfigurations, trustedHosts);
props.clear();
props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID);

View File

@ -36,23 +36,16 @@ import org.apache.hc.client5.http.osgi.services.TrustedHostsConfiguration;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedService;
final class RelaxedLayeredConnectionSocketFactory implements LayeredConnectionSocketFactory {
private TrustedHostsConfiguration trustedHostsConfiguration;
private final LayeredConnectionSocketFactory defaultSocketFactory;
private final BundleContext bundleContext;
private final ServiceRegistration<ManagedService> trustedHostConfiguration;
public RelaxedLayeredConnectionSocketFactory(final BundleContext bundleContext,
final ServiceRegistration<ManagedService> trustedHostConfiguration,
public RelaxedLayeredConnectionSocketFactory(final TrustedHostsConfiguration trustedHostsConfiguration,
final LayeredConnectionSocketFactory defaultSocketFactory) {
this.bundleContext = bundleContext;
this.trustedHostConfiguration = trustedHostConfiguration;
this.trustedHostsConfiguration = trustedHostsConfiguration;
this.defaultSocketFactory = defaultSocketFactory;
}
@ -61,26 +54,21 @@ final class RelaxedLayeredConnectionSocketFactory implements LayeredConnectionSo
final String target,
final int port,
final HttpContext context) throws IOException {
final ManagedService trustedHostsConfigurationObject = bundleContext.getService(trustedHostConfiguration.getReference());
if (trustedHostsConfigurationObject != null) {
final TrustedHostsConfiguration configuration = (TrustedHostsConfiguration) trustedHostsConfigurationObject;
if (configuration.isEnabled()) {
if (trustedHostsConfiguration.isEnabled()) {
// if trust all there is no check to perform
if (configuration.trustAll()) {
if (trustedHostsConfiguration.trustAll()) {
return socket;
}
// blindly verify the host if in the trust list
for (String trustedHost : configuration.getTrustedHosts()) {
for (String trustedHost : trustedHostsConfiguration.getTrustedHosts()) {
if (createMatcher(trustedHost).matches(target)) {
return socket;
}
}
}
}
// follow back to the default behavior
// fall back to the default behavior
return defaultSocketFactory.createLayeredSocket(socket, target, port, context);
}

View File

@ -26,10 +26,7 @@
*/
package org.apache.hc.client5.http.osgi.impl;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.net.InetSocketAddress;
@ -42,79 +39,56 @@ import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.mockito.Mock;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
public class TestRelaxedLayeredConnectionSocketFactory {
@Mock
Socket insecureSocket;
@Mock
Socket secureSocket;
private final HttpContext context = new BasicHttpContext();
@Test
public void testTrustedAllConnections() throws Exception {
final HttpContext context = new BasicHttpContext();
final Dictionary<String, Object> config = new Hashtable<>();
config.put("trustedhosts.enabled", Boolean.TRUE);
config.put("trustedhosts.trustAll", Boolean.TRUE);
config.put("trustedhosts.hosts", new String[]{});
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(true, true);
final Socket socket = socketFactory.createSocket(context);
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
assertSame(socket, secureSocket);
assertSame(this.secureSocket, secureSocket);
}
@Test
public void testTrustedConnections() throws Exception {
final HttpContext context = new BasicHttpContext();
final Dictionary<String, Object> config = new Hashtable<>();
config.put("trustedhosts.enabled", Boolean.TRUE);
config.put("trustedhosts.trustAll", Boolean.FALSE);
config.put("trustedhosts.hosts", new String[]{ "localhost" });
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(true, false, "localhost");
final Socket socket = socketFactory.createSocket(context);
final Socket localSecureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
assertSame(socket, localSecureSocket);
assertSame(this.insecureSocket, localSecureSocket);
final Socket apacheSecureSocket = socketFactory.createLayeredSocket(socket, "www.apache.org", 9999, context);
assertNotSame(socket, apacheSecureSocket);
assertSame(this.secureSocket, apacheSecureSocket);
}
@Test
public void testNotEabledConfiguration() throws Exception {
final HttpContext context = new BasicHttpContext();
final Dictionary<String, Object> config = new Hashtable<>();
config.put("trustedhosts.enabled", Boolean.TRUE);
config.put("trustedhosts.trustAll", Boolean.FALSE);
config.put("trustedhosts.hosts", new String[]{});
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(false, true);
final Socket socket = socketFactory.createSocket(context);
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
assertNotSame(socket, secureSocket);
assertSame(this.secureSocket, secureSocket);
}
private LayeredConnectionSocketFactory getLayeredConnectionSocketFactory(final Dictionary<String, ?> config) {
final ServiceReference<ManagedService> reference = mock(ServiceReference.class);
final ServiceRegistration<ManagedService> registration = mock(ServiceRegistration.class);
when(registration.getReference()).thenReturn(reference);
final BundleContext bundleContext = mock(BundleContext.class);
private LayeredConnectionSocketFactory getLayeredConnectionSocketFactory(
final boolean enabled, final boolean trustAll, final String... trustedHosts) throws ConfigurationException {
final OSGiTrustedHostsConfiguration configuration = new OSGiTrustedHostsConfiguration();
try {
configuration.updated(config);
} catch (ConfigurationException e) {
// it doesn't happen in tests
}
when(bundleContext.getService(reference)).thenReturn(configuration);
configuration.updated(createConfig(enabled, trustAll, trustedHosts));
final Socket socket = mock(Socket.class);
final Socket secureSocket = mock(Socket.class);
final LayeredConnectionSocketFactory defaultSocketFactory = new LayeredConnectionSocketFactory() {
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return socket;
return insecureSocket;
}
@Override
@ -125,7 +99,7 @@ public class TestRelaxedLayeredConnectionSocketFactory {
final InetSocketAddress localAddress,
final HttpContext context ) throws IOException {
// not needed in this version
return socket;
return insecureSocket;
}
@Override
@ -138,7 +112,15 @@ public class TestRelaxedLayeredConnectionSocketFactory {
};
return new RelaxedLayeredConnectionSocketFactory(bundleContext, registration, defaultSocketFactory);
return new RelaxedLayeredConnectionSocketFactory(configuration, defaultSocketFactory);
}
private Dictionary<String, Object> createConfig(final boolean enabled, final boolean trustAll, final String... trustedHosts) {
final Dictionary<String, Object> config = new Hashtable<>();
config.put("trustedhosts.enabled", enabled);
config.put("trustedhosts.trustAll", trustAll);
config.put("trustedhosts.hosts", trustedHosts);
return config;
}
}