You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dh...@apache.org on 2015/03/24 22:26:39 UTC

camel git commit: CAMEL-8543: Added support for configuring Salesforce HTTP client, HTTP proxy, added HTTP proxy integration tests

Repository: camel
Updated Branches:
  refs/heads/master 22f59a3ea -> 9f0e167b8


CAMEL-8543: Added support for configuring Salesforce HTTP client, HTTP proxy, added HTTP proxy integration tests


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/9f0e167b
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/9f0e167b
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/9f0e167b

Branch: refs/heads/master
Commit: 9f0e167b8306e4d15e43a0ec66916085f88e08dd
Parents: 22f59a3
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Tue Mar 24 14:26:09 2015 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Tue Mar 24 14:26:34 2015 -0700

----------------------------------------------------------------------
 .../camel-salesforce-component/pom.xml          |   6 +
 .../salesforce/SalesforceComponent.java         |  99 ++++++-
 .../salesforce/SalesforceEndpoint.java          |  36 +++
 .../salesforce/SalesforceEndpointConfig.java    |   2 +-
 .../salesforce/AbstractSalesforceTestBase.java  |   4 +-
 .../salesforce/HttpProxyIntegrationTest.java    | 154 ++++++++++
 .../camel-salesforce-maven-plugin/pom.xml       |   6 +
 .../src/it/simple-it/pom.xml                    |  14 +
 .../apache/camel/maven/CamelSalesforceMojo.java | 297 +++++++++++++------
 .../CamelSalesforceMojoIntegrationTest.java     |  23 +-
 .../maven/HttpProxyMojoIntegrationTest.java     | 110 +++++++
 11 files changed, 631 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml b/components/camel-salesforce/camel-salesforce-component/pom.xml
index 7ff091f..1be59f0 100644
--- a/components/camel-salesforce/camel-salesforce-component/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -114,6 +114,12 @@
       <artifactId>camel-test</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty-version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
index c12edc2..8d43b70 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
@@ -38,12 +38,15 @@ import org.apache.camel.component.salesforce.internal.SalesforceSession;
 import org.apache.camel.component.salesforce.internal.streaming.SubscriptionHelper;
 import org.apache.camel.impl.UriEndpointComponent;
 import org.apache.camel.spi.EndpointCompleter;
+import org.apache.camel.util.IntrospectionSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ReflectionHelper;
 import org.apache.camel.util.ServiceHelper;
 import org.apache.camel.util.jsse.SSLContextParameters;
+import org.eclipse.jetty.client.Address;
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.RedirectListener;
+import org.eclipse.jetty.client.security.ProxyAuthorization;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,16 +58,29 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
 
     private static final Logger LOG = LoggerFactory.getLogger(SalesforceComponent.class);
 
-    private static final int MAX_CONNECTIONS_PER_ADDRESS = 20;
     private static final int CONNECTION_TIMEOUT = 60000;
-    private static final int RESPONSE_TIMEOUT = 60000;
+    private static final long RESPONSE_TIMEOUT = 60000;
     private static final Pattern SOBJECT_NAME_PATTERN = Pattern.compile("^.*[\\?&]sObjectName=([^&,]+).*$");
     private static final String APEX_CALL_PREFIX = OperationName.APEX_CALL.value() + "/";
 
     private SalesforceLoginConfig loginConfig;
     private SalesforceEndpointConfig config;
 
+    // HTTP client parameters, map of property-name to value
+    private Map<String, Object> httpClientProperties;
+
+    // SSL parameters
     private SSLContextParameters sslContextParameters;
+
+    // Proxy host and port
+    private String httpProxyHost;
+    private Integer httpProxyPort;
+
+    // Proxy basic authentication
+    private String httpProxyUsername;
+    private String httpProxyPassword;
+
+    // DTO packages to scan
     private String[] packages;
 
     // component state
@@ -127,10 +143,12 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
 
         // if operation is APEX call, map remaining parameters to query params
         if (operationName == OperationName.APEX_CALL && !parameters.isEmpty()) {
-            Map<String, Object> queryParams = new HashMap<String, Object>(parameters);
+            Map<String, Object> queryParams = new HashMap<String, Object>(copy.getApexQueryParams());
+
+            // override component params with endpoint params
+            queryParams.putAll(parameters);
             parameters.clear();
 
-            queryParams.putAll(copy.getApexQueryParams());
             copy.setApexQueryParams(queryParams);
         }
 
@@ -161,18 +179,34 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
             if (config != null && config.getHttpClient() != null) {
                 httpClient = config.getHttpClient();
             } else {
-                final SslContextFactory sslContextFactory = new SslContextFactory();
-                final SSLContextParameters contextParameters =
-                    sslContextParameters != null ? sslContextParameters : new SSLContextParameters();
-                sslContextFactory.setSslContext(contextParameters.createSSLContext());
-                httpClient = new HttpClient(sslContextFactory);
+                httpClient = new HttpClient();
+                // default settings
                 httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
-                httpClient.setMaxConnectionsPerAddress(MAX_CONNECTIONS_PER_ADDRESS);
                 httpClient.setConnectTimeout(CONNECTION_TIMEOUT);
                 httpClient.setTimeout(RESPONSE_TIMEOUT);
             }
         }
 
+        // set ssl context parameters
+        final SSLContextParameters contextParameters = sslContextParameters != null
+            ? sslContextParameters : new SSLContextParameters();
+        final SslContextFactory sslContextFactory = httpClient.getSslContextFactory();
+        sslContextFactory.setSslContext(contextParameters.createSSLContext());
+
+        // set HTTP client parameters
+        if (httpClientProperties != null && !httpClientProperties.isEmpty()) {
+            IntrospectionSupport.setProperties(getCamelContext().getTypeConverter(),
+                httpClient, new HashMap<String, Object>(httpClientProperties));
+        }
+
+        // set HTTP proxy settings
+        if (this.httpProxyHost != null && httpProxyPort != null) {
+            httpClient.setProxy(new Address(this.httpProxyHost, this.httpProxyPort));
+        }
+        if (this.httpProxyUsername != null && httpProxyPassword != null) {
+            httpClient.setProxyAuthentication(new ProxyAuthorization(this.httpProxyUsername, this.httpProxyPassword));
+        }
+
         // add redirect listener to handle Salesforce redirects
         // this is ok to do since the RedirectListener is in the same classloader as Jetty client
         String listenerClass = RedirectListener.class.getName();
@@ -235,7 +269,10 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
             if (httpClient != null) {
                 // shutdown http client connections
                 httpClient.stop();
-                httpClient.destroy();
+                // destroy http client if it was created by the component
+                if (config.getHttpClient() == null) {
+                    httpClient.destroy();
+                }
                 httpClient = null;
             }
         }
@@ -332,6 +369,14 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
         this.config = config;
     }
 
+    public Map<String, Object> getHttpClientProperties() {
+        return httpClientProperties;
+    }
+
+    public void setHttpClientProperties(Map<String, Object> httpClientProperties) {
+        this.httpClientProperties = httpClientProperties;
+    }
+
     public SSLContextParameters getSslContextParameters() {
         return sslContextParameters;
     }
@@ -340,6 +385,38 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin
         this.sslContextParameters = sslContextParameters;
     }
 
