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

Commit 6f9eb50

Browse files
committed
Merge remote-tracking branch 'origin/issues/32_GECCO_FHIR_Server_https'
into develop
2 parents ca44b62 + 805293b commit 6f9eb50

21 files changed

Lines changed: 730 additions & 846 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: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ public void testConnection()
8080
private final Path trustStorePath;
8181
private final Path certificatePath;
8282
private final Path privateKeyPath;
83+
private final char[] privateKeyPassword;
84+
85+
private final int connectTimeout;
86+
private final int socketTimeout;
87+
private final int connectionRequestTimeout;
8388

8489
private final String fttpServerBase;
8590
private final String fttpBasicAuthUsername;
@@ -89,24 +94,21 @@ public void testConnection()
8994
private final String fttpStudy;
9095
private final String fttpTarget;
9196

92-
private final int connectTimeout;
93-
private final int socketTimeout;
94-
private final int connectionRequestTimeout;
95-
96-
private final String proxySchemeHostPort;
97+
private final String proxyUrl;
9798
private final String proxyUsername;
9899
private final String proxyPassword;
99100

100101
private final boolean hapiClientVerbose;
101102

102-
public FttpClientFactory(Path trustStorePath, Path certificatePath, Path privateKeyPath, int connectTimeout,
103-
int socketTimeout, int connectionRequestTimeout, String fttpBasicAuthUsername, String fttpBasicAuthPassword,
104-
String fttpServerBase, String fttpApiKey, String fttpStudy, String fttpTarget, String proxySchemeHostPort,
105-
String proxyUsername, String proxyPassword, boolean hapiClientVerbose)
103+
public FttpClientFactory(Path trustStorePath, Path certificatePath, Path privateKeyPath, char[] privateKeyPassword,
104+
int connectTimeout, int socketTimeout, int connectionRequestTimeout, String fttpBasicAuthUsername,
105+
String fttpBasicAuthPassword, String fttpServerBase, String fttpApiKey, String fttpStudy, String fttpTarget,
106+
String proxyUrl, String proxyUsername, String proxyPassword, boolean hapiClientVerbose)
106107
{
107108
this.trustStorePath = trustStorePath;
108109
this.certificatePath = certificatePath;
109110
this.privateKeyPath = privateKeyPath;
111+
this.privateKeyPassword = privateKeyPassword;
110112

111113
this.connectTimeout = connectTimeout;
112114
this.socketTimeout = socketTimeout;
@@ -120,7 +122,7 @@ public FttpClientFactory(Path trustStorePath, Path certificatePath, Path private
120122
this.fttpStudy = fttpStudy;
121123
this.fttpTarget = fttpTarget;
122124

123-
this.proxySchemeHostPort = proxySchemeHostPort;
125+
this.proxyUrl = proxyUrl;
124126
this.proxyUsername = proxyUsername;
125127
this.proxyPassword = proxyPassword;
126128

@@ -133,8 +135,11 @@ public void onContextRefreshedEvent(ContextRefreshedEvent event)
133135
try
134136
{
135137
logger.info(
136-
"Testing connection to fTTP with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, fttpServerBase: {}, fttpApiKey: {}, fttpStudy: {}, fttpTarget: {}}",
137-
trustStorePath, certificatePath, privateKeyPath, fttpServerBase, fttpApiKey, fttpStudy, fttpTarget);
138+
"Testing connection to fTTP with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {},"
139+
+ " basicAuthUsername {}, basicAuthPassword {}, serverBase: {}, apiKey: {}, study: {}, target: {}, proxyUrl {}, proxyUsername, proxyPassword {}}",
140+
trustStorePath, certificatePath, privateKeyPath, privateKeyPassword != null ? "***" : "null",
141+
fttpBasicAuthUsername, fttpBasicAuthPassword != null ? "***" : "null", fttpServerBase, fttpApiKey,
142+
fttpStudy, fttpTarget, proxyUrl, proxyUsername, proxyPassword != null ? "***" : "null");
138143

139144
getFttpClient().testConnection();
140145
}
@@ -166,11 +171,11 @@ protected FttpClient createFttpClient()
166171
char[] keyStorePassword = UUID.randomUUID().toString().toCharArray();
167172

168173
logger.debug("Creating key-store from {} and {}", certificatePath.toString(), privateKeyPath.toString());
169-
KeyStore keyStore = readKeyStore(certificatePath, privateKeyPath, keyStorePassword);
174+
KeyStore keyStore = readKeyStore(certificatePath, privateKeyPath, privateKeyPassword, keyStorePassword);
170175

171176
return new FttpClientImpl(trustStore, keyStore, keyStorePassword, connectTimeout, socketTimeout,
172177
connectionRequestTimeout, fttpBasicAuthUsername, fttpBasicAuthPassword, fttpServerBase, fttpApiKey,
173-
fttpStudy, fttpTarget, proxySchemeHostPort, proxyUsername, proxyPassword, hapiClientVerbose);
178+
fttpStudy, fttpTarget, proxyUrl, proxyUsername, proxyPassword, hapiClientVerbose);
174179
}
175180

