From 12c831e9ccdebf6bcbc9fb45d2a8b110c9fe852f Mon Sep 17 00:00:00 2001 From: Monish Vachhani Date: Wed, 21 Aug 2019 00:22:28 -0700 Subject: [PATCH] Add ability to set SSLSocketFactory on ConnectorConfig, use SSLContext when creating connections in SOAP and Bulk APIs. --- .../java/com/sforce/async/BulkConnection.java | 17 +++++---- .../java/com/sforce/ws/ConnectorConfig.java | 35 ++++++++++++------- .../sforce/ws/transport/JdkHttpTransport.java | 12 +++++-- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/sforce/async/BulkConnection.java b/src/main/java/com/sforce/async/BulkConnection.java index 7cc527fe..fe29c5f9 100644 --- a/src/main/java/com/sforce/async/BulkConnection.java +++ b/src/main/java/com/sforce/async/BulkConnection.java @@ -44,6 +44,7 @@ import java.util.zip.ZipOutputStream; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; import javax.xml.namespace.QName; import com.sforce.ws.ConnectionException; @@ -66,7 +67,7 @@ /** * BulkConnection - * + * * @author mcheenath * @since 160 */ @@ -341,9 +342,9 @@ public BatchInfo createBatchWithInputStreamAttachments(JobInfo jobInfo, InputStr } /* - * Creates a compliant Async Api batch from a stream containing an arbitrary CSV source (eg. Outlook contacts). + * Creates a compliant Async Api batch from a stream containing an arbitrary CSV source (eg. Outlook contacts). * The stream does not have to be UTF-8, and it's contents are transformed into a compliant - * batch using the previously created transformation specification (a mapping of columns to fields). + * batch using the previously created transformation specification (a mapping of columns to fields). * The stream is still limited according to the same limit rules as apply to normal batches. */ public BatchInfo createBatchFromForeignCsvStream(JobInfo jobInfo, InputStream input, String charSet) throws AsyncApiException { @@ -379,7 +380,7 @@ public BatchInfo createBatchFromForeignCsvStream(JobInfo jobInfo, InputStream in * Salesforce Field,Csv Header,Value,Hint * LastName,Surname,#N/A, * Birthdate,Birthday,,MM-dd-YYYY - * + * */ public void createTransformationSpecFromStream(JobInfo jobInfo, InputStream input) throws AsyncApiException { try { @@ -622,7 +623,7 @@ public URL buildBatchResultURL(String jobId, String batchId) throws AsyncApiExce AsyncExceptionCode.ClientInputError, e); } } - + public InputStream getBatchRequestInputStream(String jobId, String batchId) throws AsyncApiException { try { String endpoint = getRestEndpoint() + "job/" + jobId + "/batch/" + batchId + "/request"; @@ -669,7 +670,7 @@ public InputStream getQueryResultStream(String jobId, String batchId, String res throw new AsyncApiException("Failed to get result ", AsyncExceptionCode.ClientInputError, e); } } - + public URL buildQueryResultURL(String jobId, String batchId, String resultId) throws AsyncApiException { try { return new URL(getRestEndpoint() + "job/" + jobId + "/batch/" + batchId + "/result" + "/" + resultId); @@ -685,6 +686,10 @@ private InputStream doHttpGet(URL url) throws IOException, AsyncApiException { if (sslContext != null && connection instanceof HttpsURLConnection) { ((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory()); } + SSLSocketFactory sslSocketFactory = config.getSslSocketFactory(); + if (sslSocketFactory != null && connection instanceof HttpsURLConnection) { + ((HttpsURLConnection)connection).setSSLSocketFactory(sslSocketFactory); + } connection.setRequestProperty(SESSION_ID, config.getSessionId()); boolean success = true; diff --git a/src/main/java/com/sforce/ws/ConnectorConfig.java b/src/main/java/com/sforce/ws/ConnectorConfig.java index 77b65b33..ed5bb41e 100644 --- a/src/main/java/com/sforce/ws/ConnectorConfig.java +++ b/src/main/java/com/sforce/ws/ConnectorConfig.java @@ -39,10 +39,12 @@ import com.sforce.ws.util.Verbose; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + /** * This class contains a set of configuration properties - * + * * @author http://cheenath.com * @version 1.0 * @since 1.0 Dec 19, 2005 @@ -132,7 +134,7 @@ public void close() throws IOException { getTraceStream().println("------------ Request end ----------"); } } - + private int readTimeout; private int connectionTimeout; private boolean traceMessage; @@ -159,8 +161,11 @@ public void close() throws IOException { private Class transport = JdkHttpTransport.class; private SessionRenewer sessionRenewer; private String ntlmDomain; - private TransportFactory transportFactory; + private TransportFactory transportFactory; private SSLContext sslContext; + private SSLSocketFactory sslSocketFactory; + + public static final ConnectorConfig DEFAULT = new ConnectorConfig(); @@ -172,6 +177,10 @@ public SSLContext getSslContext() { return sslContext; } + public SSLSocketFactory getSslSocketFactory() { return sslSocketFactory; } + + public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) { this.sslSocketFactory = sslSocketFactory; } + public Class getTransport() { return transport; } @@ -179,11 +188,11 @@ public Class getTransport() { public TransportFactory getTransportFactory() { return transportFactory; } - + public void setTransportFactory(TransportFactory transportFactory) { this.transportFactory = transportFactory; } - + public void setTransport(Class transport) { this.transport = transport; } @@ -196,7 +205,7 @@ public void setNtlmDomain(String domain) { Verbose.log("http.auth.ntlm.domain already set"); } } - + public String getNtlmDomain() { return ntlmDomain; } @@ -385,11 +394,11 @@ public boolean isManualLogin() { public void setUseChunkedPost(boolean chunk) { this.useChunkedPost = chunk; } - + public boolean useChunkedPost() { return this.useChunkedPost; } - + public void verifyPartnerEndpoint() throws ConnectionException { verifyEndpoint("/services/Soap/u/"); } @@ -452,11 +461,11 @@ public String getRestEndpoint() { public void setRestEndpoint(String restEndpoint) { this.restEndpoint = restEndpoint; } - + public SessionRenewer getSessionRenewer() { return sessionRenewer; } - + public void setSessionRenewer(SessionRenewer sessionRenewer) { this.sessionRenewer = sessionRenewer; } @@ -465,7 +474,7 @@ public Transport createTransport() throws ConnectionException { if(transportFactory != null) { return transportFactory.createTransport(); } - + try { Transport t = (Transport)getTransport().newInstance(); t.setConfig(this); @@ -481,11 +490,11 @@ public HttpURLConnection createConnection(URL url, HashMap httpHeaders) throws IOException { return createConnection(url, httpHeaders, true); } - + public void teeInputStream(byte[] bytes) { new TeeInputStream(bytes); } - + public OutputStream teeOutputStream(OutputStream os) { return new TeeOutputStream(os); } diff --git a/src/main/java/com/sforce/ws/transport/JdkHttpTransport.java b/src/main/java/com/sforce/ws/transport/JdkHttpTransport.java index 07d086a3..c9f52555 100644 --- a/src/main/java/com/sforce/ws/transport/JdkHttpTransport.java +++ b/src/main/java/com/sforce/ws/transport/JdkHttpTransport.java @@ -41,6 +41,8 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + /** * This class is an implementation of Transport using the build in @@ -58,7 +60,7 @@ public class JdkHttpTransport implements Transport { public JdkHttpTransport() { } - + public JdkHttpTransport(ConnectorConfig config) { setConfig(config); } @@ -133,6 +135,10 @@ private OutputStream connectRaw(String uri, HashMap httpHeaders, if (sslContext != null && connection instanceof HttpsURLConnection) { ((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory()); } + SSLSocketFactory sslSocketFactory = config.getSslSocketFactory(); + if (sslSocketFactory != null && connection instanceof HttpsURLConnection) { + ((HttpsURLConnection)connection).setSSLSocketFactory(sslSocketFactory); + } connection.setRequestMethod("POST"); connection.setDoInput(true); connection.setDoOutput(true); @@ -195,7 +201,7 @@ public static HttpURLConnection createConnection(ConnectorConfig config, URL url if (config.getConnectionTimeout() != 0) { connection.setConnectTimeout(config.getConnectionTimeout()); } - + if (config.isTraceMessage()) { config.getTraceStream().println("WSC: Connection configured to have request properties " + connection.getRequestProperties()); } @@ -251,7 +257,7 @@ public InputStream getContent() throws IOException { config.getTraceStream().print("="); config.getTraceStream().println(header.getValue()); } - + config.teeInputStream(bytes); } }