+    public String getHttpProxyHost() {
+        return httpProxyHost;
+    }
+
+    public void setHttpProxyHost(String httpProxyHost) {
+        this.httpProxyHost = httpProxyHost;
+    }
+
+    public Integer getHttpProxyPort() {
+        return httpProxyPort;
+    }
+
+    public void setHttpProxyPort(Integer httpProxyPort) {
+        this.httpProxyPort = httpProxyPort;
+    }
+
+    public String getHttpProxyUsername() {
+        return httpProxyUsername;
+    }
+
+    public void setHttpProxyUsername(String httpProxyUsername) {
+        this.httpProxyUsername = httpProxyUsername;
+    }
+
+    public String getHttpProxyPassword() {
+        return httpProxyPassword;
+    }
+
+    public void setHttpProxyPassword(String httpProxyPassword) {
+        this.httpProxyPassword = httpProxyPassword;
+    }
+
     public String[] getPackages() {
         return packages;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
index 27e28f2..85d11c7 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
@@ -25,6 +25,9 @@ import org.apache.camel.impl.SynchronousDelegateProducer;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriPath;
+import org.eclipse.jetty.client.HttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Represents a Salesforce endpoint.
@@ -32,6 +35,8 @@ import org.apache.camel.spi.UriPath;
 @UriEndpoint(scheme = "salesforce", syntax = "salesforce:operationName:topicName", consumerClass = SalesforceConsumer.class)
 public class SalesforceEndpoint extends DefaultEndpoint {
 
+    private static final Logger LOG = LoggerFactory.getLogger(SalesforceEndpoint.class);
+
     @UriPath
     private final OperationName operationName;
     @UriPath
@@ -98,4 +103,35 @@ public class SalesforceEndpoint extends DefaultEndpoint {
         return topicName;
     }
 
+    @Override
+    protected void doStart() throws Exception {
+        try {
+            super.doStart();
+        } finally {
+            // check if this endpoint has its own http client that needs to be started
+            final HttpClient httpClient = getConfiguration().getHttpClient();
+            if (httpClient != null && getComponent().getConfig().getHttpClient() != httpClient) {
+                final String endpointUri = getEndpointUri();
+                LOG.debug("Starting http client for {} ...", endpointUri);
+                httpClient.start();
+                LOG.debug("Started http client for {}", endpointUri);
+            }
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        try {
+            super.doStop();
+        } finally {
+            // check if this endpoint has its own http client that needs to be stopped
+            final HttpClient httpClient = getConfiguration().getHttpClient();
+            if (httpClient != null && getComponent().getConfig().getHttpClient() != httpClient) {
+                final String endpointUri = getEndpointUri();
+                LOG.debug("Stopping http client for {} ...", endpointUri);
+                httpClient.stop();
+                LOG.debug("Stopped http client for {}", endpointUri);
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
index 9af05b9..39b860a 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
@@ -129,7 +129,7 @@ public class SalesforceEndpointConfig implements Cloneable {
     public SalesforceEndpointConfig copy() {
         try {
             final SalesforceEndpointConfig copy = (SalesforceEndpointConfig) super.clone();
-            // nothing to deep copy
+            // nothing to deep copy, getApexQueryParams() is readonly, so no need to deep copy
             return copy;
         } catch (CloneNotSupportedException ex) {
             throw new RuntimeCamelException(ex);

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
index 52d1d65..f05bbf9 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
@@ -16,8 +16,6 @@
  */
 package org.apache.camel.component.salesforce;
 
-import java.io.IOException;
-
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.salesforce.dto.generated.Merchandise__c;
 import org.apache.camel.test.junit4.CamelTestSupport;
@@ -40,7 +38,7 @@ public abstract class AbstractSalesforceTestBase extends CamelTestSupport {
 
     protected abstract RouteBuilder doCreateRouteBuilder() throws Exception;
 
-    protected void createComponent() throws IllegalAccessException, IOException {
+    protected void createComponent() throws Exception {
         // create the component
         SalesforceComponent component = new SalesforceComponent();
         final SalesforceEndpointConfig config = new SalesforceEndpointConfig();

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/HttpProxyIntegrationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/HttpProxyIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/HttpProxyIntegrationTest.java
new file mode 100644
index 0000000..7b237cd
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/HttpProxyIntegrationTest.java
@@ -0,0 +1,154 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.salesforce;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.salesforce.api.dto.Version;
+import org.apache.camel.component.salesforce.api.dto.Versions;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ConnectHandler;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.StringUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test HTTP proxy configuration for Salesforce component.
+ */
+public class HttpProxyIntegrationTest extends AbstractSalesforceTestBase {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpProxyIntegrationTest.class);
+    private static final String HTTP_PROXY_HOST = "localhost";
+    private static final String HTTP_PROXY_USER_NAME = "camel-user";
+    private static final String HTTP_PROXY_PASSWORD = "camel-user-password";
+
+    private static Server server;
+    private static int httpProxyPort;
+
+    @Test
+    public void testGetVersions() throws Exception {
+        doTestGetVersions("");
+        doTestGetVersions("Xml");
+    }
+
+    @SuppressWarnings("unchecked")
+    private void doTestGetVersions(String suffix) throws Exception {
+        // test getVersions doesn't need a body
+        // assert expected result
+        Object o = template().requestBody("direct:getVersions" + suffix, (Object) null);
+        List<Version> versions = null;
+        if (o instanceof Versions) {
+            versions = ((Versions) o).getVersions();
+        } else {
+            versions = (List<Version>) o;
+        }
+        assertNotNull(versions);
+        LOG.debug("Versions: {}", versions);
+    }
+
+    @BeforeClass
+    public static void setupServer() throws Exception {
+        // start a local HTTP proxy using Jetty server
+        server = new Server();
+
+        Connector connector = new SelectChannelConnector();
+        connector.setHost(HTTP_PROXY_HOST);
+        server.setConnectors(new Connector[]{connector});
+
+        final String authenticationString = "Basic "
+            + B64Code.encode(HTTP_PROXY_USER_NAME + ":" + HTTP_PROXY_PASSWORD, StringUtil.__ISO_8859_1);
+
+        ConnectHandler handler = new ConnectHandler() {
+            @Override
+            protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException {
+                // validate proxy-authentication header
+                final String header = request.getHeader(HttpHeaders.PROXY_AUTHORIZATION);
+                if (!authenticationString.equals(header)) {
+                    throw new ServletException("Missing header " + HttpHeaders.PROXY_AUTHORIZATION);
+                }
+                LOG.info("CONNECT exchange contains required header " + HttpHeaders.PROXY_AUTHORIZATION);
+                return super.handleAuthentication(request, response, address);
+            }
+        };
+        server.setHandler(handler);
+
+        LOG.info("Starting proxy server...");
+        server.start();
+
+        httpProxyPort = connector.getLocalPort();
+        LOG.info("Started proxy server on port {}", httpProxyPort);
+    }
+
+    @Override
+    protected void createComponent() throws Exception {
+
+        super.createComponent();
+        final SalesforceComponent salesforce = (SalesforceComponent) context().getComponent("salesforce");
+
+        // set HTTP proxy settings
+        salesforce.setHttpProxyHost(HTTP_PROXY_HOST);
+        salesforce.setHttpProxyPort(httpProxyPort);
+        salesforce.setHttpProxyUsername(HTTP_PROXY_USER_NAME);
+        salesforce.setHttpProxyPassword(HTTP_PROXY_PASSWORD);
+
+        // set HTTP client properties
+        final HashMap<String, Object> properties = new HashMap<String, Object>();
+        properties.put("timeout", "60000");
+        properties.put("removeIdleDestinations", "true");
+        salesforce.setHttpClientProperties(properties);
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+        AbstractSalesforceTestBase.tearDownAfterClass();
+        // stop the proxy server after component
+        LOG.info("Stopping proxy server...");
+        server.stop();
+        LOG.info("Stopped proxy server");
+    }
+
+    @Override
+    protected RouteBuilder doCreateRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+
+                // testGetVersion
+                from("direct:getVersions")
+                    .to("salesforce:getVersions");
+
+                // allow overriding format per endpoint
+                from("direct:getVersionsXml")
+                    .to("salesforce:getVersions?format=XML");
+
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/pom.xml b/components/camel-salesforce/camel-salesforce-maven-plugin/pom.xml
index 1f22d6a..cad281b 100644
--- a/components/camel-salesforce/camel-salesforce-maven-plugin/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-maven-plugin/pom.xml
@@ -75,6 +75,12 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
       <version>${slf4j-api-version}</version>

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-maven-plugin/src/it/simple-it/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/src/it/simple-it/pom.xml b/components/camel-salesforce/camel-salesforce-maven-plugin/src/it/simple-it/pom.xml
index 0f24037..b025aad 100644
--- a/components/camel-salesforce/camel-salesforce-maven-plugin/src/it/simple-it/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-maven-plugin/src/it/simple-it/pom.xml
@@ -61,6 +61,20 @@
               <goal>generate</goal>
             </goals>
             <configuration>
+              <httpClientProperties>
+                <timeout>60000</timeout>
+                <maxConnectionsPerAddress>10</maxConnectionsPerAddress>
+                <removeIdleDestinations>true</removeIdleDestinations>
+              </httpClientProperties>
+              <sslContextParameters>
+                <clientParameters>
+                    <cipherSuitesFilter>
+                      <exclude>
+                        <exclude>SSL.*</exclude>
+                      </exclude>
+                    </cipherSuitesFilter>
+                </clientParameters>
+              </sslContextParameters>
               <includePattern>(.*__c)</includePattern>
               <!-- Salesforce login info -->
               <clientId>${clientId}</clientId>

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java b/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java
index d517f24..372b6e4 100644
--- a/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java
+++ b/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java
@@ -21,6 +21,7 @@ import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.lang.reflect.Field;
+import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -49,6 +50,9 @@ import org.apache.camel.component.salesforce.internal.SalesforceSession;
 import org.apache.camel.component.salesforce.internal.client.DefaultRestClient;
 import org.apache.camel.component.salesforce.internal.client.RestClient;
 import org.apache.camel.component.salesforce.internal.client.SyncResponseCallback;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.jsse.SSLContextParameters;
 import org.apache.log4j.Logger;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -62,105 +66,148 @@ import org.apache.velocity.runtime.RuntimeConstants;
 import org.apache.velocity.runtime.log.Log4JLogChute;
 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
 import org.codehaus.jackson.map.ObjectMapper;
+import org.eclipse.jetty.client.Address;
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.RedirectListener;
+import org.eclipse.jetty.client.security.ProxyAuthorization;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
 
 /**
- * Goal which generates POJOs for Salesforce SObjects
+ * Goal to generate DTOs for Salesforce SObjects
  */
 @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
 public class CamelSalesforceMojo extends AbstractMojo {
+
+    // default connect and call timeout
+    protected static final int DEFAULT_TIMEOUT = 60000;
+
     private static final String JAVA_EXT = ".java";
     private static final String PACKAGE_NAME_PATTERN = "^[a-z]+(\\.[a-z][a-z0-9]*)*$";
+
     private static final String SOBJECT_POJO_VM = "/sobject-pojo.vm";
     private static final String SOBJECT_QUERY_RECORDS_VM = "/sobject-query-records.vm";
     private static final String SOBJECT_PICKLIST_VM = "/sobject-picklist.vm";
 
     // used for velocity logging, to avoid creating velocity.log
     private static final Logger LOG = Logger.getLogger(CamelSalesforceMojo.class.getName());
-    private static final int TIMEOUT = 60000;
 
     /**
-     * Salesforce client id
+     * HTTP client properties.
+     */
+    @Parameter
+    protected Map<String, Object> httpClientProperties;
+
+    /**
+     * SSL Context parameters.
+     */
+    @Parameter(property = "camelSalesforce.sslContextParameters")
+    protected SSLContextParameters sslContextParameters;
+
+    /**
+     * HTTP Proxy host.
+     */
+    @Parameter(property = "camelSalesforce.httpProxyHost")
+    protected String httpProxyHost;
+
+    /**
+     * HTTP Proxy port.
+     */
+    @Parameter(property = "camelSalesforce.httpProxyPort")
+    protected Integer httpProxyPort;
+
+    /**
+     * Proxy authentication username.
+     */
+    @Parameter(property = "camelSalesforce.httpProxyUsername")
+    protected String httpProxyUsername;
+
+    /**
+     * Proxy authentication password.
+     */
+    @Parameter(property = "camelSalesforce.httpProxyPassword")
+    protected String httpProxyPassword;
+
+    /**
+     * Salesforce client id.
      */
     @Parameter(property = "camelSalesforce.clientId", required = true)
     protected String clientId;
 
     /**
-     * Salesforce client secret
+     * Salesforce client secret.
      */
     @Parameter(property = "camelSalesforce.clientSecret", required = true)
     protected String clientSecret;
 
     /**
-     * Salesforce user name
+     * Salesforce username.
      */
     @Parameter(property = "camelSalesforce.userName", required = true)
     protected String userName;
 
     /**
-     * Salesforce password
+     * Salesforce password.
      */
     @Parameter(property = "camelSalesforce.password", required = true)
     protected String password;
 
     /**
-     * Salesforce version
+     * Salesforce API version.
      */
     @Parameter(property = "camelSalesforce.version", defaultValue = SalesforceEndpointConfig.DEFAULT_VERSION)
     protected String version;
 
     /**
-     * Location of the file.
+     * Location of generated DTO files, defaults to target/generated-sources/camel-salesforce.
      */
     @Parameter(property = "camelSalesforce.outputDirectory",
         defaultValue = "${project.build.directory}/generated-sources/camel-salesforce")
     protected File outputDirectory;
 
     /**
-     * Salesforce URL.
+     * Salesforce login URL, defaults to https://login.salesforce.com.
      */
     @Parameter(property = "camelSalesforce.loginUrl", defaultValue = SalesforceLoginConfig.DEFAULT_LOGIN_URL)
     protected String loginUrl;
 
     /**
-     * Names of Salesforce SObject for which POJOs must be generated
+     * Names of Salesforce SObject for which DTOs must be generated.
      */
     @Parameter
     protected String[] includes;
 
     /**
-     * Do NOT generate POJOs for these Salesforce SObjects
+     * Do NOT generate DTOs for these Salesforce SObjects.
      */
     @Parameter
     protected String[] excludes;
 
     /**
-     * Include Salesforce SObjects that match pattern
+     * Include Salesforce SObjects that match pattern.
      */
     @Parameter(property = "camelSalesforce.includePattern")
     protected String includePattern;
 
     /**
-     * Exclude Salesforce SObjects that match pattern
+     * Exclude Salesforce SObjects that match pattern.
      */
     @Parameter(property = "camelSalesforce.excludePattern")
     protected String excludePattern;
 
     /**
-     * Java package name for generated POJOs
+     * Java package name for generated DTOs.
      */
     @Parameter(property = "camelSalesforce.packageName", defaultValue = "org.apache.camel.salesforce.dto")
     protected String packageName;
 
     private VelocityEngine engine;
+    private long responseTimeout;
 
     /**
-     * Execute the mojo to generate SObject POJOs
+     * Execute the mojo to generate SObject DTOs
      *
      * @throws MojoExecutionException
      */
-    // CHECKSTYLE:OFF
     public void execute() throws MojoExecutionException {
         // initialize velocity to load resources from class loader and use Log4J
         Properties velocityProperties = new Properties();
@@ -177,15 +224,7 @@ public class CamelSalesforceMojo extends AbstractMojo {
         }
 
         // connect to Salesforce
-        final HttpClient httpClient = new HttpClient();
-        httpClient.registerListener(RedirectListener.class.getName());
-        httpClient.setConnectTimeout(TIMEOUT);
-        httpClient.setTimeout(TIMEOUT);
-        try {
-            httpClient.start();
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error creating HTTP client: " + e.getMessage(), e);
-        }
+        final HttpClient httpClient = createHttpClient();
 
         final SalesforceSession session = new SalesforceSession(httpClient,
                 new SalesforceLoginConfig(loginUrl, clientId, clientSecret, userName, password, false));
@@ -221,7 +260,7 @@ public class CamelSalesforceMojo extends AbstractMojo {
             try {
                 getLog().info("Getting Salesforce Objects...");
                 restClient.getGlobalObjects(callback);
-                if (!callback.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
+                if (!callback.await(responseTimeout, TimeUnit.MILLISECONDS)) {
                     throw new MojoExecutionException("Timeout waiting for getGlobalObjects!");
                 }
                 final SalesforceException ex = callback.getException();
@@ -243,67 +282,11 @@ public class CamelSalesforceMojo extends AbstractMojo {
             // check if we are generating POJOs for all objects or not
             if ((includes != null && includes.length > 0)
                     || (excludes != null && excludes.length > 0)
-                    || (includePattern != null && !includePattern.trim().isEmpty())
-                    || (excludePattern != null && !excludePattern.trim().isEmpty())) {
-
-                getLog().info("Looking for matching Object names...");
-                // create a list of accepted names
-                final Set<String> includedNames = new HashSet<String>();
-                if (includes != null && includes.length > 0) {
-                    for (String name : includes) {
-                        name = name.trim();
-                        if (name.isEmpty()) {
-                            throw new MojoExecutionException("Invalid empty name in includes");
-                        }
-                        includedNames.add(name);
-                    }
-                }
-
-                final Set<String> excludedNames = new HashSet<String>();
-                if (excludes != null && excludes.length > 0) {
-                    for (String name : excludes) {
-                        name = name.trim();
-                        if (name.isEmpty()) {
-                            throw new MojoExecutionException("Invalid empty name in excludes");
-                        }
-                        excludedNames.add(name);
-                    }
-                }
+                    || ObjectHelper.isNotEmpty(includePattern)
+                    || ObjectHelper.isNotEmpty(excludePattern)) {
 
-                // check whether a pattern is in effect
-                Pattern incPattern;
-                if (includePattern != null && !includePattern.trim().isEmpty()) {
-                    incPattern = Pattern.compile(includePattern.trim());
-                } else if (includedNames.isEmpty()) {
-                    // include everything by default if no include names are set
-                    incPattern = Pattern.compile(".*");
-                } else {
-                    // include nothing by default if include names are set
-                    incPattern = Pattern.compile("^$");
-                }
-
-                // check whether a pattern is in effect
-                Pattern excPattern;
-                if (excludePattern != null && !excludePattern.trim().isEmpty()) {
-                    excPattern = Pattern.compile(excludePattern.trim());
-                } else {
-                    // exclude nothing by default
-                    excPattern = Pattern.compile("^$");
-                }
+                filterObjectNames(objectNames);
 
-                final Set<String> acceptedNames = new HashSet<String>();
-                for (String name : objectNames) {
-                    // name is included, or matches include pattern
-                    // and is not excluded and does not match exclude pattern
-                    if ((includedNames.contains(name) || incPattern.matcher(name).matches())
-                            && !excludedNames.contains(name) && !excPattern.matcher(name).matches()) {
-                        acceptedNames.add(name);
-                    }
-                }
-                objectNames.clear();
-                objectNames.addAll(acceptedNames);
-
-                getLog().info(String.format("Found %s matching Objects", objectNames.size()));
             } else {
                 getLog().warn(String.format("Generating Java classes for all %s Objects, this may take a while...", objectNames.size()));
             }
@@ -314,16 +297,16 @@ public class CamelSalesforceMojo extends AbstractMojo {
             getLog().info("Retrieving Object descriptions...");
             for (String name : objectNames) {
                 try {
-                        callback.reset();
-                        restClient.getDescription(name, callback);
-                        if (!callback.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
-                            throw new MojoExecutionException("Timeout waiting for getDescription for sObject " + name);
-                        }
-                        final SalesforceException ex = callback.getException();
-                        if (ex != null) {
-                            throw ex;
-                        }
-                        descriptions.add(mapper.readValue(callback.getResponse(), SObjectDescription.class));
+                    callback.reset();
+                    restClient.getDescription(name, callback);
+                    if (!callback.await(responseTimeout, TimeUnit.MILLISECONDS)) {
+                        throw new MojoExecutionException("Timeout waiting for getDescription for sObject " + name);
+                    }
+                    final SalesforceException ex = callback.getException();
+                    if (ex != null) {
+                        throw ex;
+                    }
+                    descriptions.add(mapper.readValue(callback.getResponse(), SObjectDescription.class));
                 } catch (Exception e) {
                     String msg = "Error getting SObject description for '" + name + "': " + e.getMessage();
                     throw new MojoExecutionException(msg, e);
@@ -372,7 +355,129 @@ public class CamelSalesforceMojo extends AbstractMojo {
             }
         }
     }
-    // CHECKSTYLE:ON
+
+    protected void filterObjectNames(Set<String> objectNames) throws MojoExecutionException {
+        getLog().info("Looking for matching Object names...");
+        // create a list of accepted names
+        final Set<String> includedNames = new HashSet<String>();
+        if (includes != null && includes.length > 0) {
+            for (String name : includes) {
+                name = name.trim();
+                if (name.isEmpty()) {
+                    throw new MojoExecutionException("Invalid empty name in includes");
+                }
+                includedNames.add(name);
+            }
+        }
+
+        final Set<String> excludedNames = new HashSet<String>();
+        if (excludes != null && excludes.length > 0) {
+            for (String name : excludes) {
+                name = name.trim();
+                if (name.isEmpty()) {
+                    throw new MojoExecutionException("Invalid empty name in excludes");
+                }
+                excludedNames.add(name);
+            }
+        }
+
+        // check whether a pattern is in effect
+        Pattern incPattern;
+        if (includePattern != null && !includePattern.trim().isEmpty()) {
+            incPattern = Pattern.compile(includePattern.trim());
+        } else if (includedNames.isEmpty()) {
+            // include everything by default if no include names are set
+            incPattern = Pattern.compile(".*");
+        } else {
+            // include nothing by default if include names are set
+            incPattern = Pattern.compile("^$");
+        }
+
+        // check whether a pattern is in effect
+        Pattern excPattern;
+        if (excludePattern != null && !excludePattern.trim().isEmpty()) {
+            excPattern = Pattern.compile(excludePattern.trim());
+        } else {
+            // exclude nothing by default
+            excPattern = Pattern.compile("^$");
+        }
+
+        final Set<String> acceptedNames = new HashSet<String>();
+        for (String name : objectNames) {
+            // name is included, or matches include pattern
+            // and is not excluded and does not match exclude pattern
+            if ((includedNames.contains(name) || incPattern.matcher(name).matches())
+                    && !excludedNames.contains(name) && !excPattern.matcher(name).matches()) {
+                acceptedNames.add(name);
+            }
+        }
+        objectNames.clear();
+        objectNames.addAll(acceptedNames);
+
+        getLog().info(String.format("Found %s matching Objects", objectNames.size()));
+    }
+
+    protected HttpClient createHttpClient() throws MojoExecutionException {
+
+        final HttpClient httpClient = new HttpClient();
+
+        // default settings
+        httpClient.registerListener(RedirectListener.class.getName());
+        httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+        httpClient.setConnectTimeout(DEFAULT_TIMEOUT);
+        httpClient.setTimeout(DEFAULT_TIMEOUT);
+
+        // set ssl context parameters
+        try {
+            final SSLContextParameters contextParameters = sslContextParameters != null
+                ? sslContextParameters : new SSLContextParameters();
+            final SslContextFactory sslContextFactory = httpClient.getSslContextFactory();
+            sslContextFactory.setSslContext(contextParameters.createSSLContext());
+        } catch (GeneralSecurityException e) {
+            throw new MojoExecutionException("Error creating default SSL context: " + e.getMessage(), e);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Error creating default SSL context: " + e.getMessage(), e);
+        }
+
+        // set HTTP client parameters
+        if (httpClientProperties != null && !httpClientProperties.isEmpty()) {
+            try {
+                IntrospectionSupport.setProperties(httpClient, new HashMap<String, Object>(httpClientProperties));
+            } catch (Exception e) {
+                throw new MojoExecutionException("Error setting HTTP client properties: " + e.getMessage(), e);
+            }
+        }
+
+        // wait for 1 second longer than the HTTP client response timeout
+        responseTimeout = httpClient.getTimeout() + 1000L;
+
+        // set http proxy settings
+        if (this.httpProxyHost != null && httpProxyPort != null) {
+            httpClient.setProxy(new Address(this.httpProxyHost, this.httpProxyPort));
+        }
+        if (this.httpProxyUsername != null && httpProxyPassword != null) {
+            try {
+                httpClient.setProxyAuthentication(new ProxyAuthorization(this.httpProxyUsername, this.httpProxyPassword));
+            } catch (IOException e) {
+                throw new MojoExecutionException("Error configuring proxy authorization: " + e.getMessage(), e);
+            }
+        }
+
+        // add redirect listener to handle Salesforce redirects
+        // this is ok to do since the RedirectListener is in the same classloader as Jetty client
+        String listenerClass = RedirectListener.class.getName();
+        if (httpClient.getRegisteredListeners() == null
+            || !httpClient.getRegisteredListeners().contains(listenerClass)) {
+            httpClient.registerListener(listenerClass);
+        }
+
+        try {
+            httpClient.start();
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error creating HTTP client: " + e.getMessage(), e);
+        }
+        return httpClient;
+    }
 
     private void processDescription(File pkgDir, SObjectDescription description, GeneratorUtility utility, String generatedDate) throws MojoExecutionException {
         // generate a source file for SObject

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/CamelSalesforceMojoIntegrationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/CamelSalesforceMojoIntegrationTest.java b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/CamelSalesforceMojoIntegrationTest.java
index cf9bcb9..a40b9b9 100644
--- a/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/CamelSalesforceMojoIntegrationTest.java
+++ b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/CamelSalesforceMojoIntegrationTest.java
@@ -35,6 +35,19 @@ public class CamelSalesforceMojoIntegrationTest {
 
     @Test
     public void testExecute() throws Exception {
+        CamelSalesforceMojo mojo = createMojo();
+
+        // generate code
+        mojo.execute();
+
+        // validate generated code
+        // check that it was generated
+        Assert.assertTrue("Output directory was not created", mojo.outputDirectory.exists());
+
+        // TODO check that the generated code compiles
+    }
+
+    protected CamelSalesforceMojo createMojo() throws IOException {
         CamelSalesforceMojo mojo = new CamelSalesforceMojo();
 
         mojo.setLog(new SystemStreamLog());
@@ -59,15 +72,7 @@ public class CamelSalesforceMojoIntegrationTest {
             }
             mojo.outputDirectory.delete();
         }
-
-        // generate code
-        mojo.execute();
-
-        // validate generated code
-        // check that it was generated
-        Assert.assertTrue("Output directory was not created", mojo.outputDirectory.exists());
-
-        // TODO check that the generated code compiles
+        return mojo;
     }
 
     private void setLoginProperties(CamelSalesforceMojo mojo) throws IOException {

http://git-wip-us.apache.org/repos/asf/camel/blob/9f0e167b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/HttpProxyMojoIntegrationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/HttpProxyMojoIntegrationTest.java b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/HttpProxyMojoIntegrationTest.java
new file mode 100644
index 0000000..47d15fb
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-maven-plugin/src/test/java/org/apache/camel/maven/HttpProxyMojoIntegrationTest.java
@@ -0,0 +1,110 @@
+/**
+ * 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.
+ */
+package org.apache.camel.maven;
+
+import java.io.IOException;
+import java.util.HashMap;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ConnectHandler;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.StringUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HttpProxyMojoIntegrationTest extends CamelSalesforceMojoIntegrationTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpProxyMojoIntegrationTest.class);
+
+    private static final String HTTP_PROXY_HOST = "localhost";
+    private static final String HTTP_PROXY_USER_NAME = "camel-user";
+    private static final String HTTP_PROXY_PASSWORD = "camel-user-password";
+
+    private static Server server;
+    private static int httpProxyPort;
+
+    @BeforeClass
+    public static void setupServer() throws Exception {
+        // start a local HTTP proxy using Jetty server
+        server = new Server();
+
+        Connector connector = new SelectChannelConnector();
+        connector.setHost(HTTP_PROXY_HOST);
+        server.setConnectors(new Connector[]{connector});
+
+        final String authenticationString = "Basic "
+            + B64Code.encode(HTTP_PROXY_USER_NAME + ":" + HTTP_PROXY_PASSWORD, StringUtil.__ISO_8859_1);
+
+        ConnectHandler handler = new ConnectHandler() {
+            @Override
+            protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException {
+                // validate proxy-authentication header
+                final String header = request.getHeader(HttpHeaders.PROXY_AUTHORIZATION);
+                if (!authenticationString.equals(header)) {
+                    throw new ServletException("Missing header " + HttpHeaders.PROXY_AUTHORIZATION);
+                }
+                LOG.info("CONNECT exchange contains required header " + HttpHeaders.PROXY_AUTHORIZATION);
+                return super.handleAuthentication(request, response, address);
+            }
+        };
+        server.setHandler(handler);
+
+        LOG.info("Starting proxy server...");
+        server.start();
+
+        httpProxyPort = connector.getLocalPort();
+        LOG.info("Started proxy server on port {}", httpProxyPort);
+    }
+
+    @Override
+    protected CamelSalesforceMojo createMojo() throws IOException {
+        final CamelSalesforceMojo mojo = super.createMojo();
+
+        // SSL context parameters
+        mojo.sslContextParameters = new SSLContextParameters();
+
+        // HTTP proxy properties
+        mojo.httpProxyHost = HTTP_PROXY_HOST;
+        mojo.httpProxyPort = httpProxyPort;
+        mojo.httpProxyUsername = HTTP_PROXY_USER_NAME;
+        mojo.httpProxyPassword = HTTP_PROXY_PASSWORD;
+
+        // HTTP client properties
+        mojo.httpClientProperties = new HashMap<String, Object>();
+        mojo.httpClientProperties.put("timeout", "60000");
+        mojo.httpClientProperties.put("removeIdleDestinations", "true");
+
+        return mojo;
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+        // stop the proxy server after component
+        LOG.info("Stopping proxy server...");
+        server.stop();
+        LOG.info("Stopped proxy server");
+    }
+}