diff --git a/sdk/src/main/java/com/silanis/esl/sdk/EslClient.java b/sdk/src/main/java/com/silanis/esl/sdk/EslClient.java index aa181afe6..bb8294a64 100644 --- a/sdk/src/main/java/com/silanis/esl/sdk/EslClient.java +++ b/sdk/src/main/java/com/silanis/esl/sdk/EslClient.java @@ -81,13 +81,26 @@ public EslClient(String apiKey, String baseURL, String webpageURL, boolean allow } public EslClient(String apiKey, String baseURL, boolean allowAllSSLCertificates) { - this(apiKey, baseURL, allowAllSSLCertificates, null); + this(apiKey, baseURL, allowAllSSLCertificates, (ProxyConfiguration) null); } public EslClient(String apiKey, String baseURL, ProxyConfiguration proxyConfiguration) { this(apiKey, baseURL, false, proxyConfiguration); } + public EslClient(String apiKey, String baseURL, SocksConfiguration socksConfiguration) { + this(apiKey, baseURL, false, socksConfiguration); + } + + public EslClient(String apiKey, String baseURL, boolean allowAllSSLCertificates, SocksConfiguration socksConfiguration) { + Asserts.notNullOrEmpty( apiKey, "apiKey" ); + Asserts.notNullOrEmpty( baseURL, "baseURL" ); + setBaseURL(baseURL); + setWebpageURL(baseURL); + RestClient client = new RestClient(apiKey, allowAllSSLCertificates, socksConfiguration); + init(client); + } + public EslClient(String apiKey, String baseURL, boolean allowAllSSLCertificates, ProxyConfiguration proxyConfiguration) { Asserts.notNullOrEmpty( apiKey, "apiKey" ); Asserts.notNullOrEmpty( baseURL, "baseURL" ); diff --git a/sdk/src/main/java/com/silanis/esl/sdk/ProxyConfiguration.java b/sdk/src/main/java/com/silanis/esl/sdk/ProxyConfiguration.java index 0988e2c7d..21f6ceb5e 100644 --- a/sdk/src/main/java/com/silanis/esl/sdk/ProxyConfiguration.java +++ b/sdk/src/main/java/com/silanis/esl/sdk/ProxyConfiguration.java @@ -49,6 +49,7 @@ public void setHttpsHost(String httpsHost) { public int getHttpsPort() { return httpsPort; } + public void setHttpsPort(int httpsPort) { this.httpsPort = httpsPort; } diff --git a/sdk/src/main/java/com/silanis/esl/sdk/SocksConfiguration.java b/sdk/src/main/java/com/silanis/esl/sdk/SocksConfiguration.java new file mode 100644 index 000000000..32c3aff6d --- /dev/null +++ b/sdk/src/main/java/com/silanis/esl/sdk/SocksConfiguration.java @@ -0,0 +1,58 @@ +package com.silanis.esl.sdk; + +/** + * Created by rochbu on 05/12/14. + */ +public class SocksConfiguration { + + private String socksHost; + private int socksPort; + private String userName; + private String password; + private boolean credentials; + + public SocksConfiguration(){ + socksHost = null; + socksPort = 0; + userName = null; + password = null; + credentials = false; + } + + public String getSocksHost() { + return socksHost; + } + + public void setSocksHost(String socksHost) { + this.socksHost = socksHost; + } + + public int getSocksPort() { + return socksPort; + } + + public void setSocksPort(int socksPort) { + this.socksPort = socksPort; + } + + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + public boolean hasCredentials() { + return credentials; + } + public void setCredentials(boolean credentials) { + this.credentials = credentials; + } +} diff --git a/sdk/src/main/java/com/silanis/esl/sdk/internal/RestClient.java b/sdk/src/main/java/com/silanis/esl/sdk/internal/RestClient.java index 392117399..c55ddcae9 100644 --- a/sdk/src/main/java/com/silanis/esl/sdk/internal/RestClient.java +++ b/sdk/src/main/java/com/silanis/esl/sdk/internal/RestClient.java @@ -1,10 +1,25 @@ package com.silanis.esl.sdk.internal; -import com.silanis.esl.sdk.Document; -import com.silanis.esl.sdk.EslException; -import com.silanis.esl.sdk.ProxyConfiguration; -import com.silanis.esl.sdk.io.DownloadedFile; -import com.silanis.esl.sdk.io.Streams; +import static com.silanis.esl.sdk.internal.HttpUtil.percentDecode; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Collection; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + import org.apache.http.Consts; import org.apache.http.Header; import org.apache.http.HttpException; @@ -13,8 +28,18 @@ import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; @@ -25,342 +50,449 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; +import org.apache.http.protocol.HttpContext; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.Collection; - -import static com.silanis.esl.sdk.internal.HttpUtil.percentDecode; +import com.silanis.esl.sdk.Document; +import com.silanis.esl.sdk.EslException; +import com.silanis.esl.sdk.ProxyConfiguration; +import com.silanis.esl.sdk.SocksConfiguration; +import com.silanis.esl.sdk.io.DownloadedFile; +import com.silanis.esl.sdk.io.Streams; public class RestClient { - public static final String CHARSET_UTF_8 = "UTF-8"; - private static final int BUFFER_SIZE = 4096; - - public static final String ESL_API_VERSION = "11.0"; - public static final String ESL_API_VERSION_HEADER = "esl-api-version=" + ESL_API_VERSION; - - public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; - public static final String ESL_CONTENT_TYPE_APPLICATION_JSON = CONTENT_TYPE_APPLICATION_JSON + "; " + ESL_API_VERSION_HEADER; - - public static final String HEADER_KEY_ACCEPT = "Accept"; - public static final String ACCEPT_TYPE_APPLICATION_JSON = "application/json"; - public static final String ACCEPT_TYPE_APPLICATION_OCTET_STREAM = "application/octet-stream"; - public static final String ACCEPT_TYPE_APPLICATION = "*/*"; - public static final String ESL_ACCEPT_TYPE_APPLICATION_JSON = ACCEPT_TYPE_APPLICATION_JSON + "; " + ESL_API_VERSION_HEADER; - public static final String ESL_ACCEPT_TYPE_APPLICATION_OCTET_STREAM = ACCEPT_TYPE_APPLICATION_OCTET_STREAM + "; " + ESL_API_VERSION_HEADER; - public static final String ESL_ACCEPT_TYPE_APPLICATION = ACCEPT_TYPE_APPLICATION + "; " + ESL_API_VERSION_HEADER; - - private final ResponseHandler bytesHandler = new BytesHandler(); - private final ResponseHandler jsonHandler = new JsonHandler(); - - private final String apiToken; - private final Support support = new Support(); - private final boolean allowAllSSLCertificates; - - private ProxyConfiguration proxyConfiguration; - - public RestClient(String apiToken) { - this(apiToken, false); - } - - public RestClient(String apiToken, boolean allowAllSSLCertificates) { - this(apiToken, allowAllSSLCertificates, null); - } - - public RestClient(String apiToken, ProxyConfiguration proxyConfiguration) { - this(apiToken, false, proxyConfiguration); - } - - public RestClient(String apiToken, boolean allowAllSSLCertificates, ProxyConfiguration proxyConfiguration) { - this.apiToken = apiToken; - this.allowAllSSLCertificates = allowAllSSLCertificates; - this.proxyConfiguration = proxyConfiguration; - } - - public String post(String path, String jsonPayload) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("POST", path, jsonPayload); - - HttpPost post = new HttpPost(path); - post.addHeader(buildAcceptHeaderForEslApi()); - if (jsonPayload != null) { - StringEntity body = new StringEntity(jsonPayload, Charset.forName(CHARSET_UTF_8)); - - body.setContentType(ESL_CONTENT_TYPE_APPLICATION_JSON); - - post.setEntity(body); - } - - return execute(post, jsonHandler); - } - - public String put(String path, String jsonPayload) throws IOException, RequestException { - support.logRequest("PUT", path, jsonPayload); - - HttpPut put = new HttpPut(path); - put.addHeader(buildAcceptHeaderForEslApi()); - StringEntity body = new StringEntity(jsonPayload, Charset.forName("UTF-8")); - - body.setContentType(ESL_CONTENT_TYPE_APPLICATION_JSON); - put.setEntity(body); - - return execute(put, jsonHandler); - } - - public String postMultipartFile(String path, String fileName, byte[] fileBytes, String jsonPayload) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("POST", path, jsonPayload); - - final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); - multipartEntityBuilder.addPart("payload", buildPartForPayload(jsonPayload)); - multipartEntityBuilder.addPart("file", buildPartForFile(fileBytes, fileName)); - - HttpPost post = new HttpPost(path); - - post.setEntity(multipartEntityBuilder.build()); - - return execute(post, jsonHandler); - } - - public String postMultipartPackage(String path, Collection documents, String jsonPayload) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("POST", path, jsonPayload); - - final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); - multipartEntityBuilder.addPart("payload", buildPartForPayload(jsonPayload)); - - for (com.silanis.esl.sdk.Document document : documents) { - multipartEntityBuilder.addPart("file", buildPartForFile(document)); - } - - HttpPost post = new HttpPost(path); - - post.setEntity(multipartEntityBuilder.build()); - return execute(post, jsonHandler); - } - - private StringBody buildPartForPayload(String jsonPayload) { - return new StringBody(jsonPayload, ContentType.create("text/plain", Consts.UTF_8)); - } - - private ContentBody buildPartForFile(byte[] content, String fileName) { - return buildPartForFile(content, fileName, fileName); - } - - private ByteArrayBody buildPartForFile(Document document) { - return buildPartForFile(document.getContent(), document.getFileName(), document.getName()); - } - - private ByteArrayBody buildPartForFile(byte[] content, String fileName, String name) { - String contentType = MimeTypeUtils.getContentTypeByFileName(fileName); - return new ByteArrayBody(content, ContentType.create(contentType), name); - } - - protected void addAuthorizationHeader(HttpUriRequest request) { - request.setHeader("Authorization", "Basic " + apiToken); - } - - private T execute(HttpUriRequest request, ResponseHandler handler) throws IOException, RequestException { - - CloseableHttpClient client = null; - try { - client = buildHttpClient(); - } catch (HttpException e) { - throw new RequestException(request.getRequestLine().getMethod(), - request.getRequestLine().getUri(), - 500, - "No SSL Socket Factory", - "Could not build request because of SSL socket Factory"); - } - - try { - addAuthorizationHeader(request); - support.log(request); - CloseableHttpResponse response = client.execute(request); - - if (response.getStatusLine().getStatusCode() >= 400) { - String errorDetails = Streams.toString(response.getEntity().getContent()); - throw new RequestException(request.getRequestLine().getMethod(), - request.getRequestLine().getUri(), - response.getStatusLine().getStatusCode(), - response.getStatusLine().getReasonPhrase(), - errorDetails); - } else if (response.getStatusLine().getStatusCode() == 204) { - return null; - } else { - InputStream bodyContent = response.getEntity().getContent(); - if(null != response.getHeaders("Content-Disposition") && response.getHeaders("Content-Disposition").length > 0) { - String fileName = getFilename(response.getHeaders("Content-Disposition")[0].getValue()); - DownloadedFile downloadedFile = (DownloadedFile) handler.extract(bodyContent); - downloadedFile.setFilename(fileName); - return (T)downloadedFile; - } - return handler.extract(bodyContent); - } - } finally { - if (null != client) { - client.close(); - } - } - } - - private String getFilename(String disposition) { - String fileNameTitle = "filename=\""; - String[] parts = disposition.split(";"); - - for(String part : parts) { - int index = part.indexOf(fileNameTitle); - if (index > 0) { - return percentDecode(part.substring(index + fileNameTitle.length(), part.length() - 1)); - } - } - - return ""; - } - - private CloseableHttpClient buildHttpClient() throws HttpException { - final HttpClientBuilder httpClientBuilder = HttpClients.custom(); - if (allowAllSSLCertificates) { - httpClientBuilder.setSSLSocketFactory(buildSSLSocketFactory()); - } - - if (proxyConfiguration != null) { - if (proxyConfiguration.hasCredentials()) { - httpClientBuilder.setDefaultCredentialsProvider(buildCredentialsConfiguration(proxyConfiguration)); - } - httpClientBuilder.setDefaultRequestConfig(buildProxyConfiguration(proxyConfiguration)); - return httpClientBuilder.build(); - } else { - return httpClientBuilder.build(); - } - } - - private SSLConnectionSocketFactory buildSSLSocketFactory() throws HttpException { - - //Disabling all checks that SSL certificate is valid. We are actually calling e-SignLive anyways. - //Our client library should implicitly trust our e-SignLive server. This also allows testing against - //server with Self-signed certificates. - try { - SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, - new TrustManager[]{new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted( - X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted( - X509Certificate[] certs, String authType) { - } - }}, new SecureRandom()); - return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - } catch (KeyManagementException e) { - throw new HttpException("Problem configuring SSL Socket factory", e); - } catch (NoSuchAlgorithmException e) { - throw new HttpException("Problem configuring SSL Socket factory", e); - } - } - - private RequestConfig buildProxyConfiguration(ProxyConfiguration proxyConfiguration) { - return RequestConfig.custom() - .setProxy(new HttpHost(proxyConfiguration.getHost(), proxyConfiguration.getPort(), proxyConfiguration.getScheme())) - .build(); - } - - private CredentialsProvider buildCredentialsConfiguration(ProxyConfiguration proxyConfiguration) { - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxyConfiguration.getHost(), proxyConfiguration.getPort()), - new UsernamePasswordCredentials(proxyConfiguration.getUserName(), proxyConfiguration.getPassword())); - return credentialsProvider; - } - - public String get(String path) throws IOException, HttpException, URISyntaxException, RequestException { - return get(path, ESL_ACCEPT_TYPE_APPLICATION_JSON); - } - - public String get(String path, String acceptType) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("GET", path); - HttpGet get = new HttpGet(path); - get.addHeader(buildAcceptHeader(acceptType)); - - return execute(get, jsonHandler); - } - - private Header buildAcceptHeaderForEslApi() { - return buildAcceptHeader(ESL_ACCEPT_TYPE_APPLICATION_JSON); - } - - private Header buildAcceptHeader(String acceptType) { - return new BasicHeader(HEADER_KEY_ACCEPT, acceptType); - } - - public DownloadedFile getBytes(String path) throws IOException, HttpException, URISyntaxException, RequestException { - return getBytes(path, ESL_ACCEPT_TYPE_APPLICATION); - } - - public DownloadedFile getBytes(String path, String acceptType) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("GET", path); - HttpGet get = new HttpGet(path); - get.addHeader(buildAcceptHeader(acceptType)); - - return execute(get, bytesHandler); - } - - public DownloadedFile getBytesAsOctetStream(String path) throws IOException, HttpException, URISyntaxException, RequestException { - return getBytesAsOctetStream(path, ESL_ACCEPT_TYPE_APPLICATION_OCTET_STREAM); - } - - public DownloadedFile getBytesAsOctetStream(String path, String acceptType) throws IOException, HttpException, URISyntaxException, RequestException { - support.logRequest("GET", path); - HttpGet get = new HttpGet(path); - get.addHeader(buildAcceptHeader(acceptType)); - - return execute(get, bytesHandler); - } - - public String delete(String path) throws HttpException, IOException, URISyntaxException, RequestException { - support.logRequest("DELETE", path); - HttpDelete delete = new HttpDelete(path); - delete.addHeader(buildAcceptHeaderForEslApi()); - - return execute(delete, jsonHandler); - } - - private static interface ResponseHandler { - T extract(InputStream input); - } - - private class BytesHandler implements ResponseHandler { - - public DownloadedFile extract(InputStream input) { - return new DownloadedFile("", Streams.toByteArray(input)); - } - } - - private class JsonHandler implements ResponseHandler { - - public String extract(InputStream input) { - try { - - String responseBody = Streams.toString(input); - - support.logResponse(responseBody); - return responseBody; - } catch (UnsupportedEncodingException e) { - throw new EslException("", e); - } - } - } + public static final String CHARSET_UTF_8 = "UTF-8"; + private static final int BUFFER_SIZE = 4096; + + public static final String ESL_API_VERSION = "11.0"; + public static final String ESL_API_VERSION_HEADER = "esl-api-version=" + + ESL_API_VERSION; + + public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; + public static final String ESL_CONTENT_TYPE_APPLICATION_JSON = CONTENT_TYPE_APPLICATION_JSON + + "; " + ESL_API_VERSION_HEADER; + + public static final String HEADER_KEY_ACCEPT = "Accept"; + public static final String ACCEPT_TYPE_APPLICATION_JSON = "application/json"; + public static final String ACCEPT_TYPE_APPLICATION_OCTET_STREAM = "application/octet-stream"; + public static final String ACCEPT_TYPE_APPLICATION = "*/*"; + public static final String ESL_ACCEPT_TYPE_APPLICATION_JSON = ACCEPT_TYPE_APPLICATION_JSON + + "; " + ESL_API_VERSION_HEADER; + public static final String ESL_ACCEPT_TYPE_APPLICATION_OCTET_STREAM = ACCEPT_TYPE_APPLICATION_OCTET_STREAM + + "; " + ESL_API_VERSION_HEADER; + public static final String ESL_ACCEPT_TYPE_APPLICATION = ACCEPT_TYPE_APPLICATION + + "; " + ESL_API_VERSION_HEADER; + + private final ResponseHandler bytesHandler = new BytesHandler(); + private final ResponseHandler jsonHandler = new JsonHandler(); + + private final String apiToken; + private final Support support = new Support(); + private final boolean allowAllSSLCertificates; + + private ProxyConfiguration proxyConfiguration; + private SocksConfiguration socksConfiguration; + + public RestClient(String apiToken) { + this(apiToken, false); + } + + public RestClient(String apiToken, boolean allowAllSSLCertificates) { + this(apiToken, allowAllSSLCertificates, (ProxyConfiguration) null); + } + + public RestClient(String apiToken, ProxyConfiguration proxyConfiguration) { + this(apiToken, false, proxyConfiguration); + } + + public RestClient(String apiToken, SocksConfiguration socksConfiguration) { + this(apiToken, false, socksConfiguration); + } + + public RestClient(String apiToken, boolean allowAllSSLCertificates, + ProxyConfiguration proxyConfiguration) { + this.apiToken = apiToken; + this.allowAllSSLCertificates = allowAllSSLCertificates; + this.proxyConfiguration = proxyConfiguration; + } + + public RestClient(String apiToken, boolean allowAllSSLCertificates, + SocksConfiguration socksConfiguration) { + this.apiToken = apiToken; + this.allowAllSSLCertificates = allowAllSSLCertificates; + this.socksConfiguration = socksConfiguration; + } + + + public String post(String path, String jsonPayload) throws IOException, + HttpException, URISyntaxException, RequestException { + support.logRequest("POST", path, jsonPayload); + + HttpPost post = new HttpPost(path); + post.addHeader(buildAcceptHeaderForEslApi()); + if (jsonPayload != null) { + StringEntity body = new StringEntity(jsonPayload, + Charset.forName(CHARSET_UTF_8)); + + body.setContentType(ESL_CONTENT_TYPE_APPLICATION_JSON); + + post.setEntity(body); + } + + return execute(post, jsonHandler); + } + + public String put(String path, String jsonPayload) throws IOException, + RequestException { + support.logRequest("PUT", path, jsonPayload); + + HttpPut put = new HttpPut(path); + put.addHeader(buildAcceptHeaderForEslApi()); + StringEntity body = new StringEntity(jsonPayload, + Charset.forName("UTF-8")); + + body.setContentType(ESL_CONTENT_TYPE_APPLICATION_JSON); + put.setEntity(body); + + return execute(put, jsonHandler); + } + + public String postMultipartFile(String path, String fileName, + byte[] fileBytes, String jsonPayload) throws IOException, + HttpException, URISyntaxException, RequestException { + support.logRequest("POST", path, jsonPayload); + + final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder + .create(); + multipartEntityBuilder.addPart("payload", + buildPartForPayload(jsonPayload)); + multipartEntityBuilder.addPart("file", + buildPartForFile(fileBytes, fileName)); + + HttpPost post = new HttpPost(path); + + post.setEntity(multipartEntityBuilder.build()); + + return execute(post, jsonHandler); + } + + public String postMultipartPackage(String path, + Collection documents, String jsonPayload) + throws IOException, HttpException, URISyntaxException, + RequestException { + support.logRequest("POST", path, jsonPayload); + + final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder + .create(); + multipartEntityBuilder.addPart("payload", + buildPartForPayload(jsonPayload)); + + for (com.silanis.esl.sdk.Document document : documents) { + multipartEntityBuilder.addPart("file", buildPartForFile(document)); + } + + HttpPost post = new HttpPost(path); + + post.setEntity(multipartEntityBuilder.build()); + return execute(post, jsonHandler); + } + + private StringBody buildPartForPayload(String jsonPayload) { + return new StringBody(jsonPayload, ContentType.create("text/plain", + Consts.UTF_8)); + } + + private ContentBody buildPartForFile(byte[] content, String fileName) { + return buildPartForFile(content, fileName, fileName); + } + + private ByteArrayBody buildPartForFile(Document document) { + return buildPartForFile(document.getContent(), document.getFileName(), + document.getName()); + } + + private ByteArrayBody buildPartForFile(byte[] content, String fileName, + String name) { + String contentType = MimeTypeUtils.getContentTypeByFileName(fileName); + return new ByteArrayBody(content, ContentType.create(contentType), name); + } + + protected void addAuthorizationHeader(HttpUriRequest request) { + request.setHeader("Authorization", "Basic " + apiToken); + } + + private T execute(HttpUriRequest request, ResponseHandler handler) + throws IOException, RequestException { + + CloseableHttpClient client = null; + try { + client = buildHttpClient(); + } catch (HttpException e) { + throw new RequestException(request.getRequestLine().getMethod(), + request.getRequestLine().getUri(), 500, + "No SSL Socket Factory", + "Could not build request because of SSL socket Factory"); + } + + try { + addAuthorizationHeader(request); + support.log(request); + + CloseableHttpResponse response = null; + + if (socksConfiguration != null) { + InetSocketAddress socksaddr = new InetSocketAddress(socksConfiguration.getSocksHost(),socksConfiguration.getSocksPort()); + HttpClientContext context = HttpClientContext.create(); + context.setAttribute("socks.address", socksaddr); + + response = client.execute(request, context); + } else { + response = client.execute(request); + } + + + if (response.getStatusLine().getStatusCode() >= 400) { + String errorDetails = Streams.toString(response.getEntity() + .getContent()); + throw new RequestException( + request.getRequestLine().getMethod(), request + .getRequestLine().getUri(), response + .getStatusLine().getStatusCode(), response + .getStatusLine().getReasonPhrase(), + errorDetails); + } else if (response.getStatusLine().getStatusCode() == 204) { + return null; + } else { + InputStream bodyContent = response.getEntity().getContent(); + if (null != response.getHeaders("Content-Disposition") + && response.getHeaders("Content-Disposition").length > 0) { + String fileName = getFilename(response + .getHeaders("Content-Disposition")[0].getValue()); + DownloadedFile downloadedFile = (DownloadedFile) handler + .extract(bodyContent); + downloadedFile.setFilename(fileName); + return (T) downloadedFile; + } + return handler.extract(bodyContent); + } + } finally { + if (null != client) { + client.close(); + } + } + } + + private String getFilename(String disposition) { + String fileNameTitle = "filename=\""; + String[] parts = disposition.split(";"); + + for (String part : parts) { + int index = part.indexOf(fileNameTitle); + if (index > 0) { + return percentDecode(part.substring( + index + fileNameTitle.length(), part.length() - 1)); + } + } + + return ""; + } + + private CloseableHttpClient buildHttpClient() throws HttpException { + + final HttpClientBuilder httpClientBuilder = HttpClients.custom(); + + if (allowAllSSLCertificates) { + httpClientBuilder.setSSLSocketFactory(buildSSLSocketFactory()); + } + + if (proxyConfiguration != null) { + if (proxyConfiguration.hasCredentials()) { + httpClientBuilder + .setDefaultCredentialsProvider(buildCredentialsConfiguration(proxyConfiguration)); + } + + httpClientBuilder + .setDefaultRequestConfig(buildProxyConfiguration(proxyConfiguration)); + return httpClientBuilder.build(); + + } else if (socksConfiguration != null) { + + if (socksConfiguration.hasCredentials()) { + + } + + Registry reg = RegistryBuilder.create() + .register("https", new SocksConnectionSocketFactory(SSLContexts.createSystemDefault())) + + .build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg); + + CloseableHttpClient httpClient = HttpClients.custom() + .setConnectionManager(cm) + .build(); + + return httpClient; + } else { + return httpClientBuilder.build(); + } + } + + private SSLConnectionSocketFactory buildSSLSocketFactory() + throws HttpException { + + // Disabling all checks that SSL certificate is valid. We are actually + // calling e-SignLive anyways. + // Our client library should implicitly trust our e-SignLive server. + // This also allows testing against + // server with Self-signed certificates. + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new TrustManager[] { new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, + String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, + String authType) { + } + } }, new SecureRandom()); + return new SSLConnectionSocketFactory(sslContext, + SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } catch (KeyManagementException e) { + throw new HttpException("Problem configuring SSL Socket factory", e); + } catch (NoSuchAlgorithmException e) { + throw new HttpException("Problem configuring SSL Socket factory", e); + } + } + + private RequestConfig buildProxyConfiguration( + ProxyConfiguration proxyConfiguration) { + return RequestConfig + .custom() + .setProxy( + new HttpHost(proxyConfiguration.getHost(), + proxyConfiguration.getPort(), + proxyConfiguration.getScheme())).build(); + } + + private CredentialsProvider buildCredentialsConfiguration( + ProxyConfiguration proxyConfiguration) { + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials( + new AuthScope(proxyConfiguration.getHost(), proxyConfiguration + .getPort()), + new UsernamePasswordCredentials(proxyConfiguration + .getUserName(), proxyConfiguration.getPassword())); + return credentialsProvider; + } + + public String get(String path) throws IOException, HttpException, + URISyntaxException, RequestException { + return get(path, ESL_ACCEPT_TYPE_APPLICATION_JSON); + } + + public String get(String path, String acceptType) throws IOException, + HttpException, URISyntaxException, RequestException { + support.logRequest("GET", path); + HttpGet get = new HttpGet(path); + get.addHeader(buildAcceptHeader(acceptType)); + + return execute(get, jsonHandler); + } + + private Header buildAcceptHeaderForEslApi() { + return buildAcceptHeader(ESL_ACCEPT_TYPE_APPLICATION_JSON); + } + + private Header buildAcceptHeader(String acceptType) { + return new BasicHeader(HEADER_KEY_ACCEPT, acceptType); + } + + public DownloadedFile getBytes(String path) throws IOException, + HttpException, URISyntaxException, RequestException { + return getBytes(path, ESL_ACCEPT_TYPE_APPLICATION); + } + + public DownloadedFile getBytes(String path, String acceptType) + throws IOException, HttpException, URISyntaxException, + RequestException { + support.logRequest("GET", path); + HttpGet get = new HttpGet(path); + get.addHeader(buildAcceptHeader(acceptType)); + + return execute(get, bytesHandler); + } + + public DownloadedFile getBytesAsOctetStream(String path) + throws IOException, HttpException, URISyntaxException, + RequestException { + return getBytesAsOctetStream(path, + ESL_ACCEPT_TYPE_APPLICATION_OCTET_STREAM); + } + + public DownloadedFile getBytesAsOctetStream(String path, String acceptType) + throws IOException, HttpException, URISyntaxException, + RequestException { + support.logRequest("GET", path); + HttpGet get = new HttpGet(path); + get.addHeader(buildAcceptHeader(acceptType)); + + return execute(get, bytesHandler); + } + + public String delete(String path) throws HttpException, IOException, + URISyntaxException, RequestException { + support.logRequest("DELETE", path); + HttpDelete delete = new HttpDelete(path); + delete.addHeader(buildAcceptHeaderForEslApi()); + + return execute(delete, jsonHandler); + } + + private static interface ResponseHandler { + T extract(InputStream input); + } + + private class BytesHandler implements ResponseHandler { + + public DownloadedFile extract(InputStream input) { + return new DownloadedFile("", Streams.toByteArray(input)); + } + } + + private class JsonHandler implements ResponseHandler { + + public String extract(InputStream input) { + try { + + String responseBody = Streams.toString(input); + + support.logResponse(responseBody); + return responseBody; + } catch (UnsupportedEncodingException e) { + throw new EslException("", e); + } + } + } + + static class SocksConnectionSocketFactory extends SSLConnectionSocketFactory { + + public SocksConnectionSocketFactory(final SSLContext sslContext) { + super(sslContext); + } + + @Override + public Socket createSocket(final HttpContext context) throws IOException { + InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address"); + Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr); + return new Socket(proxy); + } + + } }