176181
private KeyStore readTrustStore(Path trustPath)
@@ -185,11 +190,11 @@ private KeyStore readTrustStore(Path trustPath)
185190
}
186191
}
187192

188-
private KeyStore readKeyStore(Path certificatePath, Path keyPath, char[] keyStorePassword)
193+
private KeyStore readKeyStore(Path certificatePath, Path keyPath, char[] keyPassword, char[] keyStorePassword)
189194
{
190195
try
191196
{
192-
PrivateKey privateKey = PemIo.readPrivateKeyFromPem(keyPath);
197+
PrivateKey privateKey = PemIo.readPrivateKeyFromPem(keyPath, keyPassword);
193198
X509Certificate certificate = PemIo.readX509CertificateFromPem(certificatePath);
194199

195200
return CertificateHelper.toJksKeyStore(privateKey, new Certificate[] { certificate },

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

Lines changed: 8 additions & 17 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

@@ -49,21 +48,22 @@ public class FttpClientImpl implements FttpClient, InitializingBean
4948

5049
public FttpClientImpl(KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, int connectTimeout,
5150
int socketTimeout, int connectionRequestTimeout, String fttpBasicAuthUsername, String fttpBasicAuthPassword,
52-
String fttpServerBase, String fttpApiKey, String fttpStudy, String fttpTarget, String proxySchemeHostPort,
51+
String fttpServerBase, String fttpApiKey, String fttpStudy, String fttpTarget, String proxyUrl,
5352
String proxyUsername, String proxyPassword, boolean hapiClientVerbose)
5453
{
5554
clientFactory = createClientFactory(trustStore, keyStore, keyStorePassword, connectTimeout, socketTimeout,
5655
connectionRequestTimeout);
5756

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

6262
this.fttpApiKey = fttpApiKey;
6363
this.fttpStudy = fttpStudy;
6464
this.fttpTarget = fttpTarget;
6565

66-
configureProxy(clientFactory, proxySchemeHostPort, proxyUsername, proxyPassword);
66+
configureProxy(clientFactory, proxyUrl, proxyUsername, proxyPassword);
6767

6868
this.hapiClientVerbose = hapiClientVerbose;
6969
}
@@ -88,14 +88,14 @@ protected ApacheRestfulClientFactoryWithTlsConfig createClientFactory(KeyStore t
8888
return hapiClientFactory;
8989
}
9090

91-
private void configureProxy(IRestfulClientFactory clientFactory, String proxySchemeHostPort, String proxyUsername,
91+
private void configureProxy(IRestfulClientFactory clientFactory, String proxyUrl, String proxyUsername,
9292
String proxyPassword)
9393
{
94-
if (StringUtils.isNotBlank(proxySchemeHostPort))
94+
if (proxyUrl != null && !proxyUrl.isBlank())
9595
{
9696
try
9797
{
98-
URL url = new URL(proxySchemeHostPort);
98+
URL url = new URL(proxyUrl);
9999
clientFactory.setProxy(url.getHost(), url.getPort());
100100
clientFactory.setProxyCredentials(proxyUsername, proxyPassword);
101101

@@ -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)