You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by si...@apache.org on 2016/07/26 12:42:27 UTC

svn commit: r1754122 - in /httpcomponents/httpclient/trunk/httpclient5-osgi: ./ src/main/java/org/apache/hc/client5/http/osgi/impl/ src/main/java/org/apache/hc/client5/http/osgi/services/ src/main/resources/OSGI-INF/metatype/ src/test/java/org/apache/h...

Author: simonetripodi
Date: Tue Jul 26 12:42:27 2016
New Revision: 1754122

URL: http://svn.apache.org/viewvc?rev=1754122&view=rev
Log:
HTTPCLIENT-1752 - Allow to configure the OSGI clients with relaxed SSL checks

initial check-in, GitHub pull request (https://github.com/apache/httpclient/pull/56) accepted 


Added:
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java   (with props)
Modified:
    httpcomponents/httpclient/trunk/httpclient5-osgi/pom.xml
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HttpProxyConfigurationActivator.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingClientBuilderFactory.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingHttpClientBuilder.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiClientBuilderFactory.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCredentialsProvider.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpClientBuilder.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpRoutePlanner.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiProxyConfiguration.java
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml
    httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiHttpRoutePlanner.java

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/pom.xml?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/pom.xml (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/pom.xml Tue Jul 26 12:42:27 2016
@@ -59,12 +59,13 @@
       <groupId>org.apache.httpcomponents.core5</groupId>
       <artifactId>httpcore5-osgi</artifactId>
       <version>${httpcore.version}</version>
-        <exclusions>
-          <exclusion>
-              <groupId>org.apache.httpcomponents.client5</groupId>
-              <artifactId>httpcore-nio</artifactId>
-          </exclusion>
-        </exclusions>
+      <scope>provided</scope>
+      <exclusions>
+        <exclusion>
+            <groupId>org.apache.httpcomponents.client5</groupId>
+            <artifactId>httpcore-nio</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>commons-codec</groupId>
@@ -91,6 +92,7 @@
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.compendium</artifactId>
       <version>${osgi.framework.version}</version>
+      <scope>provided</scope>
     </dependency>
     <!-- test dependencies, mainly OSGi runtime environment -->
     <dependency>

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,158 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.impl;
+
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+interface HostMatcher {
+
+    public static final String DOT = ".";
+
+    /**
+     * The IP mask pattern against which hosts are matched.
+     */
+    public static final Pattern IP_MASK_PATTERN = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
+
+    boolean matches(String host);
+
+    public static class HostMatcherFactory {
+
+        public static HostMatcher createMatcher(final String name) {
+            final NetworkAddress na = NetworkAddress.parse(name);
+            if (na != null) {
+                return new IPAddressMatcher(na);
+            }
+
+            if (name.startsWith(DOT)) {
+                return new DomainNameMatcher(name);
+            }
+
+            return new HostNameMatcher(name);
+        }
+
+    }
+
+    public static class HostNameMatcher implements HostMatcher {
+
+        private final String hostName;
+
+        HostNameMatcher(final String hostName) {
+            this.hostName = hostName;
+        }
+
+        @Override
+        public boolean matches(final String host) {
+            return hostName.equalsIgnoreCase(host);
+        }
+    }
+
+    public static class DomainNameMatcher implements HostMatcher {
+
+        private final String domainName;
+
+        DomainNameMatcher(final String domainName) {
+            this.domainName = domainName.toLowerCase(Locale.ROOT);
+        }
+
+        @Override
+        public boolean matches(final String host) {
+            return host.toLowerCase(Locale.ROOT).endsWith(domainName);
+        }
+    }
+
+    public static class IPAddressMatcher implements HostMatcher {
+
+        private final NetworkAddress address;
+
+        IPAddressMatcher(final NetworkAddress address) {
+            this.address = address;
+        }
+
+        @Override
+        public boolean matches(final String host) {
+            final NetworkAddress hostAddress = NetworkAddress.parse(host);
+            return hostAddress != null && address.address == (hostAddress.address & address.mask);
+        }
+
+    }
+
+    public static class NetworkAddress {
+
+        final int address;
+
+        final int mask;
+
+        static NetworkAddress parse(final String adrSpec) {
+
+            if (null != adrSpec) {
+                final Matcher nameMatcher = IP_MASK_PATTERN.matcher(adrSpec);
+                if (nameMatcher.matches()) {
+                    try {
+                        final int i1 = toInt(nameMatcher.group(1), 255);
+                        final int i2 = toInt(nameMatcher.group(2), 255);
+                        final int i3 = toInt(nameMatcher.group(3), 255);
+                        final int i4 = toInt(nameMatcher.group(4), 255);
+                        final int ip = i1 << 24 | i2 << 16 | i3 << 8 | i4;
+
+                        int mask = toInt(nameMatcher.group(4), 32);
+                        mask = (mask == 32) ? -1 : -1 - (-1 >>> mask);
+
+                        return new NetworkAddress(ip, mask);
+                    } catch (final NumberFormatException nfe) {
+                        // not expected after the pattern match !
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private static int toInt(final String value, final int max) {
+            if (value == null || value.isEmpty()) {
+                return max;
+            }
+
+            int number = Integer.parseInt(value);
+            if (number > max) {
+                number = max;
+            }
+            return number;
+        }
+
+        NetworkAddress(final int address, final int mask) {
+            this.address = address;
+            this.mask = mask;
+        }
+
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HostMatcher.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HttpProxyConfigurationActivator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HttpProxyConfigurationActivator.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HttpProxyConfigurationActivator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/HttpProxyConfigurationActivator.java Tue Jul 26 12:42:27 2016
@@ -43,6 +43,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
 import org.osgi.service.cm.ManagedServiceFactory;
 
 /**
@@ -52,23 +53,31 @@ public final class HttpProxyConfiguratio
 
     private static final String PROXY_SERVICE_FACTORY_NAME = "Apache HTTP Client Proxy Configuration Factory";
 
-    private static final String PROXY_SERVICE_PID = "org.apache.http.proxyconfigurator";
+    private static final String PROXY_SERVICE_PID = "org.apache.hc.client5.http.proxyconfigurator";
+
+    private static final String TRUSTED_HOSTS_SERVICE_NAME = "Apache HTTP Client Trusted Hosts Configuration";
+
+    private static final String TRUSTED_HOSTS_PID = "org.apache.hc.client5.http.trustedhosts";
 
     private static final String BUILDER_FACTORY_SERVICE_NAME = "Apache HTTP Client Client Factory";
 
-    private static final String BUILDER_FACTORY_SERVICE_PID = "org.apache.http.httpclientfactory";
+    private static final String BUILDER_FACTORY_SERVICE_PID = "org.apache.hc.client5.http.httpclientfactory";
 
     private static final String CACHEABLE_BUILDER_FACTORY_SERVICE_NAME = "Apache HTTP Client Caching Client Factory";
 
-    private static final String CACHEABLE_BUILDER_FACTORY_SERVICE_PID = "org.apache.http.cachinghttpclientfactory";
+    private static final String CACHEABLE_BUILDER_FACTORY_SERVICE_PID = "org.apache.hc.client5.http.cachinghttpclientfactory";
+
+    private ServiceRegistration<ManagedServiceFactory> configurator;
+
+    private ServiceRegistration<ManagedService> trustedHostConfiguration;
 
-    private ServiceRegistration configurator;
+    private ServiceRegistration<HttpClientBuilderFactory> clientFactory;
 
-    private ServiceRegistration clientFactory;
+    private ServiceRegistration<CachingHttpClientBuilderFactory> cachingClientFactory;
 
     private BundleContext context;
 
-    private final Map<String, ServiceRegistration> registeredConfigurations = new LinkedHashMap<>();
+    private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations = new LinkedHashMap<>();
 
     private final List<CloseableHttpClient> trackedHttpClients;
 
@@ -89,23 +98,37 @@ public final class HttpProxyConfiguratio
         props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR));
         props.put(Constants.SERVICE_DESCRIPTION, PROXY_SERVICE_FACTORY_NAME);
 
-        configurator = context.registerService(ManagedServiceFactory.class.getName(), this, props);
+        configurator = context.registerService(ManagedServiceFactory.class, this, props);
+
+        props.clear();
+        props.put(Constants.SERVICE_PID, TRUSTED_HOSTS_PID);
+        props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR));
+        props.put(Constants.SERVICE_DESCRIPTION, TRUSTED_HOSTS_SERVICE_NAME);
+        trustedHostConfiguration = context.registerService(ManagedService.class,
+                                                           new OSGiTrustedHostsConfiguration(),
+                                                           props);
 
         props.clear();
         props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID);
         props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR));
         props.put(Constants.SERVICE_DESCRIPTION, BUILDER_FACTORY_SERVICE_NAME);
-        clientFactory = context.registerService(HttpClientBuilderFactory.class.getName(),
-                                                new OSGiClientBuilderFactory(context, registeredConfigurations, trackedHttpClients),
+        clientFactory = context.registerService(HttpClientBuilderFactory.class,
+                                                new OSGiClientBuilderFactory(context,
+                                                                             registeredConfigurations,
+                                                                             trustedHostConfiguration,
+                                                                             trackedHttpClients),
                                                 props);
 
         props.clear();
         props.put(Constants.SERVICE_PID, CACHEABLE_BUILDER_FACTORY_SERVICE_PID);
         props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders(Constants.BUNDLE_VENDOR));
         props.put(Constants.SERVICE_DESCRIPTION, CACHEABLE_BUILDER_FACTORY_SERVICE_NAME);
-        clientFactory = context.registerService(CachingHttpClientBuilderFactory.class.getName(),
-                new OSGiCachingClientBuilderFactory(context, registeredConfigurations, trackedHttpClients),
-                props);
+        cachingClientFactory = context.registerService(CachingHttpClientBuilderFactory.class,
+                                                       new OSGiCachingClientBuilderFactory(context,
+                                                                                           registeredConfigurations,
+                                                                                           trustedHostConfiguration,
+                                                                                           trackedHttpClients),
+                                                       props);
     }
 
     /**
@@ -114,18 +137,14 @@ public final class HttpProxyConfiguratio
     @Override
     public void stop(final BundleContext context) throws Exception {
         // unregister services
-        for (final ServiceRegistration registeredConfiguration : registeredConfigurations.values()) {
-            registeredConfiguration.unregister();
+        for (final ServiceRegistration<ProxyConfiguration> registeredConfiguration : registeredConfigurations.values()) {
+            safeUnregister(registeredConfiguration);
         }
 
-        // unregister service factory
-        if (configurator != null) {
-            configurator.unregister();
-        }
-
-        if (clientFactory != null) {
-            clientFactory.unregister();
-        }
+        safeUnregister(configurator);
+        safeUnregister(clientFactory);
+        safeUnregister(cachingClientFactory);
+        safeUnregister(trustedHostConfiguration);
 
         // ensure all http clients - generated with the - are terminated
         for (final CloseableHttpClient client : trackedHttpClients) {
@@ -152,24 +171,22 @@ public final class HttpProxyConfiguratio
      * {@inheritDoc}
      */
     @Override
-    public void updated(final String pid, @SuppressWarnings("rawtypes") final Dictionary config) throws ConfigurationException {
-        final ServiceRegistration registration = registeredConfigurations.get(pid);
-        OSGiProxyConfiguration proxyConfiguration;
+    public void updated(final String pid, final Dictionary<String, ?> config) throws ConfigurationException {
+        final ServiceRegistration<ProxyConfiguration> registration = registeredConfigurations.get(pid);
+        final OSGiProxyConfiguration proxyConfiguration;
 
         if (registration == null) {
             proxyConfiguration = new OSGiProxyConfiguration();
-            final ServiceRegistration configurationRegistration = context.registerService(ProxyConfiguration.class.getName(),
-                                                                                    proxyConfiguration,
-                                                                                    config);
+            final ServiceRegistration<ProxyConfiguration> configurationRegistration =
+                            context.registerService(ProxyConfiguration.class,
+                                                    proxyConfiguration,
+                                                    config);
             registeredConfigurations.put(pid, configurationRegistration);
         } else {
             proxyConfiguration = (OSGiProxyConfiguration) context.getService(registration.getReference());
         }
 
-        @SuppressWarnings("unchecked") // data type is known
-        final
-        Dictionary<String, Object> properties = config;
-        proxyConfiguration.update(properties);
+        proxyConfiguration.update(config);
     }
 
     /**
@@ -177,13 +194,20 @@ public final class HttpProxyConfiguratio
      */
     @Override
     public void deleted(final String pid) {
-        final ServiceRegistration registeredConfiguration = registeredConfigurations.get(pid);
-        if (null != registeredConfiguration) {
-            registeredConfiguration.unregister();
+        final ServiceRegistration<ProxyConfiguration> registeredConfiguration = registeredConfigurations.get(pid);
+        if (safeUnregister(registeredConfiguration)) {
             registeredConfigurations.remove(pid);
         }
     }
 
+    private static <S> boolean safeUnregister(final ServiceRegistration<S> serviceRegistration) {
+        if (serviceRegistration != null) {
+            serviceRegistration.unregister();
+            return true;
+        }
+        return false;
+    }
+
     private static void closeQuietly(final Closeable closeable) {
         try {
             closeable.close();

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingClientBuilderFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingClientBuilderFactory.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingClientBuilderFactory.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingClientBuilderFactory.java Tue Jul 26 12:42:27 2016
@@ -32,28 +32,37 @@ import java.util.Map;
 import org.apache.hc.client5.http.impl.cache.CachingHttpClientBuilder;
 import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
 import org.apache.hc.client5.http.osgi.services.CachingHttpClientBuilderFactory;
+import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 
 class OSGiCachingClientBuilderFactory implements CachingHttpClientBuilderFactory {
 
     private final BundleContext bundleContext;
 
-    private final Map<String, ServiceRegistration> registeredConfigurations;
+    private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
+
+    private final ServiceRegistration<ManagedService> trustedHostConfiguration;
 
     private final List<CloseableHttpClient> trackedHttpClients;
 
     public OSGiCachingClientBuilderFactory(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations,
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations,
+            final ServiceRegistration<ManagedService> trustedHostConfiguration,
             final List<CloseableHttpClient> trackedHttpClients) {
         this.bundleContext = bundleContext;
         this.registeredConfigurations = registeredConfigurations;
+        this.trustedHostConfiguration = trustedHostConfiguration;
         this.trackedHttpClients = trackedHttpClients;
     }
 
     @Override
     public CachingHttpClientBuilder newBuilder() {
-        return new OSGiCachingHttpClientBuilder(bundleContext, registeredConfigurations, trackedHttpClients);
+        return new OSGiCachingHttpClientBuilder(bundleContext,
+                                                registeredConfigurations,
+                                                trustedHostConfiguration,
+                                                trackedHttpClients);
     }
 }

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingHttpClientBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingHttpClientBuilder.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingHttpClientBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCachingHttpClientBuilder.java Tue Jul 26 12:42:27 2016
@@ -26,13 +26,22 @@
  */
 package org.apache.hc.client5.http.osgi.impl;
 
+import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
+
 import java.util.List;
 import java.util.Map;
 
 import org.apache.hc.client5.http.impl.cache.CachingHttpClientBuilder;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
 import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
+import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
+import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
+import org.apache.hc.core5.http.config.RegistryBuilder;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 
 final class OSGiCachingHttpClientBuilder extends CachingHttpClientBuilder {
 
@@ -40,13 +49,19 @@ final class OSGiCachingHttpClientBuilder
 
     public OSGiCachingHttpClientBuilder(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations,
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations,
+            final ServiceRegistration<ManagedService> trustedHostConfiguration,
             final List<CloseableHttpClient> trackedHttpClients) {
         this.trackedHttpClients = trackedHttpClients;
         setDefaultCredentialsProvider(
                 new OSGiCredentialsProvider(bundleContext, registeredConfigurations));
         setRoutePlanner(
                 new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations));
+        final LayeredConnectionSocketFactory defaultSocketFactory = getSocketFactory();
+        setConnectionManager(new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create()
+                                                                    .register("http", PlainConnectionSocketFactory.INSTANCE)
+                                                                    .register("https", new RelaxedLayeredConnectionSocketFactory(bundleContext, trustedHostConfiguration, defaultSocketFactory))
+                                                                    .build()));
     }
 
     @Override

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiClientBuilderFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiClientBuilderFactory.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiClientBuilderFactory.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiClientBuilderFactory.java Tue Jul 26 12:42:27 2016
@@ -32,8 +32,10 @@ import java.util.Map;
 import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
 import org.apache.hc.client5.http.osgi.services.HttpClientBuilderFactory;
+import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 
 /**
  * @since 4.3
@@ -42,22 +44,26 @@ public final class OSGiClientBuilderFact
 
     private final BundleContext bundleContext;
 
-    private final Map<String, ServiceRegistration> registeredConfigurations;
+    private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
+
+    private final ServiceRegistration<ManagedService> trustedHostConfiguration;
 
     private final List<CloseableHttpClient> trackedHttpClients;
 
     public OSGiClientBuilderFactory(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations,
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations,
+            final ServiceRegistration<ManagedService> trustedHostConfiguration,
             final List<CloseableHttpClient> trackedHttpClients) {
         this.bundleContext = bundleContext;
         this.registeredConfigurations = registeredConfigurations;
+        this.trustedHostConfiguration = trustedHostConfiguration;
         this.trackedHttpClients = trackedHttpClients;
     }
 
     @Override
     public HttpClientBuilder newBuilder() {
-        return new OSGiHttpClientBuilder(bundleContext, registeredConfigurations, trackedHttpClients);
+        return new OSGiHttpClientBuilder(bundleContext, registeredConfigurations, trustedHostConfiguration, trackedHttpClients);
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCredentialsProvider.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCredentialsProvider.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCredentialsProvider.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiCredentialsProvider.java Tue Jul 26 12:42:27 2016
@@ -43,11 +43,11 @@ final class OSGiCredentialsProvider impl
 
     private final BundleContext bundleContext;
 
-    private final Map<String, ServiceRegistration> registeredConfigurations;
+    private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
 
     public OSGiCredentialsProvider(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations) {
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations) {
         this.bundleContext = bundleContext;
         this.registeredConfigurations = registeredConfigurations;
     }
@@ -66,10 +66,9 @@ final class OSGiCredentialsProvider impl
     @Override
     public Credentials getCredentials(final AuthScope authscope) {
         // iterate over all active proxy configurations at the moment of getting the credential
-        for (final ServiceRegistration registration : registeredConfigurations.values()) {
-            final Object proxyConfigurationObject = bundleContext.getService(registration.getReference());
-            if (proxyConfigurationObject != null) {
-                final ProxyConfiguration proxyConfiguration = (ProxyConfiguration) proxyConfigurationObject;
+        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) {

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpClientBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpClientBuilder.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpClientBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpClientBuilder.java Tue Jul 26 12:42:27 2016
@@ -26,14 +26,23 @@
  */
 package org.apache.hc.client5.http.osgi.impl;
 
+import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
+
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
 import org.apache.hc.client5.http.impl.sync.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
+import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
+import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
+import org.apache.hc.core5.http.config.RegistryBuilder;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 
 /**
  * @since 4.3
@@ -44,13 +53,19 @@ final class OSGiHttpClientBuilder extend
 
     public OSGiHttpClientBuilder(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations,
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations,
+            final ServiceRegistration<ManagedService> trustedHostConfiguration,
             final List<CloseableHttpClient> trackedHttpClients) {
         this.trackedHttpClients = trackedHttpClients;
         setDefaultCredentialsProvider(
                 new OSGiCredentialsProvider(bundleContext, registeredConfigurations));
         setRoutePlanner(
                 new OSGiHttpRoutePlanner(bundleContext, registeredConfigurations));
+        final LayeredConnectionSocketFactory defaultSocketFactory = getSocketFactory();
+        setConnectionManager(new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create()
+                                                                    .register("http", PlainConnectionSocketFactory.INSTANCE)
+                                                                    .register("https", new RelaxedLayeredConnectionSocketFactory(bundleContext, trustedHostConfiguration, defaultSocketFactory))
+                                                                    .build()));
     }
 
     @Override

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpRoutePlanner.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpRoutePlanner.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpRoutePlanner.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiHttpRoutePlanner.java Tue Jul 26 12:42:27 2016
@@ -26,10 +26,9 @@
  */
 package org.apache.hc.client5.http.osgi.impl;
 
-import java.util.Locale;
+import static org.apache.hc.client5.http.osgi.impl.HostMatcher.HostMatcherFactory.createMatcher;
+
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
 import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
@@ -45,23 +44,13 @@ import org.osgi.framework.ServiceRegistr
  */
 final class OSGiHttpRoutePlanner extends DefaultRoutePlanner {
 
-    private static final String DOT = ".";
-
-    /**
-     * The IP mask pattern against which hosts are matched.
-     */
-    public static final Pattern IP_MASK_PATTERN = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
-                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
-                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
-                                                                  "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
-
     private final BundleContext bundleContext;
 
-    private final Map<String, ServiceRegistration> registeredConfigurations;
+    private final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations;
 
     public OSGiHttpRoutePlanner(
             final BundleContext bundleContext,
-            final Map<String, ServiceRegistration> registeredConfigurations) {
+            final Map<String, ServiceRegistration<ProxyConfiguration>> registeredConfigurations) {
         super(null);
         this.bundleContext = bundleContext;
         this.registeredConfigurations = registeredConfigurations;
@@ -74,10 +63,9 @@ final class OSGiHttpRoutePlanner extends
     protected HttpHost determineProxy(final HttpHost target, final HttpRequest request, final HttpContext context) throws HttpException {
         ProxyConfiguration proxyConfiguration = null;
         HttpHost proxyHost = null;
-        for (final ServiceRegistration registration : registeredConfigurations.values()) {
-            final Object proxyConfigurationObject = bundleContext.getService(registration.getReference());
-            if (proxyConfigurationObject != null) {
-                proxyConfiguration = (ProxyConfiguration) proxyConfigurationObject;
+        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())) {
@@ -95,117 +83,4 @@ final class OSGiHttpRoutePlanner extends
         return proxyHost;
     }
 
-    private static HostMatcher createMatcher(final String name) {
-        final NetworkAddress na = NetworkAddress.parse(name);
-        if (na != null) {
-            return new IPAddressMatcher(na);
-        }
-
-        if (name.startsWith(DOT)) {
-            return new DomainNameMatcher(name);
-        }
-
-        return new HostNameMatcher(name);
-    }
-
-    private interface HostMatcher {
-
-        boolean matches(String host);
-
-    }
-
-    private static class HostNameMatcher implements HostMatcher {
-
-        private final String hostName;
-
-        HostNameMatcher(final String hostName) {
-            this.hostName = hostName;
-        }
-
-        @Override
-        public boolean matches(final String host) {
-            return hostName.equalsIgnoreCase(host);
-        }
-    }
-
-    private static class DomainNameMatcher implements HostMatcher {
-
-        private final String domainName;
-
-        DomainNameMatcher(final String domainName) {
-            this.domainName = domainName.toLowerCase(Locale.ROOT);
-        }
-
-        @Override
-        public boolean matches(final String host) {
-            return host.toLowerCase(Locale.ROOT).endsWith(domainName);
-        }
-    }
-
-    private static class IPAddressMatcher implements HostMatcher {
-
-        private final NetworkAddress address;
-
-        IPAddressMatcher(final NetworkAddress address) {
-            this.address = address;
-        }
-
-        @Override
-        public boolean matches(final String host) {
-            final NetworkAddress hostAddress = NetworkAddress.parse(host);
-            return hostAddress != null && address.address == (hostAddress.address & address.mask);
-        }
-
-    }
-
-    private static class NetworkAddress {
-
-        final int address;
-
-        final int mask;
-
-        static NetworkAddress parse(final String adrSpec) {
-
-            if (null != adrSpec) {
-                final Matcher nameMatcher = IP_MASK_PATTERN.matcher(adrSpec);
-                if (nameMatcher.matches()) {
-                    try {
-                        final int i1 = toInt(nameMatcher.group(1), 255);
-                        final int i2 = toInt(nameMatcher.group(2), 255);
-                        final int i3 = toInt(nameMatcher.group(3), 255);
-                        final int i4 = toInt(nameMatcher.group(4), 255);
-                        final int ip = i1 << 24 | i2 << 16 | i3 << 8 | i4;
-
-                        int mask = toInt(nameMatcher.group(4), 32);
-                        mask = (mask == 32) ? -1 : -1 - (-1 >>> mask);
-
-                        return new NetworkAddress(ip, mask);
-                    } catch (final NumberFormatException nfe) {
-                        // not expected after the pattern match !
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        private static int toInt(final String value, final int max) {
-            if (value == null || value.isEmpty()) {
-                return max;
-            }
-
-            int number = Integer.parseInt(value);
-            if (number > max) {
-                number = max;
-            }
-            return number;
-        }
-
-        NetworkAddress(final int address, final int mask) {
-            this.address = address;
-            this.mask = mask;
-        }
-
-    }
-
 }

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiProxyConfiguration.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiProxyConfiguration.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiProxyConfiguration.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiProxyConfiguration.java Tue Jul 26 12:42:27 2016
@@ -124,7 +124,7 @@ public final class OSGiProxyConfiguratio
         return proxyExceptions;
     }
 
-    public void update(final Dictionary<String, Object> config) {
+    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);

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.impl;
+
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static org.apache.hc.client5.http.osgi.impl.PropertiesUtils.to;
+
+import java.util.Dictionary;
+
+import org.apache.hc.client5.http.osgi.services.TrustedHostsConfiguration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * @since 5.0-alpha2
+ */
+final class OSGiTrustedHostsConfiguration implements ManagedService, TrustedHostsConfiguration {
+
+    /**
+     * Property indicating whether this particular configuration is enabled (shall be used or not). Defaults to true.
+     */
+    private static final String PROPERTYNAME_TRUSTEDHOSTS_ENABLED = "trustedhosts.enabled";
+
+    private static final Boolean PROPERTYDEFAULT_TRUSTEDHOSTS_ENABLED = Boolean.TRUE;
+
+    /**
+     * Property indicating whether this particular configuration . Defaults to false.
+     */
+    private static final String PROPERTYNAME_TRUST_ALL = "trustedhosts.trustAll";
+
+    private static final Boolean PROPERTYDEFAULT_TRUST_ALL = Boolean.FALSE;
+
+    /**
+     * A multivalue property representing host patterns which is an acceptable match with the server's authentication scheme.
+     * By default <code>localhost</code> (<code>127.0.0.1</code>) is trusted.
+     */
+    private static final String PROPERTYNAME_TRUSTED_HOSTS = "trustedhosts.hosts";
+
+    private static final String[] PROPERTYDEFAULT_TRUSTED_HOSTS = new String[]{ "localhost", "127.0.0.1" };
+
+    private Boolean enabled = PROPERTYDEFAULT_TRUSTEDHOSTS_ENABLED; // fewer boxing conversions needed when stored as an object
+
+    private Boolean trustAll = PROPERTYDEFAULT_TRUST_ALL; // fewer boxing conversions needed when stored as an object
+
+    private String[] trustedHosts;
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public boolean trustAll() {
+        return trustAll;
+    }
+
+    @Override
+    public String[] getTrustedHosts() {
+        return trustedHosts;
+    }
+
+    @Override
+    public void updated(final Dictionary<String, ?> config) throws ConfigurationException {
+        if (config == null) {
+            return;
+        }
+
+        enabled = to(config.get(PROPERTYNAME_TRUSTEDHOSTS_ENABLED), boolean.class, PROPERTYDEFAULT_TRUSTEDHOSTS_ENABLED);
+        trustAll = to(config.get(PROPERTYNAME_TRUST_ALL), boolean.class, PROPERTYDEFAULT_TRUST_ALL);
+        trustedHosts = to(config.get(PROPERTYNAME_TRUSTED_HOSTS), String[].class, PROPERTYDEFAULT_TRUSTED_HOSTS);
+    }
+
+    @Override
+    public String toString() {
+        return format("ProxyConfiguration [enabled=%s, trustAll=%s, trustedHosts=%s]",
+                      enabled, trustAll, asList(trustedHosts));
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/OSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,102 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.impl;
+
+import static org.apache.hc.client5.http.osgi.impl.HostMatcher.HostMatcherFactory.createMatcher;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+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 final LayeredConnectionSocketFactory defaultSocketFactory;
+
+    private final BundleContext bundleContext;
+
+    private final ServiceRegistration<ManagedService> trustedHostConfiguration;
+
+    public RelaxedLayeredConnectionSocketFactory(final BundleContext bundleContext,
+                                                 final ServiceRegistration<ManagedService> trustedHostConfiguration,
+                                                 final LayeredConnectionSocketFactory defaultSocketFactory) {
+        this.bundleContext = bundleContext;
+        this.trustedHostConfiguration = trustedHostConfiguration;
+        this.defaultSocketFactory = defaultSocketFactory;
+    }
+
+    @Override
+    public Socket createLayeredSocket(final Socket socket,
+                                      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 trust all there is no check to perform
+                if (configuration.trustAll()) {
+                    return socket;
+                }
+
+                // blindly verify the host if in the trust list
+                for (String trustedHost : configuration.getTrustedHosts()) {
+                    if (createMatcher(trustedHost).matches(target)) {
+                        return socket;
+                    }
+                }
+            }
+        }
+
+        // follow back to the default behavior
+        return defaultSocketFactory.createLayeredSocket(socket, target, port, context);
+    }
+
+    @Override
+    public Socket createSocket(final HttpContext context) throws IOException {
+        return defaultSocketFactory.createSocket(context);
+    }
+
+    @Override
+    public Socket connectSocket(final int connectTimeout,
+                                final Socket sock,
+                                final HttpHost host,
+                                final InetSocketAddress remoteAddress,
+                                final InetSocketAddress localAddress,
+                                final HttpContext context) throws IOException {
+        return defaultSocketFactory.connectSocket(connectTimeout, sock, host, remoteAddress, localAddress, context);
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/impl/RelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.services;
+
+/**
+ * @since 5.0-alpha2
+ */
+public interface TrustedHostsConfiguration {
+
+    /**
+     * Flag to mark if current configuration has to be processed when creating SSL sessions..
+     *
+     * @return true if current configuration has to be processed when creating an SSL session, false otherwise.
+     */
+    boolean isEnabled();
+
+    /**
+     * Flag to mark all SSL certificates are blindly trusted by the client.
+     *
+     * Pay attention on no enabling this feature in production environment as it is totally insecure.
+     *
+     * @return true if all SSL certificates are blindly trusted by the client, false otherwise.
+     */
+    boolean trustAll();
+
+    /**
+     * The list of trusted hosts for which self-signed certificate is acceptable.
+     *
+     * @return an array representing the list of trusted hosts for which self-signed certificate is acceptable.
+     */
+    String[] getTrustedHosts();
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/java/org/apache/hc/client5/http/osgi/services/TrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.properties Tue Jul 26 12:42:27 2016
@@ -74,4 +74,21 @@ proxy.exceptions.description = Lists dom
  reason you might want to indicate both the network address and the domain for \
  targets which should not be passed through the proxy. This property has no \
  effect if this proxy configuration is disabled. The default value is [ localhost, \
- 127.0.0.1 ].
\ No newline at end of file
+ 127.0.0.1 ].
+
+trustedhosts.name = Apache HTTP Client Trusted Hosts Configuration
+trustedhosts.description = SSL configuration for trusted SSL connections with server self-signed certificates.
+
+trustedhosts.enabled.name = SSL configuration enabled
+trustedhosts.enabled.description = Mark this SSL configuration be taken in consideration \
+ when creating a new HTTP CLient instance.
+
+trustedhosts.trustAll.name = Trust all SSL self-signed certificates
+trustedhosts.trustAll.description = Allows the new HTTP Client instance to \
+ blindly trust all SSL self-signed certificates.\
+ Pay attention on no enabling this feature in production environment as it is totally insecure!
+
+trustedhosts.hosts.name = Trust SSL self-signed certificates only for specified hosts
+trustedhosts.hosts.description = Allows the new HTTP Client instance to \
+ trust all SSL self-signed certificates coming only from the specified hosts. \
+ The default value is [ localhost, 127.0.0.1 ].

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/main/resources/OSGI-INF/metatype/metatype.xml Tue Jul 26 12:42:27 2016
@@ -69,8 +69,36 @@
 
   </OCD>
 
+  <OCD id="org.apache.hc.client5.http.trustedhosts"
+     name="%trustedhosts.name"
+     description="%trustedhosts.description">
+
+    <AD id="trustedhosts.enabled"
+      type="Boolean"
+      default="true"
+      name="%trustedhosts.enabled.name"
+      description="%trustedhosts.enabled.description" />
+
+    <AD id="trustedhosts.trustAll"
+      type="Boolean"
+      default="false"
+      name="%trustedhosts.trustAll.name"
+      description="%trustedhosts.trustAll.description" />
+
+    <AD id="trustedhosts.hosts"
+      type="String"
+      default="localhost,127.0.0.1"
+      cardinality="2147483647"
+      name="%trustedhosts.hosts.name"
+      description="%trustedhosts.hosts.description" />
+
+  </OCD>
+
   <Designate pid="org.apache.hc.client5.http.proxyconfigurator">
     <Object ocdref="org.apache.hc.client5.http.proxyconfigurator" />
   </Designate>
+  <Designate pid="org.apache.hc.client5.http.trustedhosts">
+    <Object ocdref="org.apache.hc.client5.http.trustedhosts" />
+  </Designate>
 
 </metatype:MetaData>

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,87 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.hc.client5.http.osgi.impl.HostMatcher.DomainNameMatcher;
+import org.apache.hc.client5.http.osgi.impl.HostMatcher.HostMatcherFactory;
+import org.apache.hc.client5.http.osgi.impl.HostMatcher.HostNameMatcher;
+import org.apache.hc.client5.http.osgi.impl.HostMatcher.IPAddressMatcher;
+import org.apache.hc.client5.http.osgi.impl.HostMatcher.NetworkAddress;
+import org.junit.Test;
+
+public final class HostMatcherTest {
+
+    @Test
+    public void testNetworkAddress() {
+        final NetworkAddress nullNetworkAddress = NetworkAddress.parse("www.apache.org");
+        assertNull(nullNetworkAddress);
+
+        final NetworkAddress na = NetworkAddress.parse("127.0.0.1");
+        assertEquals(2130706433, na.address);
+        assertEquals(-2147483648, na.mask);
+    }
+
+    @Test
+    public void testIPAddressMatcher() {
+        final NetworkAddress na = NetworkAddress.parse("127.0.0.1");
+        final IPAddressMatcher ipam = new IPAddressMatcher(na);
+        assertFalse(ipam.matches("127.0.0.255"));
+    }
+
+    @Test
+    public void testDomainNameMatcher() {
+        final DomainNameMatcher dnm = new DomainNameMatcher(".apache.org");
+        assertTrue(dnm.matches("www.apache.org"));
+        assertTrue(dnm.matches("hc.apache.org"));
+        assertTrue(dnm.matches("commons.apache.org"));
+        assertTrue(dnm.matches("cocoon.apache.org"));
+        assertFalse(dnm.matches("www.gnu.org"));
+    }
+
+    @Test
+    public void testHostNameMatcher() {
+        final HostNameMatcher hnm = new HostNameMatcher("www.apache.org");
+        assertTrue(hnm.matches("www.apache.org"));
+        assertTrue(hnm.matches("WwW.APACHE.org"));
+        assertTrue(hnm.matches("wWw.apache.ORG"));
+        assertTrue(hnm.matches("WWW.APACHE.ORG"));
+        assertFalse(hnm.matches("www.gnu.org"));
+    }
+
+    @Test
+    public void testHostMatcherFactory() {
+        assertTrue(HostMatcherFactory.createMatcher("127.0.0.1") instanceof IPAddressMatcher);
+        assertTrue(HostMatcherFactory.createMatcher(".apache.org") instanceof DomainNameMatcher);
+        assertTrue(HostMatcherFactory.createMatcher("www.apache.org") instanceof HostNameMatcher);
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/HostMatcherTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiHttpRoutePlanner.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiHttpRoutePlanner.java?rev=1754122&r1=1754121&r2=1754122&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiHttpRoutePlanner.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiHttpRoutePlanner.java Tue Jul 26 12:42:27 2016
@@ -114,13 +114,13 @@ public class TestOSGiHttpRoutePlanner {
 
     @Test
     public void testDeterminProxy() throws Exception {
-        final ServiceReference sRef1 = mock(ServiceReference.class);
-        final ServiceRegistration sReg1 = mock(ServiceRegistration.class);
+        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> registrations = new TreeMap<>(); // TreeMap for order
+        final Map<String, ServiceRegistration<ProxyConfiguration>> registrations = new TreeMap<>(); // TreeMap for order
         registrations.put("foo1", sReg1);
 
         OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations);
@@ -145,8 +145,8 @@ public class TestOSGiHttpRoutePlanner {
 
 
         // test with more than one registration of proxyConfiguration
-        final ServiceReference sRef2 = mock(ServiceReference.class);
-        final ServiceRegistration sReg2 = mock(ServiceRegistration.class);
+        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);
@@ -171,12 +171,12 @@ public class TestOSGiHttpRoutePlanner {
 
     @Test
     public void testMasking() throws Exception {
-        final ServiceReference sRef2 = mock(ServiceReference.class);
-        final ServiceRegistration sReg2 = mock(ServiceRegistration.class);
+        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> registrations = new TreeMap<>();
+        final Map<String, ServiceRegistration<ProxyConfiguration>> registrations = new TreeMap<>();
         registrations.put("foo2", sReg2);
 
         final OSGiHttpRoutePlanner planner = new OSGiHttpRoutePlanner(bc, registrations);

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,73 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.osgi.impl;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.hc.client5.http.osgi.services.TrustedHostsConfiguration;
+import org.junit.Test;
+import org.osgi.service.cm.ConfigurationException;
+
+public final class TestOSGiTrustedHostsConfiguration {
+
+    @Test
+    public void testSetValues() throws ConfigurationException {
+        final TrustedHostsConfiguration configuration = getTrustedHostsConfiguration();
+
+        assertEquals(true, configuration.isEnabled());
+        assertEquals(false, configuration.trustAll());
+        assertArrayEquals(new String[]{ "localhost" }, configuration.getTrustedHosts());
+    }
+
+    @Test
+    public void testToString() throws ConfigurationException {
+        final TrustedHostsConfiguration configuration = getTrustedHostsConfiguration();
+
+        final String string = configuration.toString();
+        assertThat(string, containsString("enabled=true"));
+        assertThat(string, containsString("trustAll=false"));
+        assertThat(string, containsString("trustedHosts=[localhost]"));
+    }
+
+    private TrustedHostsConfiguration getTrustedHostsConfiguration() throws ConfigurationException {
+        final Dictionary<String, Object> config = new Hashtable<>();
+        config.put("trustedhosts.enabled", true);
+        config.put("trustedhosts.trustAll", false);
+        config.put("trustedhosts.hosts", new String[]{ "localhost" });
+
+        final OSGiTrustedHostsConfiguration configuration = new OSGiTrustedHostsConfiguration();
+        configuration.updated(config);
+        return configuration;
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestOSGiTrustedHostsConfiguration.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java?rev=1754122&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java Tue Jul 26 12:42:27 2016
@@ -0,0 +1,144 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+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;
+import java.net.Socket;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+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.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+public class TestRelaxedLayeredConnectionSocketFactory {
+
+    @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 Socket socket = socketFactory.createSocket(context);
+        final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
+        assertSame(socket, 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 Socket socket = socketFactory.createSocket(context);
+        final Socket localSecureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
+        assertSame(socket, localSecureSocket);
+
+        final Socket apacheSecureSocket = socketFactory.createLayeredSocket(socket, "www.apache.org", 9999, context);
+        assertNotSame(socket, 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 Socket socket = socketFactory.createSocket(context);
+        final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
+        assertNotSame(socket, 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);
+        final OSGiTrustedHostsConfiguration configuration = new OSGiTrustedHostsConfiguration();
+        try {
+            configuration.updated(config);
+        } catch (ConfigurationException e) {
+            // it doesn't happen in tests
+        }
+        when(bundleContext.getService(reference)).thenReturn(configuration);
+
+        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;
+            }
+
+            @Override
+            public Socket connectSocket(final int connectTimeout,
+                                        final Socket sock,
+                                        final HttpHost host,
+                                        final InetSocketAddress remoteAddress,
+                                        final InetSocketAddress localAddress,
+                                        final HttpContext context ) throws IOException {
+                // not needed in this version
+                return socket;
+            }
+
+            @Override
+            public Socket createLayeredSocket(final Socket socket,
+                                              final String target,
+                                              final int port,
+                                              final HttpContext context) throws IOException {
+                return secureSocket;
+            }
+
+        };
+
+        return new RelaxedLayeredConnectionSocketFactory(bundleContext, registration, defaultSocketFactory);
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/httpclient5-osgi/src/test/java/org/apache/hc/client5/http/osgi/impl/TestRelaxedLayeredConnectionSocketFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain