Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit 7edc0d8

Browse files
committed
reworked gecco client creation, added support for tls and encrypted keys
The private key for the fTTP connection can now be encrypted The connection to the GECCO FHIR server can now use tls with optional client certificate authentication. Connections to fTTP and GECCo FHIR server can use forwarding proxies. closes #32
1 parent 0845374 commit 7edc0d8

21 files changed

Lines changed: 706 additions & 830 deletions

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/ApacheRestfulClientFactoryWithTlsConfig.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.security.KeyStoreException;
66
import java.security.NoSuchAlgorithmException;
77
import java.security.UnrecoverableKeyException;
8+
import java.util.HashMap;
89
import java.util.List;
910
import java.util.Map;
1011
import java.util.concurrent.TimeUnit;
@@ -28,6 +29,7 @@
2829
import org.apache.http.impl.client.HttpClients;
2930
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
3031
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
32+
import org.apache.http.ssl.SSLContextBuilder;
3133
import org.apache.http.ssl.SSLContexts;
3234
import org.slf4j.Logger;
3335
import org.slf4j.LoggerFactory;
@@ -50,6 +52,8 @@ public class ApacheRestfulClientFactoryWithTlsConfig extends RestfulClientFactor
5052
private final KeyStore keyStore;
5153
private final char[] keyStorePassword;
5254

