diff --git a/src/main/java/Diadoc/Api/DiadocApi.java b/src/main/java/Diadoc/Api/DiadocApi.java index c4a3ede1..4568ed6f 100644 --- a/src/main/java/Diadoc/Api/DiadocApi.java +++ b/src/main/java/Diadoc/Api/DiadocApi.java @@ -49,13 +49,30 @@ public class DiadocApi { private EmployeePowerOfAttorneyClient employeePowerOfAttorneyClient; private DocumentWorkflowClient documentWorkflowClient; + protected final DiadocHttpClient diadocHttpClient; + public DiadocApi(String apiClientId, String url, @Nullable HttpHost proxyHost, @Nullable ConnectionSettings connectionSettings) { - if (url == null) { - throw new IllegalArgumentException("url"); + this( + new DiadocHttpClient( + apiClientId, + url, + proxyHost, + connectionSettings + ) + ); + } + + public DiadocApi(String apiClientId, String url) { + this(apiClientId, url, null, null); + } + + public DiadocApi(DiadocHttpClient diadocHttpClient) { + if (diadocHttpClient == null) { + throw new IllegalArgumentException("diadocHttpClient"); } - authManager = new AuthManager(apiClientId); - DiadocHttpClient diadocHttpClient = new DiadocHttpClient(authManager.getCredentialsProvider(), url, proxyHost, connectionSettings); - authClient = new AuthenticateClient(authManager, diadocHttpClient); + this.diadocHttpClient = diadocHttpClient; + authManager = new AuthManager(diadocHttpClient); + authClient = new AuthenticateClient(diadocHttpClient); organizationClient = new OrganizationClient(diadocHttpClient); departmentClient = new DepartmentClient(diadocHttpClient); employeeClient = new EmployeeClient(diadocHttpClient); @@ -78,10 +95,6 @@ public DiadocApi(String apiClientId, String url, @Nullable HttpHost proxyHost, @ authManager.setCredentials(null); } - public DiadocApi(String apiClientId, String url) { - this(apiClientId, url, null, null); - } - public AuthenticateClient getAuthClient() { return authClient; } diff --git a/src/main/java/Diadoc/Api/auth/AuthManager.java b/src/main/java/Diadoc/Api/auth/AuthManager.java index 6e44a9ae..c88eaa43 100644 --- a/src/main/java/Diadoc/Api/auth/AuthManager.java +++ b/src/main/java/Diadoc/Api/auth/AuthManager.java @@ -1,35 +1,30 @@ package Diadoc.Api.auth; -import org.apache.http.auth.AuthScope; +import Diadoc.Api.httpClient.DiadocHttpClient; import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; public class AuthManager { - private boolean isAuthenticated = false; - private String apiClientId; - private CredentialsProvider credentialsProvider; - - public AuthManager(String apiClientId) { - this.apiClientId = apiClientId; - credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, null)); + + private final DiadocHttpClient diadocHttpClient; + + public AuthManager(DiadocHttpClient diadocHttpClient) { + this.diadocHttpClient = diadocHttpClient; } public CredentialsProvider getCredentialsProvider() { - return credentialsProvider; + return diadocHttpClient.getCredentialsProvider(); } public boolean isAuthenticated() { - return isAuthenticated; + return diadocHttpClient.isAuthenticated(); } public void setCredentials(String authToken) { - isAuthenticated = (authToken != null); - credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, authToken)); + diadocHttpClient.setCredentials(authToken); } public void clearCredentials(){ - isAuthenticated = false; - credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, null)); + diadocHttpClient.clearCredentials(); } + } diff --git a/src/main/java/Diadoc/Api/auth/AuthenticateClient.java b/src/main/java/Diadoc/Api/auth/AuthenticateClient.java index f278eb29..376c89af 100644 --- a/src/main/java/Diadoc/Api/auth/AuthenticateClient.java +++ b/src/main/java/Diadoc/Api/auth/AuthenticateClient.java @@ -16,22 +16,20 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import static Diadoc.Api.Proto.ExternalServiceAuthInfoProtos.*; -import static java.nio.charset.StandardCharsets.*; +import static Diadoc.Api.Proto.ExternalServiceAuthInfoProtos.ExternalServiceAuthInfo; +import static java.nio.charset.StandardCharsets.UTF_8; public class AuthenticateClient { private static final String V_3_AUTHENTICATE = "/V3/Authenticate"; - private AuthManager authManager; private DiadocHttpClient diadocHttpClient; - public AuthenticateClient(AuthManager authManager, DiadocHttpClient diadocHttpClient) { - this.authManager = authManager; + public AuthenticateClient(DiadocHttpClient diadocHttpClient) { this.diadocHttpClient = diadocHttpClient; } public void authenticate(String sid) throws DiadocSdkException { try { - authManager.clearCredentials(); + diadocHttpClient.clearCredentials(); var request = RequestBuilder .post(new URIBuilder(diadocHttpClient.getBaseUrl()) .setPath(V_3_AUTHENTICATE) @@ -41,7 +39,7 @@ public void authenticate(String sid) throws DiadocSdkException { .setEntity(new ByteArrayEntity(sid.getBytes())); var response = diadocHttpClient.performRequest(request); - authManager.setCredentials(new String(response, UTF_8)); + diadocHttpClient.setCredentials(new String(response, UTF_8)); } catch (URISyntaxException | IOException ex) { throw new DiadocSdkException(ex); } @@ -49,7 +47,7 @@ public void authenticate(String sid) throws DiadocSdkException { public void authenticate(String login, String password) throws DiadocSdkException { try { - authManager.clearCredentials(); + diadocHttpClient.clearCredentials(); var request = RequestBuilder .post(new URIBuilder(diadocHttpClient.getBaseUrl()) @@ -65,7 +63,7 @@ public void authenticate(String login, String password) throws DiadocSdkExceptio .toByteArray())); var response = diadocHttpClient.performRequest(request); - authManager.setCredentials(new String(response, UTF_8)); + diadocHttpClient.setCredentials(new String(response, UTF_8)); } catch (IOException | URISyntaxException e) { throw new DiadocSdkException(e); } @@ -74,7 +72,7 @@ public void authenticate(String login, String password) throws DiadocSdkExceptio public void authenticate(X509Certificate currentCert, boolean autoConfirm) throws DiadocSdkException { try { - authManager.clearCredentials(); + diadocHttpClient.clearCredentials(); var request = RequestBuilder .post(new URIBuilder(diadocHttpClient.getBaseUrl()) @@ -110,7 +108,7 @@ public void confirmAuthenticationByCertificate(X509Certificate currentCert, Stri var response = diadocHttpClient.performRequest(request); - authManager.setCredentials(StringUtils.newStringUtf8(response)); + diadocHttpClient.setCredentials(StringUtils.newStringUtf8(response)); } catch (URISyntaxException | CertificateEncodingException | IOException ex) { throw new DiadocSdkException(ex); } diff --git a/src/main/java/Diadoc/Api/httpClient/DefaultHttpClientBuilder.java b/src/main/java/Diadoc/Api/httpClient/DefaultHttpClientBuilder.java new file mode 100644 index 00000000..bc1ad6ea --- /dev/null +++ b/src/main/java/Diadoc/Api/httpClient/DefaultHttpClientBuilder.java @@ -0,0 +1,105 @@ +package Diadoc.Api.httpClient; + +import Diadoc.Api.ConnectionSettings; +import Diadoc.Api.auth.DiadocPreemptiveAuthRequestInterceptor; +import Diadoc.Api.helpers.EnvironmentHelpers; +import org.apache.http.HttpHost; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustAllStrategy; +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.ssl.SSLContextBuilder; +import org.jetbrains.annotations.Nullable; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.function.Consumer; + +public class DefaultHttpClientBuilder { + + private Consumer connectionManagerConfigurer; + + private Consumer httpBuilderConfigurer; + + public CloseableHttpClient build(CredentialsProvider credentialsProvider) { + SSLConnectionSocketFactory sslSocketFactory = trustfulSslSocketFactory(); + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager( + RegistryBuilder.create() + .register("https", sslSocketFactory) + .register("http", new PlainConnectionSocketFactory()) + .build() + ); + if (connectionManagerConfigurer != null) { + connectionManagerConfigurer.accept(connectionManager); + } + + HttpClientBuilder builder = HttpClients.custom() + .setSSLSocketFactory(sslSocketFactory) + .setConnectionManager(connectionManager) + .setUserAgent(EnvironmentHelpers.getUserAgentString()) + .addInterceptorFirst(new DiadocPreemptiveAuthRequestInterceptor()) + .addInterceptorLast(new ContentLengthInterceptor()) + .setDefaultCredentialsProvider(credentialsProvider); + + if (httpBuilderConfigurer != null) { + httpBuilderConfigurer.accept(builder); + } + + return builder.build(); + } + + public DefaultHttpClientBuilder configureConnectionManager( + Consumer connectionManagerConfigurer + ) { + this.connectionManagerConfigurer = connectionManagerConfigurer; + return this; + } + + + public DefaultHttpClientBuilder configureHttpBuilder(Consumer httpBuilderConfigurer) { + this.httpBuilderConfigurer = httpBuilderConfigurer; + return this; + } + + + public static DefaultHttpClientBuilder defaultClient( + @Nullable HttpHost proxyHost, + @Nullable ConnectionSettings connectionSettings + ) { + DefaultHttpClientBuilder builder = new DefaultHttpClientBuilder(); + if (connectionSettings != null) { + builder.configureConnectionManager(cm -> { + cm.setMaxTotal(connectionSettings.getMaxTotalConnections()); + cm.setDefaultMaxPerRoute(connectionSettings.getMaxConnectionsPerRoute()); + }); + } + + if (proxyHost != null) { + builder.configureHttpBuilder(b -> { + b.setProxy(proxyHost); + }); + } + return builder; + } + + + public static SSLConnectionSocketFactory trustfulSslSocketFactory() { + try { + var ctx = SSLContextBuilder.create().loadTrustMaterial(new TrustAllStrategy()).build(); + return new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); + } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { + e.printStackTrace(); + throw new RuntimeException("Can't create ssl connection factory", e); + } + } + + +} diff --git a/src/main/java/Diadoc/Api/httpClient/DiadocHttpClient.java b/src/main/java/Diadoc/Api/httpClient/DiadocHttpClient.java index 365efd8d..4a8c7ddb 100644 --- a/src/main/java/Diadoc/Api/httpClient/DiadocHttpClient.java +++ b/src/main/java/Diadoc/Api/httpClient/DiadocHttpClient.java @@ -1,109 +1,126 @@ package Diadoc.Api.httpClient; import Diadoc.Api.ConnectionSettings; +import Diadoc.Api.auth.DiadocCredentials; import Diadoc.Api.exceptions.DiadocException; -import Diadoc.Api.auth.DiadocPreemptiveAuthRequestInterceptor; import Diadoc.Api.exceptions.DiadocSdkException; -import Diadoc.Api.helpers.EnvironmentHelpers; import Diadoc.Api.helpers.Tools; import org.apache.commons.io.IOUtils; -import org.apache.http.*; +import org.apache.http.Header; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.auth.AuthScope; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpResponseException; import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.client.utils.URIBuilder; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustAllStrategy; +import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.ssl.SSLContextBuilder; import org.jetbrains.annotations.Nullable; import javax.mail.internet.ContentDisposition; import javax.mail.internet.ParseException; import java.io.IOException; import java.net.URISyntaxException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.concurrent.TimeoutException; public class DiadocHttpClient { - private CloseableHttpClient httpClient; - private String baseUrl; + protected CloseableHttpClient httpClient; + + private final String baseUrl; + + private final String apiClientId; + + private final CredentialsProvider credentialsProvider; + + private boolean isAuthenticated = false; public DiadocHttpClient( - CredentialsProvider credentialsProvider, + String apiClientId, String baseUrl, @Nullable HttpHost proxyHost, @Nullable ConnectionSettings connectionSettings) { - var sslSocketFactory = getTrustfulSslSocketFactory(); - - var connectionManager = new PoolingHttpClientConnectionManager( - RegistryBuilder.create() - .register("https", sslSocketFactory) - .register("http", new PlainConnectionSocketFactory()) - .build()); - if(connectionSettings != null) { - connectionManager.setMaxTotal(connectionSettings.getMaxTotalConnections()); - connectionManager.setDefaultMaxPerRoute(connectionSettings.getMaxConnectionsPerRoute()); - } - var httpClientBuilder = HttpClients - .custom() - .setSSLSocketFactory(sslSocketFactory) - .setConnectionManager(connectionManager) - .setUserAgent(EnvironmentHelpers.getUserAgentString()) - .addInterceptorFirst(new DiadocPreemptiveAuthRequestInterceptor()) - .addInterceptorLast(new ContentLengthInterceptor()) - .setDefaultCredentialsProvider(credentialsProvider); - - if (proxyHost != null) { - httpClientBuilder.setProxy(proxyHost); + this(apiClientId, baseUrl, DefaultHttpClientBuilder.defaultClient(proxyHost, connectionSettings)); + } + + public DiadocHttpClient(String apiClientId, String baseUrl, DefaultHttpClientBuilder clientBuilder) { + if (baseUrl == null) { + throw new IllegalArgumentException("url"); } - httpClient = httpClientBuilder.build(); + this.apiClientId = apiClientId; this.baseUrl = baseUrl; + + credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, null)); + + httpClient = clientBuilder.build(credentialsProvider); } + public String getBaseUrl() { return baseUrl; } + public boolean isAuthenticated() { + return isAuthenticated; + } + + public void setCredentials(String authToken) { + isAuthenticated = (authToken != null); + credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, authToken)); + } + + public void clearCredentials(){ + isAuthenticated = false; + credentialsProvider.setCredentials(AuthScope.ANY, new DiadocCredentials(apiClientId, null)); + } + + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + + protected CloseableHttpResponse performCall(RequestBuilder requestBuilder) throws IOException { + return performCall(createRequest(requestBuilder)); + } + + protected CloseableHttpResponse performCall(HttpUriRequest request) throws IOException { + return httpClient.execute(request); + } + public byte[] performRequest(RequestBuilder requestBuilder) throws IOException { - try (var response = httpClient.execute(createRequest(requestBuilder))) { + try (var response = performCall(requestBuilder)) { return getResponseBytes(response); } } public GeneratedFile performRequestWithGeneratedFile(RequestBuilder requestBuilder) throws IOException, ParseException { - try (var response = httpClient.execute(createRequest(requestBuilder))) { + try (var response = performCall(requestBuilder)) { return new GeneratedFile(tryGetHttpResponseFileName(response), getResponseBytes(response)); } } public FileContent performRequestWithFileContent(RequestBuilder requestBuilder) throws IOException { - try (var response = httpClient.execute(createRequest(requestBuilder))) { + try (var response = performCall(requestBuilder)) { return new FileContent(getResponseBytes(response), tryGetFileContentName(response)); } } public DiadocResponseInfo getResponse(RequestBuilder requestBuilder) throws IOException { - try (var response = httpClient.execute(createRequest(requestBuilder))) { + try (var response = performCall(requestBuilder)) { return getResponse(response); } } public DiadocResponseInfo getRawResponse(RequestBuilder requestBuilder) throws IOException, ParseException { - try (var response = httpClient.execute(createRequest(requestBuilder))) { + try (var response = performCall(requestBuilder)) { return getRawResponse(response); } } @@ -145,12 +162,12 @@ private DiadocResponseInfo getRawResponse(HttpResponse response) throws IOExcept tryGetContentType(response)); } - private HttpUriRequest createRequest(RequestBuilder requestBuilder) { + protected HttpUriRequest createRequest(RequestBuilder requestBuilder) { var requestConfig = RequestConfig.custom().setAuthenticationEnabled(false).build(); return requestBuilder.setConfig(requestConfig).build(); } - private HttpUriRequest createWaitRequest(String path, String taskId) throws URISyntaxException { + protected HttpUriRequest createWaitRequest(String path, String taskId) throws URISyntaxException { return createRequest(RequestBuilder.get( new URIBuilder(baseUrl) .setPath(path) @@ -166,16 +183,6 @@ private static String tryGetContentType(HttpResponse response) { return null; } - private static SSLConnectionSocketFactory getTrustfulSslSocketFactory() { - try { - var ctx = SSLContextBuilder.create().loadTrustMaterial(new TrustAllStrategy()).build(); - return new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); - } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { - e.printStackTrace(); - throw new RuntimeException("Can't create ssl connection factory", e); - } - } - public byte[] waitTaskResult(String path, String taskId, @Nullable Integer timeoutInMillis) throws DiadocSdkException { if (timeoutInMillis == null) { timeoutInMillis = 5 * 60 * 1000; @@ -184,7 +191,7 @@ public byte[] waitTaskResult(String path, String taskId, @Nullable Integer timeo try { while (true) { - try (var response = httpClient.execute(createWaitRequest(path, taskId))) { + try (var response = performCall(createWaitRequest(path, taskId))) { var statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_NO_CONTENT) { if (new Date().getTime() > timeLimit) {