diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dd21cc..8500cff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,9 @@
+## 1.21.0 (10-06-2024)
+
+### Novità: 1
+- [#32690](https://parermine.regione.emilia-romagna.it/issues/32690) Introduzione di logica centralizzata per invocazione revocation URL via "single client instance" (DSS)
+
## 1.20.0 (06-06-2024)
### Novità: 1
diff --git a/CONTAINER-SCAN-REPORT.md b/CONTAINER-SCAN-REPORT.md
index 1385796..be87776 100644
--- a/CONTAINER-SCAN-REPORT.md
+++ b/CONTAINER-SCAN-REPORT.md
@@ -1,7 +1,7 @@
## Container scan evidence CVE
Image name: registry.ente.regione.emr.it/parer/okd/verifica-firma-eidas:sast
-
Run date: Thu Jun 6 18:35:21 CEST 2024
-
Produced by: Job
+
Run date: Mon Jun 10 17:26:01 CEST 2024
+
Produced by: Job
CVE founded: 8
| CVE | Description | Severity | Solution |
|:---:|:---|:---:|:---|
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 30dcb68..6690ff9 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -1,4 +1,4 @@
-## 1.20.0 (06-06-2024)
+## 1.21.0 (10-06-2024)
### Novità: 1
-- [#32661](https://parermine.regione.emilia-romagna.it/issues/32661) Ottimizzazione/Re-factor apache client utilizzato per recupero documento da verificare e parametro per disattivazione verifica SSL
+- [#32690](https://parermine.regione.emilia-romagna.it/issues/32690) Introduzione di logica centralizzata per invocazione revocation URL via "single client instance" (DSS)
diff --git a/pom.xml b/pom.xml
index e471cd5..f3cc814 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
verifica-firma-eidas
- 1.20.1-SNAPSHOT
+ 1.21.1-SNAPSHOT
${packaging.type}
Verifica Firma EIDAS
Progetto per effettuare firme e validazioni con librerie DSS (EIDAS)
diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java
new file mode 100644
index 0000000..c0e55d2
--- /dev/null
+++ b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java
@@ -0,0 +1,947 @@
+
+package it.eng.parer.eidas.core.bean;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.net.ssl.HostnameVerifier;
+
+import org.apache.hc.client5.http.HttpRequestRetryStrategy;
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.BasicScheme;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.io.HttpClientConnectionManager;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.io.SocketConfig;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.ssl.SSLContextBuilder;
+import org.apache.hc.core5.ssl.TrustStrategy;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import eu.europa.esig.dss.model.DSSDocument;
+import eu.europa.esig.dss.service.http.commons.CommonsHttpClientResponseHandler;
+import eu.europa.esig.dss.service.http.commons.HostConnection;
+import eu.europa.esig.dss.service.http.commons.UserCredentials;
+import eu.europa.esig.dss.spi.exception.DSSExternalResourceException;
+import eu.europa.esig.dss.utils.Utils;
+
+public class CommonsDataHttpClient implements Serializable {
+
+ private static final long serialVersionUID = 5684332248649660441L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(CommonsDataHttpClient.class);
+
+ /** The default connection timeout (1 minute) */
+ private static final Timeout TIMEOUT_CONNECTION = toTimeoutMilliseconds(60000);
+
+ /** The default socket timeout (1 minute) */
+ private static final Timeout TIMEOUT_SOCKET = toTimeoutMilliseconds(60000);
+
+ /** The default value of maximum connections in time (20) */
+ private static final int CONNECTIONS_MAX_TOTAL = 20;
+
+ /** The default value of maximum connections per route (2) */
+ private static final int CONNECTIONS_MAX_PER_ROUTE = 2;
+
+ /** The default connection total time to live (TTL) (1 minute) */
+ private static final TimeValue CONNECTION_TIME_TO_LIVE = toTimeValueMilliseconds(60000);
+
+ /** The timeout connection */
+ private Timeout timeoutConnection = TIMEOUT_CONNECTION;
+
+ /** The connection request timeout */
+ private Timeout timeoutConnectionRequest = TIMEOUT_CONNECTION;
+
+ /** The server response timeout */
+ private Timeout timeoutResponse = TIMEOUT_CONNECTION;
+
+ /** The timeout socket */
+ private Timeout timeoutSocket = TIMEOUT_SOCKET;
+
+ /** Connection keep alive timeout */
+ private TimeValue connectionKeepAlive = CONNECTION_TIME_TO_LIVE;
+
+ /** Maximum connections number in time */
+ private int connectionsMaxTotal = CONNECTIONS_MAX_TOTAL;
+
+ /** Maximum connections number per route */
+ private int connectionsMaxPerRoute = CONNECTIONS_MAX_PER_ROUTE;
+
+ /** The finite connection total time to live (TTL) */
+ private TimeValue connectionTimeToLive = CONNECTION_TIME_TO_LIVE;
+
+ /** Defines if the redirection is enabled */
+ private boolean redirectsEnabled = true;
+
+ /** Defines if the default system network properties shall be used */
+ private boolean useSystemProperties = false;
+
+ /** Contains rules credentials for authentication to different resources */
+ private Map authenticationMap;
+
+ /**
+ * Used SSL protocol
+ */
+ private String sslProtocol;
+
+ /**
+ * Keystore for SSL.
+ */
+ private DSSDocument sslKeystore;
+
+ /**
+ * Keystore's type.
+ */
+ private String sslKeystoreType = KeyStore.getDefaultType();
+
+ /**
+ * Keystore's password.
+ */
+ private char[] sslKeystorePassword = new char[] {};
+
+ /**
+ * Defines if the keyStore shall be loaded as a trusted material
+ */
+ private boolean loadKeyStoreAsTrustMaterial = false;
+
+ /**
+ * TrustStore for SSL.
+ */
+ private DSSDocument sslTruststore;
+
+ /**
+ * Trust store's type
+ */
+ private String sslTruststoreType = KeyStore.getDefaultType();
+
+ /**
+ * Truststore's password.
+ */
+ private char[] sslTruststorePassword = new char[] {};
+
+ /**
+ * The trust strategy
+ */
+ private transient TrustStrategy trustStrategy;
+
+ /**
+ * Array of supported SSL protocols
+ */
+ private String[] supportedSSLProtocols;
+
+ /**
+ * Array of supported SSL Cipher Suites
+ */
+ private String[] supportedSSLCipherSuites;
+
+ /**
+ * The hostname verifier
+ */
+ private transient HostnameVerifier hostnameVerifier = new DefaultHostnameVerifier();
+
+ /**
+ * The connection retry strategy
+ */
+ private transient HttpRequestRetryStrategy retryStrategy;
+
+ /**
+ * Defines whether the preemptive basic authentication should be used
+ */
+ private boolean preemptiveAuthentication;
+
+ /**
+ * Processes the HTTP dataHttpClient response and returns byte array in case of success Default:
+ * {@code CommonsHttpClientResponseHandler}
+ */
+ private transient HttpClientResponseHandler httpClientResponseHandler = new CommonsHttpClientResponseHandler();
+
+ /**
+ * Standard dataHttpClient
+ */
+ private transient CloseableHttpClient client;
+
+ /**
+ * The default constructor for CommonsDataLoader.
+ */
+ public CommonsDataHttpClient() {
+ // empty
+ }
+
+ /**
+ * init method
+ */
+ public void init() {
+ if (client == null) {
+ client = createHttpClient();
+ }
+ }
+
+ /**
+ * destroy method
+ *
+ * @throws IOException
+ * generic exception
+ */
+ public void destroy() throws IOException {
+ if (client != null) {
+ client.close();
+ }
+ }
+
+ /**
+ * Gets the connection timeout.
+ *
+ * @return the value (millis)
+ */
+ public int getTimeoutConnection() {
+ return timeoutConnection.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the connection timeout in milliseconds.
+ *
+ * A negative value is interpreted as undefined (use system default).
+ *
+ * @param timeoutConnection
+ * the value (millis)
+ */
+ public void setTimeoutConnection(final int timeoutConnection) {
+ this.timeoutConnection = toTimeoutMilliseconds(timeoutConnection);
+ }
+
+ /**
+ * Gets the connection request timeout.
+ *
+ * @return the value (millis)
+ */
+ public int getTimeoutConnectionRequest() {
+ return timeoutConnectionRequest.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the connection request in milliseconds.
+ *
+ * A negative value is interpreted as undefined (use system default).
+ *
+ * @param timeoutConnectionRequest
+ * the value (millis)
+ */
+ public void setTimeoutConnectionRequest(int timeoutConnectionRequest) {
+ this.timeoutConnectionRequest = toTimeoutMilliseconds(timeoutConnectionRequest);
+ }
+
+ /**
+ * Gets the server response timeout.
+ *
+ * @return the value (millis)
+ */
+ public int getTimeoutResponse() {
+ return timeoutResponse.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the server response timeout in milliseconds.
+ *
+ * A negative value is interpreted as undefined (use system default).
+ *
+ * @param timeoutResponse
+ * the value (millis)
+ */
+ public void setTimeoutResponse(int timeoutResponse) {
+ this.timeoutResponse = toTimeoutMilliseconds(timeoutResponse);
+ }
+
+ /**
+ * Gets the socket timeout.
+ *
+ * @return the value (millis)
+ */
+ public int getTimeoutSocket() {
+ return timeoutSocket.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the socket timeout in milliseconds.
+ *
+ * A negative value is interpreted as undefined (use system default).
+ *
+ * @param timeoutSocket
+ * the value (millis)
+ */
+ public void setTimeoutSocket(final int timeoutSocket) {
+ this.timeoutSocket = toTimeoutMilliseconds(timeoutSocket);
+ }
+
+ /**
+ * Gets the connection keep alive timeout.
+ *
+ * @return the value (millis)
+ */
+ public int getConnectionKeepAlive() {
+ return connectionKeepAlive.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the connection keep alive timeout in milliseconds.
+ *
+ * @param connectionKeepAlive
+ * the value (millis)
+ */
+ public void setConnectionKeepAlive(int connectionKeepAlive) {
+ this.connectionKeepAlive = toTimeValueMilliseconds(connectionKeepAlive);
+ }
+
+ /**
+ * Gets the maximum connections number.
+ *
+ * @return the value (millis)
+ */
+ public int getConnectionsMaxTotal() {
+ return connectionsMaxTotal;
+ }
+
+ /**
+ * Sets the maximum connections number.
+ *
+ * @param connectionsMaxTotal
+ * maximum number of connections
+ */
+ public void setConnectionsMaxTotal(int connectionsMaxTotal) {
+ this.connectionsMaxTotal = connectionsMaxTotal;
+ }
+
+ /**
+ * Gets the maximum connections number per route.
+ *
+ * @return maximum number of connections per one route
+ */
+ public int getConnectionsMaxPerRoute() {
+ return connectionsMaxPerRoute;
+ }
+
+ /**
+ * Sets the maximum connections number per route.
+ *
+ * @param connectionsMaxPerRoute
+ * maximum number of connections per one route
+ */
+ public void setConnectionsMaxPerRoute(int connectionsMaxPerRoute) {
+ this.connectionsMaxPerRoute = connectionsMaxPerRoute;
+ }
+
+ /**
+ * Gets the finite connection time to live.
+ *
+ * @return connection time to live (millis)
+ */
+ public int getConnectionTimeToLive() {
+ return connectionTimeToLive.toMillisecondsIntBound();
+ }
+
+ /**
+ * Sets the finite connection total time to live (TTL) in milliseconds.
+ *
+ * @param connectionTimeToLive
+ * the finite connection time to live (millis)
+ */
+ public void setConnectionTimeToLive(int connectionTimeToLive) {
+ this.connectionTimeToLive = toTimeValueMilliseconds(connectionTimeToLive);
+ }
+
+ /**
+ * Gets if redirect is enabled.
+ *
+ * @return true if http redirects are allowed
+ */
+ public boolean isRedirectsEnabled() {
+ return redirectsEnabled;
+ }
+
+ /**
+ * Sets if redirect should be enabled.
+ *
+ * @param redirectsEnabled
+ * true if http redirects are allowed
+ */
+ public void setRedirectsEnabled(boolean redirectsEnabled) {
+ this.redirectsEnabled = redirectsEnabled;
+ }
+
+ /**
+ * Gets if the default system network properties shall be used
+ *
+ * @return TRUE if the default system network properties shall be used, FALSE otherwise
+ */
+ public boolean isUseSystemProperties() {
+ return useSystemProperties;
+ }
+
+ /**
+ * Sets if the default system network properties shall be used
+ *
+ * Default: FALSE (system properties are not used)
+ *
+ * NOTE: all other configured property may override the default behavior!
+ *
+ * @param useSystemProperties
+ * if the default system network properties shall be used
+ */
+ public void setUseSystemProperties(boolean useSystemProperties) {
+ this.useSystemProperties = useSystemProperties;
+ }
+
+ /**
+ * This method sets the SSL protocol to be used
+ *
+ * @param sslProtocol
+ * the ssl protocol to be used
+ */
+ public void setSslProtocol(String sslProtocol) {
+ this.sslProtocol = sslProtocol;
+ }
+
+ /**
+ * Sets the SSL KeyStore
+ *
+ * @param sslKeyStore
+ * {@link DSSDocument}
+ */
+ public void setSslKeystore(DSSDocument sslKeyStore) {
+ this.sslKeystore = sslKeyStore;
+ }
+
+ /**
+ * Sets if the KeyStore shall be considered as a trust material (used for SSL connection)
+ *
+ * @param loadKeyStoreAsTrustMaterial
+ * if the KeyStore shall be considered as a trust material
+ */
+ public void setKeyStoreAsTrustMaterial(boolean loadKeyStoreAsTrustMaterial) {
+ this.loadKeyStoreAsTrustMaterial = loadKeyStoreAsTrustMaterial;
+ }
+
+ /**
+ * Sets the SSL KeyStore type
+ *
+ * @param sslKeystoreType
+ * {@link String}
+ */
+ public void setSslKeystoreType(String sslKeystoreType) {
+ this.sslKeystoreType = sslKeystoreType;
+ }
+
+ /**
+ * Sets the KeyStore password. Please note that the password shall be the same for the keystore and the extraction
+ * of a corresponding key.
+ *
+ * @param sslKeystorePassword
+ * char array representing the password
+ */
+ public void setSslKeystorePassword(char[] sslKeystorePassword) {
+ this.sslKeystorePassword = sslKeystorePassword;
+ }
+
+ /**
+ * Sets the SSL trust store
+ *
+ * NOTE: different from KeyStore!
+ *
+ * @param sslTrustStore
+ * {@link DSSDocument}
+ */
+ public void setSslTruststore(DSSDocument sslTrustStore) {
+ this.sslTruststore = sslTrustStore;
+ }
+
+ /**
+ * Sets the password for SSL truststore
+ *
+ * @param sslTruststorePassword
+ * char array representing a password string
+ */
+ public void setSslTruststorePassword(char[] sslTruststorePassword) {
+ this.sslTruststorePassword = sslTruststorePassword;
+ }
+
+ /**
+ * Sets the SSL TrustStore type
+ *
+ * @param sslTruststoreType
+ * {@link String}
+ */
+ public void setSslTruststoreType(String sslTruststoreType) {
+ this.sslTruststoreType = sslTruststoreType;
+ }
+
+ /**
+ * Returns the current instance of the authentication map
+ *
+ * @return a map between {@link HostConnection} and {@link UserCredentials}
+ */
+ public Map getAuthenticationMap() {
+ if (authenticationMap == null) {
+ authenticationMap = new HashMap<>();
+ }
+ return authenticationMap;
+ }
+
+ /**
+ * Sets the authentication map
+ *
+ * NOTE: this method overrides the current instance of {@code authenticationMap}
+ *
+ * @param authenticationMap
+ * a map between {@link HostConnection} and {@link UserCredentials}
+ */
+ public void setAuthenticationMap(Map authenticationMap) {
+ this.authenticationMap = authenticationMap;
+ }
+
+ /**
+ * Adds authentication credentials to the existing {@code authenticationMap}
+ *
+ * @param hostConnection
+ * host connection details
+ * @param userCredentials
+ * user login credentials
+ *
+ * @return this (for fluent addAuthentication)
+ */
+ public CommonsDataHttpClient addAuthentication(HostConnection hostConnection, UserCredentials userCredentials) {
+ Map authenticationMap = getAuthenticationMap();
+ authenticationMap.put(hostConnection, userCredentials);
+ return this;
+ }
+
+ /**
+ * Sets whether the preemptive authentication should be used. When set to TRUE, the dataHttpClient sends
+ * authentication details (i.e. user credentials) within the initial request to the remote host, instead of sending
+ * the credentials only after a request from the host. Please note that the preemptive authentication should not be
+ * used over an insecure connection. Default : FALSE (preemptive authentication is not used)
+ *
+ * @param preemptiveAuthentication
+ * whether the preemptive authentication should be used
+ */
+ public void setPreemptiveAuthentication(boolean preemptiveAuthentication) {
+ this.preemptiveAuthentication = preemptiveAuthentication;
+ }
+
+ /**
+ * Adds authentication credentials to the existing {@code authenticationMap}
+ *
+ * @param host
+ * host
+ * @param port
+ * port
+ * @param scheme
+ * scheme
+ * @param login
+ * login
+ * @param password
+ * password
+ *
+ * @return this (for fluent addAuthentication)
+ */
+ public CommonsDataHttpClient addAuthentication(final String host, final int port, final String scheme,
+ final String login, final char[] password) {
+ final HostConnection hostConnection = new HostConnection(host, port, scheme);
+ final UserCredentials userCredentials = new UserCredentials(login, password);
+ return addAuthentication(hostConnection, userCredentials);
+ }
+
+ /**
+ * Sets a custom retry strategy
+ *
+ * @param retryStrategy
+ * {@link HttpRequestRetryStrategy}
+ */
+ public void setRetryStrategy(final HttpRequestRetryStrategy retryStrategy) {
+ this.retryStrategy = retryStrategy;
+ }
+
+ /**
+ * Gets supported SSL protocols
+ *
+ * @return an array if {@link String}s
+ */
+ public String[] getSupportedSSLProtocols() {
+ return supportedSSLProtocols;
+ }
+
+ /**
+ * Sets supported SSL protocols
+ *
+ * @param supportedSSLProtocols
+ * an array if {@link String}s
+ */
+ public void setSupportedSSLProtocols(String[] supportedSSLProtocols) {
+ this.supportedSSLProtocols = supportedSSLProtocols;
+ }
+
+ /**
+ * Gets supported SSL Cipher Suites
+ *
+ * @return an array if {@link String}s
+ */
+ public String[] getSupportedSSLCipherSuites() {
+ return supportedSSLCipherSuites;
+ }
+
+ /**
+ * Sets supported SSL Cipher Suites
+ *
+ * @param supportedSSLCipherSuites
+ * an array if {@link String}s
+ */
+ public void setSupportedSSLCipherSuites(String[] supportedSSLCipherSuites) {
+ this.supportedSSLCipherSuites = supportedSSLCipherSuites;
+ }
+
+ /**
+ * Gets the hostname verifier
+ *
+ * @return {@link HostnameVerifier}
+ */
+ public HostnameVerifier getHostnameVerifier() {
+ return hostnameVerifier;
+ }
+
+ /**
+ * Sets a custom {@code HostnameVerifier}
+ *
+ * @param hostnameVerifier
+ * {@link HostnameVerifier}
+ */
+ public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
+ this.hostnameVerifier = hostnameVerifier;
+ }
+
+ /**
+ * Gets the TrustStrategy
+ *
+ * @return {@link TrustStrategy}
+ */
+ public TrustStrategy getTrustStrategy() {
+ return trustStrategy;
+ }
+
+ /**
+ * Sets the {@code TrustStrategy}
+ *
+ * @param trustStrategy
+ * {@link TrustStrategy}
+ */
+ public void setTrustStrategy(TrustStrategy trustStrategy) {
+ this.trustStrategy = trustStrategy;
+ }
+
+ /**
+ * Returns the {@code HttpClientResponseHandler} response handler
+ *
+ * @return {@link HttpClientResponseHandler}
+ */
+ public HttpClientResponseHandler getHttpClientResponseHandler() {
+ return httpClientResponseHandler;
+ }
+
+ /**
+ * Sets the {@code HttpClientResponseHandler} response handler performing a processing of an HTTP
+ * dataHttpClient response and returns a byte array in case of success.
+ *
+ * @param httpClientResponseHandler
+ * {@link HttpClientResponseHandler}
+ */
+ public void setHttpClientResponseHandler(HttpClientResponseHandler httpClientResponseHandler) {
+ Objects.requireNonNull(httpClientResponseHandler, "HttpClientResponseHandler cannot be null!");
+ this.httpClientResponseHandler = httpClientResponseHandler;
+ }
+
+ /**
+ * Gets the {@code HttpHost}
+ *
+ * @param httpRequest
+ * {@link HttpUriRequest}
+ *
+ * @return {@link HttpHost}
+ */
+ protected HttpHost getHttpHost(final HttpUriRequest httpRequest) {
+ try {
+ final URI uri = httpRequest.getUri();
+ return new HttpHost(uri.getScheme(), uri.getHost(), uri.getPort());
+ } catch (URISyntaxException e) {
+ throw new DSSExternalResourceException(String.format("Invalid URI : %s", e.getMessage()), e);
+ }
+ }
+
+ /**
+ * Gets the {@code HttpContext}
+ *
+ * @param httpHost
+ * {@link HttpHost}
+ *
+ * @return {@link HttpContext}
+ */
+ protected HttpContext getHttpContext(HttpHost httpHost) {
+ HttpClientContext localContext = HttpClientContext.create();
+ localContext = configurePreemptiveAuthentication(localContext, httpHost);
+ return localContext;
+ }
+
+ /**
+ * This method is used to configure preemptive authentication process for {@code HttpClientContext}, when required
+ *
+ * @param localContext
+ * {@link HttpClientContext}
+ * @param httpHost
+ * {@link HttpHost}
+ *
+ * @return {@link HttpClientContext}
+ */
+ protected HttpClientContext configurePreemptiveAuthentication(HttpClientContext localContext, HttpHost httpHost) {
+ if (preemptiveAuthentication && Utils.isMapNotEmpty(getAuthenticationMap())) {
+ Credentials credentials = getCredentialsProvider().getCredentials(new AuthScope(httpHost), localContext);
+ BasicScheme basicScheme = new BasicScheme();
+ basicScheme.initPreemptive(credentials);
+ localContext.resetAuthExchange(httpHost, basicScheme);
+ }
+ return localContext;
+ }
+
+ /**
+ * Closes all the parameters quietly
+ *
+ * @param httpRequest
+ * {@link HttpUriRequestBase}
+ * @param client
+ * {@link CloseableHttpClient}
+ */
+ protected void closeQuietly(HttpUriRequestBase httpRequest, CloseableHttpClient client) {
+ try {
+ if (httpRequest != null) {
+ httpRequest.cancel();
+ }
+ } finally {
+ Utils.closeQuietly(client);
+ }
+ }
+
+ private HttpClientConnectionManager getConnectionManager() {
+ final PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create()
+ .setSSLSocketFactory(getConnectionSocketFactoryHttps()).setDefaultSocketConfig(getSocketConfig())
+ .setMaxConnTotal(getConnectionsMaxTotal()).setMaxConnPerRoute(getConnectionsMaxPerRoute());
+
+ final ConnectionConfig.Builder connectionConfigBuilder = ConnectionConfig.custom()
+ .setConnectTimeout(timeoutConnection).setTimeToLive(connectionTimeToLive);
+
+ final PoolingHttpClientConnectionManager connectionManager = builder.build();
+ connectionManager.setDefaultConnectionConfig(connectionConfigBuilder.build());
+
+ LOG.debug("PoolingHttpClientConnectionManager: max total: {}", connectionManager.getMaxTotal());
+ LOG.debug("PoolingHttpClientConnectionManager: max per route: {}", connectionManager.getDefaultMaxPerRoute());
+
+ return connectionManager;
+ }
+
+ private SocketConfig getSocketConfig() {
+ SocketConfig.Builder socketConfigBuilder = SocketConfig.custom();
+ socketConfigBuilder.setSoTimeout(timeoutSocket);
+ return socketConfigBuilder.build();
+ }
+
+ private SSLConnectionSocketFactory getConnectionSocketFactoryHttps() {
+ try {
+ SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
+ sslContextBuilder.setProtocol(sslProtocol);
+
+ final TrustStrategy trustStrategy = getTrustStrategy();
+ if (trustStrategy != null) {
+ LOG.debug("Set the TrustStrategy");
+ sslContextBuilder.loadTrustMaterial(null, trustStrategy);
+ }
+
+ final KeyStore sslTrustStore = getSSLTrustStore();
+ if (sslTrustStore != null) {
+ LOG.debug("Set the SSL trust store as trust materials");
+ sslContextBuilder.loadTrustMaterial(sslTrustStore, trustStrategy);
+ }
+
+ final KeyStore sslKeystore = getSSLKeyStore();
+ if (sslKeystore != null) {
+ LOG.debug("Set the SSL keystore as key materials");
+ sslContextBuilder.loadKeyMaterial(sslKeystore, sslKeystorePassword);
+ if (loadKeyStoreAsTrustMaterial) {
+ LOG.debug("Set the SSL keystore as trust materials");
+ sslContextBuilder.loadTrustMaterial(sslKeystore, trustStrategy);
+ }
+ }
+
+ SSLConnectionSocketFactoryBuilder sslConnectionSocketFactoryBuilder = new SSLConnectionSocketFactoryBuilder();
+ return sslConnectionSocketFactoryBuilder.setSslContext(sslContextBuilder.build())
+ .setTlsVersions(getSupportedSSLProtocols()).setCiphers(getSupportedSSLCipherSuites())
+ .setHostnameVerifier(getHostnameVerifier()).build();
+
+ } catch (final Exception e) {
+ throw new IllegalArgumentException("Unable to configure the SSLContext/SSLConnectionSocketFactory", e);
+ }
+ }
+
+ /**
+ * Gets the SSL KeyStore
+ *
+ * @return {@link KeyStore}
+ *
+ * @throws IOException
+ * if IOException occurs
+ * @throws GeneralSecurityException
+ * if GeneralSecurityException occurs
+ */
+ protected KeyStore getSSLKeyStore() throws IOException, GeneralSecurityException {
+ return loadKeyStore(sslKeystore, sslKeystoreType, sslKeystorePassword);
+ }
+
+ /**
+ * Gets the SSL Trusted KeyStore
+ *
+ * @return {@link KeyStore}
+ *
+ * @throws IOException
+ * if IOException occurs
+ * @throws GeneralSecurityException
+ * if GeneralSecurityException occurs
+ */
+ protected KeyStore getSSLTrustStore() throws IOException, GeneralSecurityException {
+ return loadKeyStore(sslTruststore, sslTruststoreType, sslTruststorePassword);
+ }
+
+ private KeyStore loadKeyStore(DSSDocument store, String type, char[] password)
+ throws IOException, GeneralSecurityException {
+ if (store != null) {
+ try (InputStream is = store.openStream()) {
+ KeyStore ks = KeyStore.getInstance(type);
+ ks.load(is, password);
+ return ks;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the {@code HttpClientBuilder}
+ *
+ *
+ * @return {@link HttpClientBuilder}
+ */
+ protected HttpClientBuilder getHttpClientBuilder() {
+ HttpClientBuilder httpClientBuilder = HttpClients.custom();
+
+ if (useSystemProperties) {
+ httpClientBuilder.useSystemProperties();
+ }
+
+ httpClientBuilder = configCredentials(httpClientBuilder);
+
+ final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
+ .setConnectionRequestTimeout(timeoutConnectionRequest).setResponseTimeout(timeoutResponse)
+ .setConnectionKeepAlive(connectionKeepAlive).setRedirectsEnabled(redirectsEnabled);
+
+ httpClientBuilder.setConnectionManager(getConnectionManager())
+ .setDefaultRequestConfig(requestConfigBuilder.build()).setRetryStrategy(retryStrategy);
+
+ return httpClientBuilder;
+ }
+
+ /**
+ * Create the HTTP dataHttpClient
+ *
+ * @return {@link CloseableHttpClient}
+ */
+ protected CloseableHttpClient createHttpClient() {
+ return getHttpClientBuilder().build();
+ }
+
+ /**
+ * Defines the Credentials
+ *
+ * @param httpClientBuilder
+ * {@link HttpClientBuilder}
+ * @param url
+ * {@link String}
+ *
+ * @return {@link HttpClientBuilder}
+ */
+ private HttpClientBuilder configCredentials(HttpClientBuilder httpClientBuilder) {
+ final BasicCredentialsProvider credentialsProvider = getCredentialsProvider();
+ httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+ return httpClientBuilder;
+ }
+
+ /**
+ * Builds and returns a {@code BasicCredentialsProvider} configured with {@code authenticationMap}
+ *
+ * @return {@link BasicCredentialsProvider}
+ */
+ protected BasicCredentialsProvider getCredentialsProvider() {
+ final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+ for (final Map.Entry entry : getAuthenticationMap().entrySet()) {
+ final HostConnection hostConnection = entry.getKey();
+ final UserCredentials userCredentials = entry.getValue();
+ final AuthScope authscope = new AuthScope(hostConnection.getProtocol(), hostConnection.getHost(),
+ hostConnection.getPort(), hostConnection.getRealm(), hostConnection.getScheme());
+
+ final UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(
+ userCredentials.getUsername(), userCredentials.getPassword());
+ credentialsProvider.setCredentials(authscope, usernamePasswordCredentials);
+ }
+ return credentialsProvider;
+ }
+
+ private static Timeout toTimeoutMilliseconds(int millis) {
+ if (millis < 0) {
+ LOG.info("A negative timeout has been provided. Use system default.");
+ return null;
+ }
+ return Timeout.ofMilliseconds(millis);
+ }
+
+ private static TimeValue toTimeValueMilliseconds(int millis) {
+ return TimeValue.ofMilliseconds(millis);
+ }
+
+ /**
+ * Standard HTTP Apache Client
+ *
+ * @return dataHttpClient
+ */
+ public CloseableHttpClient getHttpClient() {
+ return client;
+ }
+
+}
diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java
index 818bcb3..e51b55c 100644
--- a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java
+++ b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java
@@ -17,14 +17,27 @@
package it.eng.parer.eidas.core.bean;
+import java.io.IOException;
+
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import eu.europa.esig.dss.service.http.commons.CommonsDataLoader;
-import it.eng.parer.eidas.core.util.Constants;
public class CommonsDataLoaderExt extends CommonsDataLoader implements CustomDataLoaderExt {
private static final long serialVersionUID = -272512490031055464L;
- private String ldapTimeoutConnection = Constants.TIMEOUT_LDAP_CONNECTION;
+ private static final Logger LOG = LoggerFactory.getLogger(CommonsDataLoaderExt.class);
+
+ // ** LDAP
+
+ private String ldapTimeoutConnection = TIMEOUT_LDAP_CONNECTION;
+
+ /** The Commons HTTP dataHttpClient */
+ private CommonsDataHttpClient dataHttpClient;
/**
* Sovrascritto il metodo del padre in quanto non implementava un TIMEOUT nelle chiamate LDAP
@@ -51,4 +64,36 @@ public void setLdapTimeoutConnection(String ldapTimeoutConnection) {
this.ldapTimeoutConnection = ldapTimeoutConnection;
}
+ /* HTTP GET */
+ @Override
+ protected byte[] httpGet(String url) {
+ return customHttpGet(url);
+ }
+
+ /* HTTP POST */
+ @Override
+ public byte[] post(String url, byte[] content) {
+ return customPost(url, content);
+ }
+
+ @Override
+ public byte[] execute(CloseableHttpClient client, HttpUriRequest httpRequest) throws IOException {
+ return super.execute(client, httpRequest);
+ }
+
+ @Override
+ public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient) {
+ this.dataHttpClient = dataHttpClient;
+ }
+
+ @Override
+ public CommonsDataHttpClient getCommonsDataHttpClient() {
+ return dataHttpClient;
+ }
+
+ @Override
+ public Logger logger() {
+ return LOG;
+ }
+
}
diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java
index 3f59b73..d2d90cd 100644
--- a/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java
+++ b/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java
@@ -17,6 +17,10 @@
package it.eng.parer.eidas.core.bean;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Hashtable;
import java.util.StringTokenizer;
@@ -26,13 +30,28 @@
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.io.entity.BufferedHttpEntity;
+import org.apache.hc.core5.http.io.entity.InputStreamEntity;
+import org.slf4j.Logger;
+
import eu.europa.esig.dss.model.DSSException;
import eu.europa.esig.dss.service.http.commons.LdapURLUtils;
+import eu.europa.esig.dss.spi.DSSUtils;
import eu.europa.esig.dss.spi.exception.DSSExternalResourceException;
import eu.europa.esig.dss.utils.Utils;
public interface CustomDataLoaderExt {
+ static final String CONTENT_TYPE = "Content-Type";
+
+ static final String TIMEOUT_LDAP_CONNECTION = "6000";
+
/**
* Extendend OCSPDataLoader method, not implemented TIMEOUT on LDPA call
*
@@ -92,4 +111,89 @@ default byte[] customLdapGet(String urlString) {
public String getLdapTimeoutConnection();
+ /* CUSTOM DATA LOADING HTTP */
+
+ public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient);
+
+ public CommonsDataHttpClient getCommonsDataHttpClient();
+
+ /* apache dataHttpClient management */
+
+ default byte[] customPost(String url, byte[] content) {
+ logger().debug("Fetching data via POST from url {}", url);
+
+ HttpPost httpRequest = null;
+ // The length for the InputStreamEntity is needed, because some receivers (on
+ // the other side)
+ // need this information.
+ // To determine the length, we cannot read the content-stream up to the end and
+ // re-use it afterwards.
+ // This is because, it may not be possible to reset the stream (= go to position
+ // 0).
+ // So, the solution is to cache temporarily the complete content data (as we do
+ // not expect much here) in
+ // a byte-array.
+ try (final ByteArrayInputStream bis = new ByteArrayInputStream(content);) {
+ final URI uri = URI.create(Utils.trim(url));
+ httpRequest = new HttpPost(uri);
+
+ final HttpEntity httpEntity = new InputStreamEntity(bis, content.length,
+ toContentTypeExt(getContentType()));
+ final HttpEntity requestEntity = new BufferedHttpEntity(httpEntity);
+ httpRequest.setEntity(requestEntity);
+
+ return execute(getCommonsDataHttpClient().getHttpClient(), httpRequest);
+
+ } catch (IOException e) {
+ throw new DSSExternalResourceException(
+ String.format("Unable to process POST call for url [%s]. Reason : [%s]", url, e.getMessage()), e);
+
+ } finally {
+ if (httpRequest != null) {
+ httpRequest.cancel();
+ }
+ }
+ }
+
+ default byte[] customHttpGet(String url) {
+ HttpGet httpRequest = null;
+
+ try {
+ httpRequest = customGetHttpRequest(url);
+ return execute(getCommonsDataHttpClient().getHttpClient(), httpRequest);
+
+ } catch (URISyntaxException | IOException e) {
+ throw new DSSExternalResourceException(String.format(
+ "Unable to process GET call for url [%s]. Reason : [%s]", url, DSSUtils.getExceptionMessage(e)), e);
+
+ } finally {
+ if (httpRequest != null) {
+ httpRequest.cancel();
+ }
+ }
+ }
+
+ default HttpGet customGetHttpRequest(String url) throws URISyntaxException {
+ final URI uri = new URI(Utils.trim(url));
+ HttpGet httpRequest = new HttpGet(uri);
+ if (getContentType() != null) {
+ httpRequest.setHeader(CONTENT_TYPE, getContentType());
+ }
+ return httpRequest;
+ }
+
+ default ContentType toContentTypeExt(String contentTypeString) {
+ return Utils.isStringNotBlank(contentTypeString) ? ContentType.create(contentTypeString) : null;
+ }
+
+ public Logger logger();
+
+ /*
+ * define standard getter & setter (inherint from {@link CommonsDataLoader})
+ */
+
+ public byte[] execute(final CloseableHttpClient client, final HttpUriRequest httpRequest) throws IOException;
+
+ public String getContentType();
+
}
diff --git a/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java
index 0dee77c..10acb34 100644
--- a/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java
+++ b/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java
@@ -17,8 +17,14 @@
package it.eng.parer.eidas.core.bean;
+import java.io.IOException;
+
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import eu.europa.esig.dss.service.http.commons.OCSPDataLoader;
-import it.eng.parer.eidas.core.util.Constants;
public class OCSPDataLoaderExt extends OCSPDataLoader implements CustomDataLoaderExt {
@@ -27,7 +33,12 @@ public class OCSPDataLoaderExt extends OCSPDataLoader implements CustomDataLoade
*/
private static final long serialVersionUID = 2497778964600711396L;
- private String ldapTimeoutConnection = Constants.TIMEOUT_LDAP_CONNECTION;
+ private static final Logger LOG = LoggerFactory.getLogger(OCSPDataLoaderExt.class);
+
+ private String ldapTimeoutConnection = TIMEOUT_LDAP_CONNECTION;
+
+ /** The Commons HTTP dataHttpClient */
+ private CommonsDataHttpClient dataHttpClient;
/**
* Extendend OCSPDataLoader method, not implemented TIMEOUT on LDAP call
@@ -55,4 +66,36 @@ public void setLdapTimeoutConnection(String ldapTimeoutConnection) {
this.ldapTimeoutConnection = ldapTimeoutConnection;
}
+ /* HTTP GET */
+ @Override
+ protected byte[] httpGet(String url) {
+ return customHttpGet(url);
+ }
+
+ /* HTTP POST */
+ @Override
+ public byte[] post(String url, byte[] content) {
+ return customPost(url, content);
+ }
+
+ @Override
+ public byte[] execute(CloseableHttpClient client, HttpUriRequest httpRequest) throws IOException {
+ return super.execute(client, httpRequest);
+ }
+
+ @Override
+ public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient) {
+ this.dataHttpClient = dataHttpClient;
+ }
+
+ @Override
+ public CommonsDataHttpClient getCommonsDataHttpClient() {
+ return dataHttpClient;
+ }
+
+ @Override
+ public Logger logger() {
+ return LOG;
+ }
+
}
diff --git a/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java b/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java
index 241282f..95d024c 100644
--- a/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java
+++ b/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java
@@ -37,10 +37,8 @@
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
-import java.time.Duration;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
@@ -60,24 +58,18 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.info.BuildProperties;
import org.springframework.core.env.Environment;
-import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.client.WebClient;
import eu.europa.esig.dss.enumerations.MimeTypeEnum;
import eu.europa.esig.dss.model.DSSDocument;
import eu.europa.esig.dss.spi.DSSUtils;
-import it.eng.parer.eidas.core.util.Constants.URIClientType;
+import it.eng.parer.eidas.core.bean.CommonsDataHttpClient;
import it.eng.parer.eidas.model.EidasDataToValidateMetadata;
import it.eng.parer.eidas.model.EidasRemoteDocument;
import it.eng.parer.eidas.model.exception.EidasParerException;
import it.eng.parer.eidas.model.exception.ParerError;
-import reactor.core.publisher.Flux;
-import reactor.util.retry.Retry;
@Component
public class EidasHelper {
@@ -100,48 +92,7 @@ public class EidasHelper {
BuildProperties buildProperties;
@Autowired
- ApacheClientHelper apacheClientHelper;
-
- @Value("${parer.eidas.uriloader.client-type:httpclient}")
- URIClientType uRIClientType;
-
- /*
- * Flux+Mono config
- */
- // default 60 s
- @Value("${parer.eidas.uriloader.webclient.timeout:60}")
- long webClientTimeout;
-
- // default 5 times
- @Value("${parer.eidas.uriloader.webclient.backoff:5}")
- long webClientBackoff;
-
- // default 3 s
- @Value("${parer.eidas.uriloader.webclient.backofftime:3}")
- long webClientBackoffTime;
-
- /*
- * Standard httpclient
- */
- // default 60 s
- @Value("${parer.eidas.uriloader.httpclient.timeout:60}")
- long httpClientTimeout;
-
- // default 60 s
- @Value("${parer.eidas.uriloader.httpclient.timeoutsocket:60}")
- int httpClientSocketTimeout;
-
- // default 4
- @Value("${parer.eidas.uriloader.httpclient.connectionsmaxperroute:4}")
- int httpClientConnectionsmaxperroute;
-
- // default 40
- @Value("${parer.eidas.uriloader.httpclient.connectionsmax:40}")
- int httpClientConnectionsmax;
-
- // default 60s
- @Value("${parer.eidas.uriloader.httpclient.timetolive:60}")
- long httpClientTimeToLive;
+ CommonsDataHttpClient dataHttpClient;
public String buildversion() {
return env.getProperty(BUILD_VERSION);
@@ -420,37 +371,11 @@ private Path readBase64EncodedFile(String prefix, InputStream is) throws IOExcep
}
public void getResourceFromURI(URI signedResource, Path localPath) throws IOException {
- if (uRIClientType.equals(URIClientType.HTTPCLIENT)) {
- getWithCommonHttpclient(signedResource, localPath);
- } else {
- getWithWebClient(signedResource, localPath);
- }
- }
-
- private void getWithWebClient(URI signedResource, Path localPath) throws IOException {
- try {
- // Attenzione, se al posto dell'uri viene utilizzata una stringa ci possono
- // essere problemi di conversione
- // dei
- // caratteri
- Flux dataBuffer = WebClient.create().get().uri(signedResource).retrieve()
- .bodyToFlux(DataBuffer.class);
- // scarica sul local path provando 5 volte aspettando almeno 3 secondi tra un
- // prova e l'altra
- DataBufferUtils.write(dataBuffer, localPath).timeout(Duration.ofSeconds(webClientTimeout))
- .retryWhen(Retry.backoff(webClientBackoff, Duration.ofSeconds(webClientBackoffTime))).share()
- .block();
- } catch (Exception ex) {
- throw new IOException("Impossibile recuperare il documento da URI", ex);
- }
- }
-
- private void getWithCommonHttpclient(URI signedResource, Path localPath) throws IOException {
- try (ClassicHttpResponse response = apacheClientHelper.client().executeOpen(null, new HttpGet(signedResource),
- null); FileOutputStream out = new FileOutputStream(localPath.toFile());) {
+ try (ClassicHttpResponse response = dataHttpClient.getHttpClient().executeOpen(null,
+ new HttpGet(signedResource), null); FileOutputStream out = new FileOutputStream(localPath.toFile());) {
//
- IOUtils.copy(response.getEntity().getContent(), out);
+ IOUtils.copyLarge(response.getEntity().getContent(), out);
}
}
diff --git a/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java b/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java
index 11fbd23..857a359 100644
--- a/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java
+++ b/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java
@@ -511,7 +511,7 @@ private EidasWSReportsDTOTree createRoot(DSSDocument signedDocument, Reports rep
/**
* Vedi issue https://gitlab.ente.regione.emr.it/parer/okd/verifica-firma-eidas/issues/7
*
- * Per il momento il validation report non viene restituito al client
+ * Per il momento il validation report non viene restituito al dataHttpClient
*/
WSReportsDTO wsdto = new WSReportsDTO(reports.getDiagnosticDataJaxb(), reports.getSimpleReportJaxb(),
reports.getDetailedReportJaxb());
diff --git a/src/main/java/it/eng/parer/eidas/core/util/Constants.java b/src/main/java/it/eng/parer/eidas/core/util/Constants.java
index 557c805..91e7d0a 100644
--- a/src/main/java/it/eng/parer/eidas/core/util/Constants.java
+++ b/src/main/java/it/eng/parer/eidas/core/util/Constants.java
@@ -37,9 +37,6 @@ private Constants() {
public static final String BUILD_TIME = "git.commit.time";
public static final String DSS_VERSION = "dss.version";
- /* default configuration */
- public static final String TIMEOUT_LDAP_CONNECTION = "6000";
-
public static final String TMP_FILE_SUFFIX = "-eidasvf.tmp";
/* default error message on advice handler */
diff --git a/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java b/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java
index 467a38a..035c9bf 100644
--- a/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java
+++ b/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java
@@ -54,8 +54,8 @@ public class AdviceHandler {
/*
* Aggiunto log al fine di loggare i casi di generiche eccezioni ossia generate dopo l'esecuzione del servizio di
- * verifica firma (o prima quando si valuta la risposta del client), ma che comunque in generale non sono gestite
- * (EidasParerException) all'interno dell'implementazione dell'endpoint.
+ * verifica firma (o prima quando si valuta la risposta del dataHttpClient), ma che comunque in generale non sono
+ * gestite (EidasParerException) all'interno dell'implementazione dell'endpoint.
*/
private static final Logger log = LoggerFactory.getLogger(AdviceHandler.class);
diff --git a/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java b/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java
index a178a4d..184963d 100644
--- a/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java
+++ b/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java
@@ -91,7 +91,7 @@ public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter()
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(
mapper);
- // Aggiungo i media type text/plain per supportare client come jmeter
+ // Aggiungo i media type text/plain per supportare dataHttpClient come jmeter
List supportedMediaTypes = new ArrayList<>(
mappingJackson2HttpMessageConverter.getSupportedMediaTypes());
supportedMediaTypes.add(new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8));
diff --git a/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java b/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java
index 2906d01..28220ce 100644
--- a/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java
+++ b/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java
@@ -78,6 +78,7 @@
import eu.europa.esig.dss.ws.signature.common.RemoteTrustedListSignatureServiceImpl;
import eu.europa.esig.dss.ws.validation.common.RemoteDocumentValidationService;
import eu.europa.esig.dss.xades.signature.XAdESService;
+import it.eng.parer.eidas.core.bean.CommonsDataHttpClient;
import it.eng.parer.eidas.core.bean.CommonsDataLoaderExt;
import it.eng.parer.eidas.core.bean.OCSPDataLoaderExt;
import it.eng.parer.eidas.core.service.CustomRemoteDocumentValidationImpl;
@@ -160,12 +161,12 @@ public class DSSBeanConfig {
@Value("${revoke.removeExpired.enabled:true}")
private boolean revokeRemoveExpired;
- /* in ms */
- @Value("${dataloader.timeoutconnection:120000}")
+ /* in ms (5m) */
+ @Value("${dataloader.timeoutconnection:300000}")
private int timeoutConnection;
- /* in ms */
- @Value("${dataloader.timeoutsocket:120000}")
+ /* in ms (5m) */
+ @Value("${dataloader.timeoutsocket:300000}")
private int timeoutSocket;
@Value("${dataloader.connectionsmaxtotal:40}")
@@ -174,12 +175,12 @@ public class DSSBeanConfig {
@Value("${dataloader.connectionsmaxperroute:4}")
private int connectionsMaxPerRoute;
- /* in ms */
- @Value("${dataloader.connectiontimetolive:120000}")
+ /* in ms (5m) */
+ @Value("${dataloader.connectiontimetolive:300000}")
private int connectionTimeToLive;
- /* in ms */
- @Value("${dataloader.ldaptimeoutconnection:120000}")
+ /* in ms (5m) */
+ @Value("${dataloader.ldaptimeoutconnection:300000}")
private String ldapTimeoutConnection;
@Value("${cache.enabled:true}")
@@ -189,17 +190,26 @@ public class DSSBeanConfig {
@Value("${cache.file.path:}")
private String cacheFilePath;
+ /** CUSTOM HTTP CLIENT ! **/
+ @Bean(initMethod = "init", destroyMethod = "destroy")
+ public CommonsDataHttpClient dataHttpClient() {
+ CommonsDataHttpClient dataClient = new CommonsDataHttpClient();
+ // NOTA timeout impostabile (da configurazione!)
+ dataClient.setTimeoutConnection(timeoutConnection);
+ dataClient.setConnectionsMaxTotal(connectionsMaxTotal);
+ dataClient.setTimeoutSocket(timeoutSocket);
+ //
+ dataClient.setConnectionsMaxPerRoute(connectionsMaxPerRoute);
+ dataClient.setConnectionTimeToLive(connectionTimeToLive);
+ //
+ return dataClient;
+ }
+
@Bean
public CommonsDataLoaderExt dataLoader() {
CommonsDataLoaderExt dataLoader = new CommonsDataLoaderExt();
+ dataLoader.setCommonsDataHttpClient(dataHttpClient());
dataLoader.setProxyConfig(proxyConfig);
- // NOTA timeout impostabile (da configurazione!)
- dataLoader.setTimeoutConnection(timeoutConnection);
- dataLoader.setConnectionsMaxTotal(connectionsMaxTotal);
- dataLoader.setTimeoutSocket(timeoutSocket);
- //
- dataLoader.setConnectionsMaxPerRoute(connectionsMaxPerRoute);
- dataLoader.setConnectionTimeToLive(connectionTimeToLive);
//
dataLoader.setLdapTimeoutConnection(ldapTimeoutConnection);
return dataLoader;
@@ -208,14 +218,8 @@ public CommonsDataLoaderExt dataLoader() {
@Bean
public OCSPDataLoaderExt ocspDataLoader() {
OCSPDataLoaderExt ocspDataLoader = new OCSPDataLoaderExt();
+ ocspDataLoader.setCommonsDataHttpClient(dataHttpClient());
ocspDataLoader.setProxyConfig(proxyConfig);
- // NOTA timeout impostabile (da configurazione!)
- ocspDataLoader.setTimeoutConnection(timeoutConnection);
- ocspDataLoader.setConnectionsMaxTotal(connectionsMaxTotal);
- ocspDataLoader.setTimeoutSocket(timeoutSocket);
- //
- ocspDataLoader.setConnectionsMaxPerRoute(connectionsMaxPerRoute);
- //
ocspDataLoader.setLdapTimeoutConnection(ldapTimeoutConnection);
return ocspDataLoader;
}
@@ -570,7 +574,8 @@ public TLValidationJob job() {
/* from 5.8 */
@Bean
public CommonsDataLoader trustAllDataLoader() {
- CommonsDataLoader dataLoader = new CommonsDataLoader();
+ CommonsDataLoaderExt dataLoader = new CommonsDataLoaderExt();
+ dataLoader.setCommonsDataHttpClient(dataHttpClient());
dataLoader.setProxyConfig(proxyConfig);
dataLoader.setTrustStrategy(new TrustAllStrategy());
return dataLoader;