55+
private final Map<String, ApacheHttpClient> clientByServerBase = new HashMap<>();
56+
5357
public ApacheRestfulClientFactoryWithTlsConfig(FhirContext fhirContext, KeyStore trustStore, KeyStore keyStore,
5458
char[] keyStorePassword)
5559
{
@@ -61,11 +65,21 @@ public ApacheRestfulClientFactoryWithTlsConfig(FhirContext fhirContext, KeyStore
6165
}
6266

6367
@Override
64-
protected synchronized ApacheHttpClient getHttpClient(String theServerBase)
68+
protected synchronized ApacheHttpClient getHttpClient(String serverBase)
6569
{
66-
logger.info("Returning new ApacheHttpClient for ServerBase {}", theServerBase);
67-
68-
return new ApacheHttpClient(getNativeHttpClient(), new StringBuilder(theServerBase), null, null, null, null);
70+
if (clientByServerBase.containsKey(serverBase))
71+
{
72+
logger.debug("Reusing ApacheHttpClient for ServerBase {}", serverBase);
73+
return clientByServerBase.get(serverBase);
74+
}
75+
else
76+
{
77+
logger.debug("Returning new ApacheHttpClient for ServerBase {}", serverBase);
78+
ApacheHttpClient client = new ApacheHttpClient(getNativeHttpClient(), new StringBuilder(serverBase), null,
79+
null, null, null);
80+
clientByServerBase.put(serverBase, client);
81+
return client;
82+
}
6983
}
7084

7185
@Override
@@ -119,8 +133,14 @@ protected SSLContext getSslContext()
119133
{
120134
try
121135
{
122-
return SSLContexts.custom().loadTrustMaterial(trustStore, null).loadKeyMaterial(keyStore, keyStorePassword)
123-
.build();
136+
SSLContextBuilder custom = SSLContexts.custom();
137+
138+
if (trustStore != null)
139+
custom = custom.loadTrustMaterial(trustStore, null);
140+
if (keyStore != null && keyStorePassword != null)
141+
custom = custom.loadKeyMaterial(keyStore, keyStorePassword);
142+
143+
return custom.build();
124144
}
125145
catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException e)
126146
{

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientFactory.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ public void testConnection()
8282
private final Path privateKeyPath;
8383
private final char[] privateKeyPassword;
8484

85+
private final int connectTimeout;
86+
private final int socketTimeout;
87+
private final int connectionRequestTimeout;
88+
8589
private final String fttpServerBase;
8690
private final String fttpBasicAuthUsername;
8791
private final String fttpBasicAuthPassword;
@@ -90,10 +94,6 @@ public void testConnection()
9094
private final String fttpStudy;
9195
private final String fttpTarget;
9296

93-
private final int connectTimeout;
94-
private final int socketTimeout;
95-
private final int connectionRequestTimeout;
96-
9797
private final String proxySchemeHostPort;
9898
private final String proxyUsername;
9999
private final String proxyPassword;
@@ -135,9 +135,10 @@ public void onContextRefreshedEvent(ContextRefreshedEvent event)
135135
try
136136
{
137137
logger.info(
138-
"Testing connection to fTTP with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {}, fttpServerBase: {}, fttpApiKey: {}, fttpStudy: {}, fttpTarget: {}}",
138+
"Testing connection to fTTP with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {}, fttpBasicAuthUsername {}, fttpBasicAuthPassword {}, fttpServerBase: {}, fttpApiKey: {}, fttpStudy: {}, fttpTarget: {}}",
139139
trustStorePath, certificatePath, privateKeyPath, privateKeyPassword != null ? "***" : "null",
140-
fttpServerBase, fttpApiKey, fttpStudy, fttpTarget);
140+
fttpBasicAuthUsername, fttpBasicAuthPassword != null ? "***" : "null", fttpServerBase, fttpApiKey,
141+
fttpStudy, fttpTarget);
141142

142143
getFttpClient().testConnection();
143144
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,13 @@
1010
import java.util.regex.Matcher;
1111
import java.util.regex.Pattern;
1212

13-
import org.apache.commons.lang3.StringUtils;
1413
import org.hl7.fhir.r4.model.Base64BinaryType;
1514
import org.hl7.fhir.r4.model.CapabilityStatement;
1615
import org.hl7.fhir.r4.model.Identifier;
1716
import org.hl7.fhir.r4.model.Parameters;
1817
import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
1918
import org.slf4j.Logger;
2019
import org.slf4j.LoggerFactory;
21-
import org.springframework.beans.factory.InitializingBean;
2220

2321
import ca.uhn.fhir.context.FhirContext;
2422
import ca.uhn.fhir.rest.api.Constants;
@@ -29,7 +27,7 @@
2927
import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
3028
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
3129

32-
public class FttpClientImpl implements FttpClient, InitializingBean
30+
public class FttpClientImpl implements FttpClient
3331
{
3432
private static final Logger logger = LoggerFactory.getLogger(FttpClientImpl.class);
3533

@@ -38,6 +36,7 @@ public class FttpClientImpl implements FttpClient, InitializingBean
3836
private final IRestfulClientFactory clientFactory;
3937

4038
private final String fttpServerBase;
39+
4140
private final String fttpBasicAuthUsername;
4241
private final String fttpBasicAuthPassword;
4342

@@ -56,6 +55,7 @@ public FttpClientImpl(KeyStore trustStore, KeyStore keyStore, char[] keyStorePas
5655
connectionRequestTimeout);
5756

5857
this.fttpServerBase = fttpServerBase;
58+
5959
this.fttpBasicAuthUsername = fttpBasicAuthUsername;
6060
this.fttpBasicAuthPassword = fttpBasicAuthPassword;
6161

@@ -91,7 +91,7 @@ protected ApacheRestfulClientFactoryWithTlsConfig createClientFactory(KeyStore t
9191
private void configureProxy(IRestfulClientFactory clientFactory, String proxySchemeHostPort, String proxyUsername,
9292
String proxyPassword)
9393
{
94-
if (StringUtils.isNotBlank(proxySchemeHostPort))
94+
if (proxySchemeHostPort != null && !proxySchemeHostPort.isBlank())
9595
{
9696
try
9797
{
@@ -109,15 +109,6 @@ private void configureProxy(IRestfulClientFactory clientFactory, String proxySch
109109
}
110110
}
111111

112-
@Override
113-
public void afterPropertiesSet() throws Exception
114-
{
115-
Objects.requireNonNull(fttpServerBase, "fttpServerBase");
116-
Objects.requireNonNull(fttpApiKey, "fttpApiKey");
117-
Objects.requireNonNull(fttpStudy, "fttpStudy");
118-
Objects.requireNonNull(fttpTarget, "fttpTarget");
119-
}
120-
121112
@Override
122113
public Optional<String> getCrrPseudonym(String dicSourceAndPseudonym)
123114
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client;
2+
3+
import java.nio.file.Path;
4+
5+
import ca.uhn.fhir.context.FhirContext;
6+
import ca.uhn.fhir.rest.client.api.IGenericClient;
7+
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.GeccoFhirClient;
8+
9+
public interface GeccoClient
10+
{
11+
FhirContext getFhirContext();
12+
13+
void testConnection();
14+
15+
GeccoFhirClient getFhirClient();
16+
17+
Path getSearchBundleOverride();
18+
19+
IGenericClient getGenericFhirClient();
20+
21+
String getLocalIdentifierValue();
22+
23+
boolean shouldUseChainedParameterNotLogicalReference();
24+
}

0 commit comments

Comments
 (0)