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

- simplify ProxyConfiguration handling

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1763261 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Julian Sedding 2016-10-04 11:29:27 +00:00
parent c08880c2c6
commit e9f8c5b315
6 changed files with 68 additions and 156 deletions

View File

@ -26,6 +26,8 @@
*/
package org.apache.hc.client5.http.osgi.impl;
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;
@ -37,8 +39,6 @@ import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedService;
import java.util.Map;
import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
final class HttpClientBuilderConfigurator {
@ -51,10 +51,10 @@ final class HttpClientBuilderConfigurator {
HttpClientBuilderConfigurator(
final BundleContext bundleContext,
final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations,
final List<ProxyConfiguration> proxyConfigurations,
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
credentialsProvider = new OSGiCredentialsProvider(bundleContext, registeredConfigurations);
routePlanner = new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations);
credentialsProvider = new OSGiCredentialsProvider(proxyConfigurations);
routePlanner = new OSGiHttpRoutePlanner(proxyConfigurations);
socketFactoryRegistry = createSocketFactoryRegistry(bundleContext, trustedHostsConfiguration);
}

View File

@ -33,6 +33,7 @@ import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
import org.apache.hc.client5.http.osgi.services.CachingHttpClientBuilderFactory;
@ -41,6 +42,7 @@ import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
@ -79,6 +81,8 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations = new LinkedHashMap<>();
private final List<ProxyConfiguration> proxyConfigurations = new CopyOnWriteArrayList<>();
private final List<CloseableHttpClient> trackedHttpClients;
public HttpProxyConfigurationActivator() {
@ -109,7 +113,7 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
props);
final HttpClientBuilderConfigurator configurator =
new HttpClientBuilderConfigurator(context, registeredConfigurations, trustedHostConfiguration);
new HttpClientBuilderConfigurator(context, proxyConfigurations, trustedHostConfiguration);
props.clear();
props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID);
@ -179,6 +183,7 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
proxyConfiguration,
config);
registeredConfigurations.put(pid, configurationRegistration);
proxyConfigurations.add(proxyConfiguration);
} else {
proxyConfiguration = (OSGiProxyConfiguration) context.getService(registration.getReference());
}
@ -191,9 +196,13 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
*/
@Override
public void deleted(final String pid) {
final ServiceRegistration<ProxyConfiguration> registeredConfiguration = registeredConfigurations.get(pid);
if (safeUnregister(registeredConfiguration)) {
registeredConfigurations.remove(pid);
final ServiceRegistration<ProxyConfiguration> registration = registeredConfigurations.remove(pid);
if (registration != null) {
final ServiceReference<ProxyConfiguration> ref = registration.getReference();
final ProxyConfiguration config = context.getService(ref);
proxyConfigurations.remove(config);
context.ungetService(ref);
safeUnregister(registration);
}
}

View File

@ -26,7 +26,7 @@
*/
package org.apache.hc.client5.http.osgi.impl;
import java.util.Map;
import java.util.List;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.Credentials;
@ -34,23 +34,16 @@ import org.apache.hc.client5.http.auth.CredentialsStore;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
* @since 4.3
*/
final class OSGiCredentialsProvider implements CredentialsStore {
private final BundleContext bundleContext;
private List<ProxyConfiguration> proxyConfigurations;
private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
public OSGiCredentialsProvider(
final BundleContext bundleContext,
final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations) {
this.bundleContext = bundleContext;
this.registeredConfigurations = registeredConfigurations;
public OSGiCredentialsProvider(final List<ProxyConfiguration> proxyConfigurations) {
this.proxyConfigurations = proxyConfigurations;
}
/**
@ -67,16 +60,13 @@ final class OSGiCredentialsProvider implements CredentialsStore {
@Override
public Credentials getCredentials(final AuthScope authscope, final HttpContext context) {
// iterate over all active proxy configurations at the moment of getting the credential
for (final ServiceRegistration<ProxyConfiguration> registration : registeredConfigurations.values()) {
final ProxyConfiguration proxyConfiguration = bundleContext.getService(registration.getReference());
if (proxyConfiguration != null) {
if (proxyConfiguration.isEnabled()) {
final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort());
if (authscope.match(actual) >= 12) {
final String username = proxyConfiguration.getUsername();
final String password = proxyConfiguration.getPassword();
return new UsernamePasswordCredentials(username, password != null ? password.toCharArray() : null);
}
for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) {
if (proxyConfiguration.isEnabled()) {
final AuthScope actual = new AuthScope(proxyConfiguration.getHostname(), proxyConfiguration.getPort());
if (authscope.match(actual) >= 12) {
final String username = proxyConfiguration.getUsername();
final String password = proxyConfiguration.getPassword();
return new UsernamePasswordCredentials(username, password != null ? password.toCharArray() : null);
}
}
}

View File

@ -28,7 +28,7 @@ package org.apache.hc.client5.http.osgi.impl;
import static org.apache.hc.client5.http.osgi.impl.HostMatcher.HostMatcherFactory.createMatcher;
import java.util.Map;
import java.util.List;
import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
@ -36,24 +36,17 @@ import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
* @since 4.3
*/
final class OSGiHttpRoutePlanner extends DefaultRoutePlanner {
private final BundleContext bundleContext;
private List<ProxyConfiguration> proxyConfigurations;
private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
public OSGiHttpRoutePlanner(
final BundleContext bundleContext,
final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations) {
public OSGiHttpRoutePlanner(final List<ProxyConfiguration> proxyConfigurations) {
super(null);
this.bundleContext = bundleContext;
this.registeredConfigurations = registeredConfigurations;
this.proxyConfigurations = proxyConfigurations;
}
/**
@ -61,22 +54,17 @@ final class OSGiHttpRoutePlanner extends DefaultRoutePlanner {
*/
@Override
protected HttpHost determineProxy(final HttpHost target, final HttpRequest request, final HttpContext context) throws HttpException {
ProxyConfiguration proxyConfiguration = null;
HttpHost proxyHost = null;
for (final ServiceRegistration<ProxyConfiguration> registration : registeredConfigurations.values()) {
proxyConfiguration = bundleContext.getService(registration.getReference());
if (proxyConfiguration != null) {
if (proxyConfiguration.isEnabled()) {
for (final String exception : proxyConfiguration.getProxyExceptions()) {
if (createMatcher(exception).matches(target.getHostName())) {
return null;
}
}
if (null == proxyHost)
{
proxyHost = new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort());
for (final ProxyConfiguration proxyConfiguration : proxyConfigurations) {
if (proxyConfiguration.isEnabled()) {
for (final String exception : proxyConfiguration.getProxyExceptions()) {
if (createMatcher(exception).matches(target.getHostName())) {
return null;
}
}
if (null == proxyHost) {
proxyHost = new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort());
}
}
}

View File

@ -125,12 +125,12 @@ public final class OSGiProxyConfiguration implements ProxyConfiguration {
}
public void update(final Dictionary<String, ?> config) {
enabled = to(config.get(PROPERTYNAME_PROXY_ENABLED), boolean.class, PROPERTYDEFAULT_PROXY_ENABLED);
hostname = to(config.get(PROPERTYNAME_PROXY_HOSTNAME), String.class, PROPERTYDEFAULT_PROXY_HOSTNAME);
port = to(config.get(PROPERTYNAME_PROXY_PORT), int.class, PROPERTYDEFAULT_PROXY_PORT);
username = to(config.get(PROPERTYNAME_PROXY_USERNAME), String.class, PROPERTYDEFAULT_PROXY_USERNAME);
password = to(config.get(PROPERTYNAME_PROXY_PASSWORD), String.class, PROPERTYDEFAULT_PROXY_PASSWORD);
proxyExceptions = to(config.get(PROPERTYNAME_PROXY_EXCEPTIONS), String[].class, PROPERTYDEFAULT_PROXY_EXCEPTIONS);
enabled = to(config.get(PROPERTYNAME_PROXY_ENABLED), boolean.class, PROPERTYDEFAULT_PROXY_ENABLED);
hostname = to(config.get(PROPERTYNAME_PROXY_HOSTNAME), String.class, PROPERTYDEFAULT_PROXY_HOSTNAME);
port = to(config.get(PROPERTYNAME_PROXY_PORT), int.class, PROPERTYDEFAULT_PROXY_PORT);
username = to(config.get(PROPERTYNAME_PROXY_USERNAME), String.class, PROPERTYDEFAULT_PROXY_USERNAME);
password = to(config.get(PROPERTYNAME_PROXY_PASSWORD), String.class, PROPERTYDEFAULT_PROXY_PASSWORD);
proxyExceptions = to(config.get(PROPERTYNAME_PROXY_EXCEPTIONS), String[].class, PROPERTYDEFAULT_PROXY_EXCEPTIONS);
}
@Override

View File

@ -26,104 +26,30 @@
*/
package org.apache.hc.client5.http.osgi.impl;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.net.InetAddress;
import java.util.Map;
import java.util.TreeMap;
import java.util.Hashtable;
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
import org.apache.hc.core5.http.HttpHost;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* @since 4.4.3
*/
public class TestOSGiHttpRoutePlanner {
final ProxyConfiguration pc1 = new ProxyConfiguration() {
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getHostname() {
return "proxy1";
}
@Override
public int getPort() {
return 8080;
}
@Override
public String getUsername() {
return "";
}
@Override
public String getPassword() {
return "";
}
@Override
public String[] getProxyExceptions() {
return new String[]{"localhost", "127.0.0.1", ".apache.org"};
}
};
final ProxyConfiguration pc2 = new ProxyConfiguration() {
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getHostname() {
return "proxy2";
}
@Override
public int getPort() {
return 9090;
}
@Override
public String getUsername() {
return "";
}
@Override
public String getPassword() {
return "";
}
@Override
public String[] getProxyExceptions() {
return new String[]{"localhost", "127.0.0.1", ".oracle.com", "12.34.34.8"};
}
};
private final ProxyConfiguration pc1 = proxy("proxy1", 8080, "localhost", "127.0.0.1", ".apache.org");
private final ProxyConfiguration pc2 = proxy("proxy2", 9090, "localhost", "127.0.0.1", ".oracle.com", "12.34.34.8");
@Test
public void testDeterminProxy() throws Exception {
final ServiceReference<ProxyConfiguration> sRef1 = mock(ServiceReference.class);
final ServiceRegistration<ProxyConfiguration> sReg1 = mock(ServiceRegistration.class);
when(sReg1.getReference()).thenReturn(sRef1);
final BundleContext bc = mock(BundleContext.class);
when(bc.getService(sRef1)).thenReturn(this.pc1);
final Map<String, ServiceRegistration<ProxyConfiguration>> registrations = new TreeMap<>(); // TreeMap for order
registrations.put("foo1", sReg1);
OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations);
OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(singletonList(pc1));
HttpHost proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null);
assertNull(proxy);
@ -145,13 +71,7 @@ public class TestOSGiHttpRoutePlanner {
// test with more than one registration of proxyConfiguration
final ServiceReference<ProxyConfiguration> sRef2 = mock(ServiceReference.class);
final ServiceRegistration<ProxyConfiguration> sReg2 = mock(ServiceRegistration.class);
when(sReg2.getReference()).thenReturn(sRef2);
when(bc.getService(sRef2)).thenReturn(this.pc2);
registrations.put("foo2", sReg2);
planner = new OSGiHttpRoutePlanner(bc, registrations);
planner = new OSGiHttpRoutePlanner(asList(pc1, pc2));
proxy = planner.determineProxy(new HttpHost("localhost", 8090), null, null);
assertNull(proxy);
@ -171,15 +91,7 @@ public class TestOSGiHttpRoutePlanner {
@Test
public void testMasking() throws Exception {
final ServiceReference<ProxyConfiguration> sRef2 = mock(ServiceReference.class);
final ServiceRegistration<ProxyConfiguration> sReg2 = mock(ServiceRegistration.class);
when(sReg2.getReference()).thenReturn(sRef2);
final BundleContext bc = mock(BundleContext.class);
when(bc.getService(sRef2)).thenReturn(this.pc2);
final Map<String, ServiceRegistration<ProxyConfiguration>> registrations = new TreeMap<>();
registrations.put("foo2", sReg2);
final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations);
final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(singletonList(pc2));
HttpHost proxy = planner.determineProxy(new HttpHost("12.34.34.2", 4554), null, null);
assertNotNull(proxy);
@ -189,4 +101,17 @@ public class TestOSGiHttpRoutePlanner {
assertNotNull(proxy);
}
private ProxyConfiguration proxy(final String host, final int port, final String... exceptions) {
final OSGiProxyConfiguration proxyConfiguration = new OSGiProxyConfiguration();
final Hashtable<String, Object> config = new Hashtable<>();
config.put("proxy.enabled", true);
config.put("proxy.host", host);
config.put("proxy.port", port);
config.put("proxy.user", "");
config.put("proxy.password", "");
config.put("proxy.exceptions", exceptions);
proxyConfiguration.update(config);
return proxyConfiguration;
}
}