3776 add https support for hapi fhir cli using tls (#3777)
* wip functional
TODO
- add tests
- look at adding TLS to other RestfulClientFactory classes (FhirwebRestfulClientFactory, JaxRsRestfulClientFactory, OkHttpRestfulClientFactory)
* move BaseRestServerHelper to Hapi-Fhir
* - add TLS support for JaxRsClient and OkHttpClient
- add tests
* - to use resources and files
* - ci fixes
* - ci fixes
* - ci fixes
* - ci fixes
* - refactor and tests
* - ci fixes
* - tests
* - tests
* - tests / refactor
* - clean up
* - changelog
* - remove OkHttpClient HTTPS support
* - ci
* - Ken's code review changes
* - Ken's code review: method renaming
* - Ken's code review: javadoc
* - Code coverage
* - Create HapiFhirCliRestfulClientFactory to encapsulate new HTTPS functionality. Remove modifications to the FhirContext API.
* - version bump
* - fix unable to bind port errors by using Jetty functionality to assign random ports
* Revert "- version bump"
This reverts commit cfce82576a
.
* - version bump
Co-authored-by: nathaniel.doef <nathaniel.doef@smilecdr.com>
This commit is contained in:
parent
8740c10ed9
commit
e2bed96d74
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import ca.uhn.fhir.util.VersionUtil;
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
|
@ -888,8 +889,8 @@ public class FhirContext {
|
||||||
* {@link #newRestfulClient(Class, String) non-generic clients}).
|
* {@link #newRestfulClient(Class, String) non-generic clients}).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every operation invocation
|
* Performance Note: This method performs an additional GET request to /metadata before
|
||||||
* without incurring any performance penalty
|
* the desired request is performed.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theServerBase The URL of the base for the restful FHIR server to connect to
|
* @param theServerBase The URL of the base for the restful FHIR server to connect to
|
||||||
|
|
|
@ -25,7 +25,7 @@ public final class Msg {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMPORTANT: Please update the following comment after you add a new code
|
* IMPORTANT: Please update the following comment after you add a new code
|
||||||
* Last code value: 2109
|
* Last code value: 2123
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private Msg() {}
|
private Msg() {}
|
||||||
|
|
|
@ -20,12 +20,12 @@ package ca.uhn.fhir.rest.client.api;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface IRestfulClientFactory {
|
public interface IRestfulClientFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class KeyStoreInfo extends StoreInfo {
|
||||||
|
|
||||||
|
private final char[] myKeyPass;
|
||||||
|
|
||||||
|
public KeyStoreInfo(String theFilePath, String theStorePass, String theKeyPass, String theAlias) {
|
||||||
|
super(theFilePath, theStorePass, theAlias);
|
||||||
|
this.myKeyPass = toCharArray(theKeyPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getKeyPass() {
|
||||||
|
return myKeyPass;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum KeyStoreType {
|
||||||
|
|
||||||
|
PKCS12("p12", "pfx"),
|
||||||
|
JKS("jks");
|
||||||
|
|
||||||
|
private List<String> myFileExtensions;
|
||||||
|
|
||||||
|
KeyStoreType(String... theFileExtensions){
|
||||||
|
myFileExtensions = Arrays.asList(theFileExtensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFileExtensions() {
|
||||||
|
return myFileExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyStoreType fromFileExtension(String theFileExtension) {
|
||||||
|
for(KeyStoreType type : KeyStoreType.values()){
|
||||||
|
if(type.getFileExtensions().contains(theFileExtension.toLowerCase())){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(Msg.code(2121)+"Invalid KeyStore Type");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public enum PathType {
|
||||||
|
|
||||||
|
FILE("file://"),
|
||||||
|
RESOURCE("classpath:");
|
||||||
|
|
||||||
|
private String myPrefix;
|
||||||
|
|
||||||
|
PathType(String thePrefix) {
|
||||||
|
myPrefix = thePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefix(){
|
||||||
|
return myPrefix;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
public abstract class StoreInfo {
|
||||||
|
|
||||||
|
private final String myFilePath;
|
||||||
|
private final PathType myPathType;
|
||||||
|
private final char[] myStorePass;
|
||||||
|
private final String myAlias;
|
||||||
|
private final KeyStoreType myType;
|
||||||
|
|
||||||
|
public StoreInfo(String theFilePath, String theStorePass, String theAlias) {
|
||||||
|
if(theFilePath.startsWith(PathType.RESOURCE.getPrefix())){
|
||||||
|
myFilePath = theFilePath.substring(PathType.RESOURCE.getPrefix().length());
|
||||||
|
myPathType = PathType.RESOURCE;
|
||||||
|
}
|
||||||
|
else if(theFilePath.startsWith(PathType.FILE.getPrefix())){
|
||||||
|
myFilePath = theFilePath.substring(PathType.FILE.getPrefix().length());
|
||||||
|
myPathType = PathType.FILE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new StoreInfoException(Msg.code(2117)+"Invalid path prefix");
|
||||||
|
}
|
||||||
|
|
||||||
|
myStorePass = toCharArray(theStorePass);
|
||||||
|
myAlias = theAlias;
|
||||||
|
|
||||||
|
String extension = FilenameUtils.getExtension(theFilePath);
|
||||||
|
myType = KeyStoreType.fromFileExtension(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath() {
|
||||||
|
return myFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getStorePass() {
|
||||||
|
return myStorePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return myAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyStoreType getType() {
|
||||||
|
return myType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathType getPathType() {
|
||||||
|
return myPathType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected char[] toCharArray(String theString){
|
||||||
|
return isBlank(theString) ? "".toCharArray() : theString.toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StoreInfoException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1l;
|
||||||
|
public StoreInfoException(String theMessage) {
|
||||||
|
super(theMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class TlsAuthentication {
|
||||||
|
|
||||||
|
private final Optional<KeyStoreInfo> myKeyStoreInfo;
|
||||||
|
private final Optional<TrustStoreInfo> myTrustStoreInfo;
|
||||||
|
|
||||||
|
public TlsAuthentication(Optional<KeyStoreInfo> theKeyStoreInfo, Optional<TrustStoreInfo> theTrustStoreInfo) {
|
||||||
|
myKeyStoreInfo = theKeyStoreInfo;
|
||||||
|
myTrustStoreInfo = theTrustStoreInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<KeyStoreInfo> getKeyStoreInfo() {
|
||||||
|
return myKeyStoreInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<TrustStoreInfo> getTrustStoreInfo() {
|
||||||
|
return myTrustStoreInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package ca.uhn.fhir.tls;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TrustStoreInfo extends StoreInfo{
|
||||||
|
|
||||||
|
public TrustStoreInfo(String theFilePath, String theStorePass, String theAlias) {
|
||||||
|
super(theFilePath, theStorePass, theAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-bom</artifactId>
|
<artifactId>hapi-fhir-bom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>HAPI FHIR BOM</name>
|
<name>HAPI FHIR BOM</name>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,21 @@ package ca.uhn.fhir.cli;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.cli.client.HapiFhirCliRestfulClientFactory;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.TrustStoreInfo;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.Option;
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.OptionGroup;
|
import org.apache.commons.cli.OptionGroup;
|
||||||
|
@ -56,6 +63,7 @@ import java.io.Console;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
@ -65,6 +73,7 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
@ -80,6 +89,9 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
||||||
protected static final String BASE_URL_PARAM_LONGOPT = "target";
|
protected static final String BASE_URL_PARAM_LONGOPT = "target";
|
||||||
protected static final String BASE_URL_PARAM_NAME = "target";
|
protected static final String BASE_URL_PARAM_NAME = "target";
|
||||||
protected static final String BASE_URL_PARAM_DESC = "Base URL for the target server (e.g. \"http://example.com/fhir\").";
|
protected static final String BASE_URL_PARAM_DESC = "Base URL for the target server (e.g. \"http://example.com/fhir\").";
|
||||||
|
protected static final String TLS_AUTH_PARAM_LONGOPT = "tls-auth";
|
||||||
|
protected static final String TLS_AUTH_PARAM_NAME = "tls-auth";
|
||||||
|
protected static final String TLS_AUTH_PARAM_DESC = "If specified, this parameter supplies a path and filename for a json authentication file that will be used to authenticate HTTPS requests.";
|
||||||
protected static final String BASIC_AUTH_PARAM = "b";
|
protected static final String BASIC_AUTH_PARAM = "b";
|
||||||
protected static final String BASIC_AUTH_PARAM_LONGOPT = "basic-auth";
|
protected static final String BASIC_AUTH_PARAM_LONGOPT = "basic-auth";
|
||||||
protected static final String BASIC_AUTH_PARAM_NAME = "basic-auth";
|
protected static final String BASIC_AUTH_PARAM_NAME = "basic-auth";
|
||||||
|
@ -118,6 +130,10 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
||||||
addOptionalOption(theOptions, null, THREAD_COUNT, "count", "If specified, this argument specifies the number of worker threads used (default is " + DEFAULT_THREAD_COUNT + ")");
|
addOptionalOption(theOptions, null, THREAD_COUNT, "count", "If specified, this argument specifies the number of worker threads used (default is " + DEFAULT_THREAD_COUNT + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addHttpsAuthOption(Options theOptions){
|
||||||
|
addOptionalOption(theOptions, null, TLS_AUTH_PARAM_LONGOPT, TLS_AUTH_PARAM_NAME, TLS_AUTH_PARAM_DESC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String promptUser(String thePrompt) throws ParseException {
|
protected String promptUser(String thePrompt) throws ParseException {
|
||||||
System.out.print(ansi().bold().fgBrightDefault());
|
System.out.print(ansi().bold().fgBrightDefault());
|
||||||
|
@ -457,10 +473,11 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IGenericClient newClient(CommandLine theCommandLine) throws ParseException {
|
protected IGenericClient newClient(CommandLine theCommandLine) throws ParseException {
|
||||||
return newClient(theCommandLine, BASE_URL_PARAM, BASIC_AUTH_PARAM, BEARER_TOKEN_PARAM_LONGOPT);
|
return newClient(theCommandLine, BASE_URL_PARAM, BASIC_AUTH_PARAM, BEARER_TOKEN_PARAM_LONGOPT, TLS_AUTH_PARAM_LONGOPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IGenericClient newClient(CommandLine theCommandLine, String theBaseUrlParamName, String theBasicAuthOptionName, String theBearerTokenOptionName) throws ParseException {
|
protected IGenericClient newClient(CommandLine theCommandLine, String theBaseUrlParamName, String theBasicAuthOptionName,
|
||||||
|
String theBearerTokenOptionName, String theTlsAuthOptionName) throws ParseException {
|
||||||
String baseUrl = theCommandLine.getOptionValue(theBaseUrlParamName);
|
String baseUrl = theCommandLine.getOptionValue(theBaseUrlParamName);
|
||||||
if (isBlank(baseUrl)) {
|
if (isBlank(baseUrl)) {
|
||||||
throw new ParseException(Msg.code(1579) + "No target server (-" + BASE_URL_PARAM + ") specified.");
|
throw new ParseException(Msg.code(1579) + "No target server (-" + BASE_URL_PARAM + ") specified.");
|
||||||
|
@ -468,10 +485,18 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
||||||
throw new ParseException(Msg.code(1580) + "Invalid target server specified, must begin with 'http' or 'file'.");
|
throw new ParseException(Msg.code(1580) + "Invalid target server specified, must begin with 'http' or 'file'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return newClientWithBaseUrl(theCommandLine, baseUrl, theBasicAuthOptionName, theBearerTokenOptionName);
|
return newClientWithBaseUrl(theCommandLine, baseUrl, theBasicAuthOptionName, theBearerTokenOptionName, theTlsAuthOptionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IGenericClient newClientWithBaseUrl(CommandLine theCommandLine, String theBaseUrl, String theBasicAuthOptionName, String theBearerTokenOptionName) throws ParseException {
|
protected IGenericClient newClientWithBaseUrl(CommandLine theCommandLine, String theBaseUrl, String theBasicAuthOptionName,
|
||||||
|
String theBearerTokenOptionName, String theTlsAuthOptionName) throws ParseException {
|
||||||
|
|
||||||
|
Optional<TlsAuthentication> tlsConfig = createTlsConfig(theCommandLine, theTlsAuthOptionName);
|
||||||
|
RestfulClientFactory restfulClientFactory = tlsConfig.isPresent()
|
||||||
|
? new HapiFhirCliRestfulClientFactory(myFhirCtx, tlsConfig.get())
|
||||||
|
: new HapiFhirCliRestfulClientFactory(myFhirCtx);
|
||||||
|
|
||||||
|
myFhirCtx.setRestfulClientFactory(restfulClientFactory);
|
||||||
myFhirCtx.getRestfulClientFactory().setSocketTimeout((int) DateUtils.MILLIS_PER_HOUR);
|
myFhirCtx.getRestfulClientFactory().setSocketTimeout((int) DateUtils.MILLIS_PER_HOUR);
|
||||||
IGenericClient retVal = myFhirCtx.newRestfulGenericClient(theBaseUrl);
|
IGenericClient retVal = myFhirCtx.newRestfulGenericClient(theBaseUrl);
|
||||||
|
|
||||||
|
@ -490,6 +515,62 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<TlsAuthentication> createTlsConfig(CommandLine theCommandLine, String theTlsAuthOptionName){
|
||||||
|
String httpAuthFilePath = theCommandLine.getOptionValue(theTlsAuthOptionName);
|
||||||
|
if(isBlank(httpAuthFilePath)){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
try(FileReader fileReader = new FileReader(httpAuthFilePath)) {
|
||||||
|
JsonObject json = JsonParser.parseReader(fileReader).getAsJsonObject();
|
||||||
|
Optional<KeyStoreInfo> keyStoreInfo = createKeyStoreInfo(json.get("keyStore").getAsJsonObject());
|
||||||
|
Optional<TrustStoreInfo> trustStoreInfo = createTrustStoreInfo(json.get("trustStore").getAsJsonObject());
|
||||||
|
if(keyStoreInfo.isEmpty() && trustStoreInfo.isEmpty()){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.of(new TlsAuthentication(keyStoreInfo, trustStoreInfo));
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
throw new RuntimeException(Msg.code(2115)+"Could not create TLS configuration options", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<KeyStoreInfo> createKeyStoreInfo(JsonObject theJson) throws ParseException {
|
||||||
|
String filePath = theJson.get("filePath").getAsString();
|
||||||
|
if(isBlank(filePath)){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
String storePass = theJson.get("storePass").getAsString();
|
||||||
|
if (PROMPT.equals(storePass)) {
|
||||||
|
storePass = trim(promptUser("Enter the store password for the keystore: "));
|
||||||
|
}
|
||||||
|
String keyPass = theJson.get("keyPass").getAsString();
|
||||||
|
if (PROMPT.equals(keyPass)) {
|
||||||
|
keyPass = trim(promptUser("Enter the key password for the keystore: "));
|
||||||
|
}
|
||||||
|
String alias = theJson.get("alias").getAsString();
|
||||||
|
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo(filePath, storePass, keyPass, alias);
|
||||||
|
return Optional.of(keyStoreInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<TrustStoreInfo> createTrustStoreInfo(JsonObject theJson) throws ParseException {
|
||||||
|
String filePath = theJson.get("filePath").getAsString();
|
||||||
|
if(isBlank(filePath)){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
String storePass = theJson.get("storePass").getAsString();
|
||||||
|
if (PROMPT.equals(storePass)) {
|
||||||
|
storePass = trim(promptUser("Enter the store password for the truststore: "));
|
||||||
|
}
|
||||||
|
|
||||||
|
String alias = theJson.get("alias").getAsString();
|
||||||
|
TrustStoreInfo trustStoreInfo = new TrustStoreInfo(filePath, storePass, alias);
|
||||||
|
return Optional.of(trustStoreInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private String getAndParseBearerTokenAuthHeader(CommandLine theCommandLine, String theBearerTokenOptionName) throws ParseException {
|
private String getAndParseBearerTokenAuthHeader(CommandLine theCommandLine, String theBearerTokenOptionName) throws ParseException {
|
||||||
String value = theCommandLine.getOptionValue(theBearerTokenOptionName);
|
String value = theCommandLine.getOptionValue(theBearerTokenOptionName);
|
||||||
if (PROMPT.equals(value)) {
|
if (PROMPT.equals(value)) {
|
||||||
|
|
|
@ -42,7 +42,8 @@ public abstract class BaseRequestGeneratingCommand extends BaseCommand {
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
BASIC_AUTH,
|
BASIC_AUTH,
|
||||||
VERBOSE_LOGGING,
|
VERBOSE_LOGGING,
|
||||||
HEADER_PASSTHROUGH
|
HEADER_PASSTHROUGH,
|
||||||
|
TLS_AUTH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,16 +83,21 @@ public abstract class BaseRequestGeneratingCommand extends BaseCommand {
|
||||||
addHeaderPassthroughOption(options);
|
addHeaderPassthroughOption(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! theExcludeOptions.contains(BaseRequestGeneratingCommandOptions.TLS_AUTH)) {
|
||||||
|
addHttpsAuthOption(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IGenericClient newClientWithBaseUrl(CommandLine theCommandLine, String theBaseUrl,
|
protected IGenericClient newClientWithBaseUrl(CommandLine theCommandLine, String theBaseUrl,
|
||||||
String theBasicAuthOptionName, String theBearerTokenOptionName) throws ParseException {
|
String theBasicAuthOptionName, String theBearerTokenOptionName, String theTlsAuthOptionName) throws ParseException {
|
||||||
|
|
||||||
IGenericClient client = super.newClientWithBaseUrl(
|
IGenericClient client = super.newClientWithBaseUrl(
|
||||||
theCommandLine, theBaseUrl, theBasicAuthOptionName, theBearerTokenOptionName);
|
theCommandLine, theBaseUrl, theBasicAuthOptionName, theBearerTokenOptionName, theTlsAuthOptionName);
|
||||||
registerHeaderPassthrough(theCommandLine, client);
|
registerHeaderPassthrough(theCommandLine, client);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
|
|
|
@ -129,7 +129,7 @@ public class BulkImportCommand extends BaseCommand {
|
||||||
|
|
||||||
String targetBaseUrl = theCommandLine.getOptionValue(TARGET_BASE);
|
String targetBaseUrl = theCommandLine.getOptionValue(TARGET_BASE);
|
||||||
ourLog.info("Initiating bulk import against server: {}", targetBaseUrl);
|
ourLog.info("Initiating bulk import against server: {}", targetBaseUrl);
|
||||||
IGenericClient client = newClient(theCommandLine, TARGET_BASE, BASIC_AUTH_PARAM, BEARER_TOKEN_PARAM_LONGOPT);
|
IGenericClient client = newClient(theCommandLine, TARGET_BASE, BASIC_AUTH_PARAM, BEARER_TOKEN_PARAM_LONGOPT, TLS_AUTH_PARAM_LONGOPT);
|
||||||
client.registerInterceptor(new LoggingInterceptor(false));
|
client.registerInterceptor(new LoggingInterceptor(false));
|
||||||
|
|
||||||
IBaseParameters request = createRequest(sourceBaseUrl, indexes, resourceTypes);
|
IBaseParameters request = createRequest(sourceBaseUrl, indexes, resourceTypes);
|
||||||
|
|
|
@ -46,6 +46,7 @@ import java.util.concurrent.ExecutionException;
|
||||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
|
||||||
public class ExportConceptMapToCsvCommand extends AbstractImportExportCsvConceptMapCommand {
|
public class ExportConceptMapToCsvCommand extends AbstractImportExportCsvConceptMapCommand {
|
||||||
|
public static final String COMMAND = "export-conceptmap-to-csv";
|
||||||
// TODO: Don't use qualified names for loggers in HAPI CLI.
|
// TODO: Don't use qualified names for loggers in HAPI CLI.
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExportConceptMapToCsvCommand.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExportConceptMapToCsvCommand.class);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class ImportCsvToConceptMapCommand extends AbstractImportExportCsvConceptMapCommand {
|
public class ImportCsvToConceptMapCommand extends AbstractImportExportCsvConceptMapCommand {
|
||||||
|
public static final String COMMAND = "import-csv-to-conceptmap";
|
||||||
|
|
||||||
// TODO: Don't use qualified names for loggers in HAPI CLI.
|
// TODO: Don't use qualified names for loggers in HAPI CLI.
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ImportCsvToConceptMapCommand.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ImportCsvToConceptMapCommand.class);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
package ca.uhn.fhir.cli.client;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Command Line Client - API
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.client.apache.ApacheHttpClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.Header;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.tls.TlsAuthenticationSvc;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.config.Registry;
|
||||||
|
import org.apache.http.config.RegistryBuilder;
|
||||||
|
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended for use with the HapiFhir CLI only.
|
||||||
|
* <br/><br/>
|
||||||
|
* A Restful Factory to create clients, requests and responses based on the Apache httpclient library.
|
||||||
|
* This class supports HTTP and HTTPS protocol and attempts to use the same client whenever possible.
|
||||||
|
* The method {@link HapiFhirCliRestfulClientFactory#useHttp()} should be used if the protocol needs to be changed to HTTP.
|
||||||
|
* Similarly, the method {@link HapiFhirCliRestfulClientFactory#useHttps(TlsAuthentication)} should be used if the protocol
|
||||||
|
* needs to be changed to HTTPS or if new TLS credentials are required for a client request.
|
||||||
|
*/
|
||||||
|
public class HapiFhirCliRestfulClientFactory extends RestfulClientFactory {
|
||||||
|
|
||||||
|
private HttpClient myHttpClient;
|
||||||
|
private TlsAuthentication myTlsAuthentication;
|
||||||
|
|
||||||
|
public HapiFhirCliRestfulClientFactory(FhirContext theFhirContext) {
|
||||||
|
this(theFhirContext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HapiFhirCliRestfulClientFactory(FhirContext theFhirContext, TlsAuthentication theTlsAuthentication) {
|
||||||
|
super(theFhirContext);
|
||||||
|
myTlsAuthentication = theTlsAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected synchronized IHttpClient getHttpClient(String theServerBase) {
|
||||||
|
return getHttpClient(new StringBuilder(theServerBase), null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
|
||||||
|
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||||
|
return new ApacheHttpClient(getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClient getNativeHttpClient() {
|
||||||
|
if (myHttpClient == null) {
|
||||||
|
|
||||||
|
RequestConfig defaultRequestConfig =
|
||||||
|
RequestConfig.custom()
|
||||||
|
.setSocketTimeout(getSocketTimeout())
|
||||||
|
.setConnectTimeout(getConnectTimeout())
|
||||||
|
.setConnectionRequestTimeout(getConnectionRequestTimeout())
|
||||||
|
.setStaleConnectionCheckEnabled(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpClientBuilder builder = HttpClients.custom()
|
||||||
|
.useSystemProperties()
|
||||||
|
.setDefaultRequestConfig(defaultRequestConfig)
|
||||||
|
.disableCookieManagement();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager;
|
||||||
|
if(myTlsAuthentication != null){
|
||||||
|
SSLContext sslContext = TlsAuthenticationSvc.createSslContext(myTlsAuthentication);
|
||||||
|
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||||
|
builder.setSSLSocketFactory(sslConnectionSocketFactory);
|
||||||
|
Registry<ConnectionSocketFactory> registry = RegistryBuilder
|
||||||
|
.<ConnectionSocketFactory> create()
|
||||||
|
.register("https", sslConnectionSocketFactory)
|
||||||
|
.build();
|
||||||
|
connectionManager = new PoolingHttpClientConnectionManager(
|
||||||
|
registry, null, null, null, 5000, TimeUnit.MILLISECONDS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionManager.setMaxTotal(getPoolMaxTotal());
|
||||||
|
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
|
||||||
|
myHttpClient = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return myHttpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void resetHttpClient() {
|
||||||
|
myHttpClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void useHttp(){
|
||||||
|
myTlsAuthentication = null;
|
||||||
|
resetHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void useHttps(TlsAuthentication theTlsAuthentication){
|
||||||
|
myTlsAuthentication = theTlsAuthentication;
|
||||||
|
resetHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setHttpClient(Object theHttpClient) {
|
||||||
|
throw new UnsupportedOperationException(Msg.code(2119));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProxy(String theHost, Integer thePort) {
|
||||||
|
throw new UnsupportedOperationException(Msg.code(2120));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class ApacheRestfulClientFactoryTest extends BaseFhirVersionParameterizedTest {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) throws Exception {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
HttpClient client = clientFactory.getNativeHttpClient();
|
||||||
|
|
||||||
|
HttpUriRequest request = new HttpGet(fhirVersionParams.getPatientEndpoint());
|
||||||
|
HttpResponse response = client.execute(request);
|
||||||
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
String json = EntityUtils.toString(response.getEntity());
|
||||||
|
IBaseResource bundle = fhirVersionParams.parseResource(json);
|
||||||
|
assertEquals(fhirVersionParams.getFhirVersion(), bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
HttpClient unauthenticatedClient = clientFactory.getNativeHttpClient();
|
||||||
|
|
||||||
|
try{
|
||||||
|
HttpUriRequest request = new HttpGet(fhirVersionParams.getSecuredPatientEndpoint());
|
||||||
|
unauthenticatedClient.execute(request);
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttp(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String base = fhirVersionParams.getBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new ApacheRestfulClientFactory(context));
|
||||||
|
IBaseResource bundle = context.newRestfulGenericClient(base).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String secureBase = fhirVersionParams.getSecureBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new ApacheRestfulClientFactory(context));
|
||||||
|
try {
|
||||||
|
context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertTrue(e.getMessage().contains("HAPI-1357: Failed to retrieve the server metadata statement during client initialization"));
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getCause().getCause().getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,25 +32,26 @@ class BaseRequestGeneratingCommandTest {
|
||||||
@Test
|
@Test
|
||||||
void getOptions() {
|
void getOptions() {
|
||||||
Options options = tested.getOptions();
|
Options options = tested.getOptions();
|
||||||
assertEquals(6, options.getOptions().size());
|
assertEquals(7, options.getOptions().size());
|
||||||
assertTrue(options.hasShortOption(BaseCommand.FHIR_VERSION_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.FHIR_VERSION_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BASE_URL_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.BASE_URL_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BASIC_AUTH_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.BASIC_AUTH_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BEARER_TOKEN_PARAM_NAME));
|
assertTrue(options.hasShortOption(BaseCommand.BEARER_TOKEN_PARAM_NAME));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.VERBOSE_LOGGING_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.VERBOSE_LOGGING_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseRequestGeneratingCommand.HEADER_PASSTHROUGH));
|
assertTrue(options.hasShortOption(BaseRequestGeneratingCommand.HEADER_PASSTHROUGH));
|
||||||
|
assertTrue(options.hasShortOption(BaseRequestGeneratingCommand.TLS_AUTH_PARAM_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Excluding {0}")
|
@ParameterizedTest(name = "Excluding {0}")
|
||||||
@EnumSource(value = BaseRequestGeneratingCommandOptions.class,
|
@EnumSource(value = BaseRequestGeneratingCommandOptions.class,
|
||||||
names = {"VERSION", "BASE_URL", "BASIC_AUTH", "VERBOSE_LOGGING", "HEADER_PASSTHROUGH"})
|
names = {"VERSION", "BASE_URL", "BASIC_AUTH", "VERBOSE_LOGGING", "HEADER_PASSTHROUGH", "TLS_AUTH"})
|
||||||
void getSomeOptionsExcludingOne(BaseRequestGeneratingCommandOptions excludedOption) {
|
void getSomeOptionsExcludingOne(BaseRequestGeneratingCommandOptions excludedOption) {
|
||||||
Collection<BaseRequestGeneratingCommandOptions> excludeOptions = Collections.singleton(excludedOption);
|
Collection<BaseRequestGeneratingCommandOptions> excludeOptions = Collections.singleton(excludedOption);
|
||||||
|
|
||||||
Options options = tested.getSomeOptions(excludeOptions);
|
Options options = tested.getSomeOptions(excludeOptions);
|
||||||
|
|
||||||
// BASIC_AUTH exclusion excludes 2 options
|
// BASIC_AUTH exclusion excludes 2 options
|
||||||
int expectedSize = excludedOption == BASIC_AUTH ? 4 : 5;
|
int expectedSize = excludedOption == BASIC_AUTH ? 5 : 6;
|
||||||
assertEquals(expectedSize, options.getOptions().size());
|
assertEquals(expectedSize, options.getOptions().size());
|
||||||
|
|
||||||
assertFalse(options.hasShortOption(getOptionForExcludedOption(excludedOption)));
|
assertFalse(options.hasShortOption(getOptionForExcludedOption(excludedOption)));
|
||||||
|
@ -86,6 +87,9 @@ class BaseRequestGeneratingCommandTest {
|
||||||
|
|
||||||
case HEADER_PASSTHROUGH:
|
case HEADER_PASSTHROUGH:
|
||||||
return BaseRequestGeneratingCommand.HEADER_PASSTHROUGH;
|
return BaseRequestGeneratingCommand.HEADER_PASSTHROUGH;
|
||||||
|
|
||||||
|
case TLS_AUTH:
|
||||||
|
return BaseCommand.TLS_AUTH_PARAM_NAME;
|
||||||
}
|
}
|
||||||
throw new InvalidParameterException("unexpected exclude option " + excludeOption);
|
throw new InvalidParameterException("unexpected exclude option " + excludeOption);
|
||||||
}
|
}
|
||||||
|
@ -94,11 +98,12 @@ class BaseRequestGeneratingCommandTest {
|
||||||
void getSomeOptionsExcludeTwo() {
|
void getSomeOptionsExcludeTwo() {
|
||||||
Options options = tested.getSomeOptions(Lists.newArrayList(VERSION, HEADER_PASSTHROUGH));
|
Options options = tested.getSomeOptions(Lists.newArrayList(VERSION, HEADER_PASSTHROUGH));
|
||||||
|
|
||||||
assertEquals(4, options.getOptions().size());
|
assertEquals(5, options.getOptions().size());
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BASE_URL_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.BASE_URL_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BASIC_AUTH_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.BASIC_AUTH_PARAM));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.BEARER_TOKEN_PARAM_NAME));
|
assertTrue(options.hasShortOption(BaseCommand.BEARER_TOKEN_PARAM_NAME));
|
||||||
assertTrue(options.hasShortOption(BaseCommand.VERBOSE_LOGGING_PARAM));
|
assertTrue(options.hasShortOption(BaseCommand.VERBOSE_LOGGING_PARAM));
|
||||||
|
assertTrue(options.hasShortOption(BaseCommand.TLS_AUTH_PARAM_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
package ca.uhn.fhir.cli;
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.Resource;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -24,10 +28,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
class ExampleDataUploaderTest {
|
class ExampleDataUploaderTest {
|
||||||
|
|
||||||
private FhirContext myCtx = FhirContext.forR4();
|
|
||||||
|
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public final RestfulServerExtension myRestfulServerExtension = new RestfulServerExtension(myCtx);
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper();
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
private final CapturingInterceptor myCapturingInterceptor = new CapturingInterceptor();
|
private final CapturingInterceptor myCapturingInterceptor = new CapturingInterceptor();
|
||||||
private final ExampleDataUploader testedCommand = new RequestCapturingExampleDataUploader(myCapturingInterceptor);
|
private final ExampleDataUploader testedCommand = new RequestCapturingExampleDataUploader(myCapturingInterceptor);
|
||||||
|
@ -40,19 +44,20 @@ class ExampleDataUploaderTest {
|
||||||
inputFilePath = resourcesPath + "/sample.json.zip";
|
inputFilePath = resourcesPath + "/sample.json.zip";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(booleans = {true, false})
|
||||||
@Test
|
public void testHeaderPassthrough(boolean theIncludeTls) throws ParseException {
|
||||||
public void testHeaderPassthrough() throws ParseException {
|
|
||||||
String headerKey = "test-header-key";
|
String headerKey = "test-header-key";
|
||||||
String headerValue = "test header value";
|
String headerValue = "test header value";
|
||||||
|
|
||||||
String[] args = new String[] {
|
String[] args = myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
"-v", "r4", // BaseRequestGeneratingCommandTest required
|
"-v", "r4", // BaseRequestGeneratingCommandTest required
|
||||||
"-t", "http://localhost:8000", // BaseRequestGeneratingCommandTest required
|
|
||||||
"-d", inputFilePath,
|
"-d", inputFilePath,
|
||||||
"-hp", headerKey + ":" + headerValue // optional
|
"-hp", headerKey + ":" + headerValue // optional
|
||||||
};
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper // BaseRequestGeneratingCommandTest required
|
||||||
|
);
|
||||||
|
|
||||||
final CommandLine commandLine = new DefaultParser().parse(testedCommand.getOptions(), args, true);
|
final CommandLine commandLine = new DefaultParser().parse(testedCommand.getOptions(), args, true);
|
||||||
testedCommand.run(commandLine);
|
testedCommand.run(commandLine);
|
||||||
|
@ -65,8 +70,13 @@ class ExampleDataUploaderTest {
|
||||||
assertEquals(1, allHeaders.get(headerKey).size());
|
assertEquals(1, allHeaders.get(headerKey).size());
|
||||||
|
|
||||||
assertThat(allHeaders.get(headerKey), hasItems(headerValue));
|
assertThat(allHeaders.get(headerKey), hasItems(headerValue));
|
||||||
}
|
|
||||||
|
|
||||||
|
assertEquals(1, myRestServerR4Helper.getTransactions().size());
|
||||||
|
Bundle bundle = myRestServerR4Helper.getTransactions().get(0);
|
||||||
|
Resource resource = bundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(Patient.class, resource.getClass());
|
||||||
|
assertEquals("EX3152", resource.getIdElement().getIdPart());
|
||||||
|
}
|
||||||
|
|
||||||
private static class RequestCapturingExampleDataUploader extends ExampleDataUploader {
|
private static class RequestCapturingExampleDataUploader extends ExampleDataUploader {
|
||||||
private final CapturingInterceptor myCapturingInterceptor;
|
private final CapturingInterceptor myCapturingInterceptor;
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
package ca.uhn.fhir.cli;
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.VerboseLoggingInterceptor;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.test.utilities.LoggingExtension;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.dstu3.model.ConceptMap;
|
import org.hl7.fhir.dstu3.model.ConceptMap;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.dstu3.model.Enumerations.ConceptMapEquivalence;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -38,30 +34,50 @@ public class ExportConceptMapToCsvCommandDstu3Test {
|
||||||
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
||||||
private static final String FILE = "./target/output_dstu3.csv";
|
private static final String FILE = "./target/output_dstu3.csv";
|
||||||
|
|
||||||
private static String ourBase;
|
private final FhirContext myCtx = FhirContext.forDstu3();
|
||||||
private static IGenericClient ourClient;
|
private final String myVersion = "dstu3";
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
private static String ourVersion = "dstu3";
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public LoggingExtension myLoggingExtension = new LoggingExtension();
|
public final RestServerDstu3Helper myRestServerDstu3Helper = new RestServerDstu3Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
@Test
|
@BeforeEach
|
||||||
public void testExportConceptMapToCsvCommand() throws IOException {
|
public void before(){
|
||||||
ourLog.debug("ConceptMap:\n" + ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(createConceptMap()));
|
myRestServerDstu3Helper.setConceptMapResourceProvider(new HashMapResourceProviderConceptMapDstu3(myCtx));
|
||||||
|
myRestServerDstu3Helper.getClient().create().resource(createConceptMap()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
App.main(new String[]{"export-conceptmap-to-csv",
|
@AfterEach
|
||||||
"-v", ourVersion,
|
public void afterEach() {
|
||||||
"-t", ourBase,
|
myRestServerDstu3Helper.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterAll(){
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testExportConceptMapToCsvCommandNoTls(boolean theIncludeTls) throws IOException {
|
||||||
|
ourLog.debug("ConceptMap:\n" + myCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(createConceptMap()));
|
||||||
|
|
||||||
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
|
ExportConceptMapToCsvCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-f", FILE,
|
"-f", FILE,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerDstu3Helper
|
||||||
|
));
|
||||||
|
|
||||||
await().until(() -> new File(FILE).exists());
|
await().until(() -> new File(FILE).exists());
|
||||||
|
|
||||||
String expected = "\"SOURCE_CODE_SYSTEM\",\"SOURCE_CODE_SYSTEM_VERSION\",\"TARGET_CODE_SYSTEM\",\"TARGET_CODE_SYSTEM_VERSION\",\"SOURCE_CODE\",\"SOURCE_DISPLAY\",\"TARGET_CODE\",\"TARGET_DISPLAY\",\"EQUIVALENCE\",\"COMMENT\"\n" +
|
String expected = "\"SOURCE_CODE_SYSTEM\",\"SOURCE_CODE_SYSTEM_VERSION\",\"TARGET_CODE_SYSTEM\",\"TARGET_CODE_SYSTEM_VERSION\",\"SOURCE_CODE\",\"SOURCE_DISPLAY\",\"TARGET_CODE\",\"TARGET_DISPLAY\",\"EQUIVALENCE\",\"COMMENT\"\n" +
|
||||||
|
@ -85,36 +101,6 @@ public class ExportConceptMapToCsvCommandDstu3Test {
|
||||||
FileUtils.deleteQuietly(new File(FILE));
|
FileUtils.deleteQuietly(new File(FILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
ServletHandler servletHandler = new ServletHandler();
|
|
||||||
|
|
||||||
RestfulServer restfulServer = new RestfulServer(ourCtx);
|
|
||||||
restfulServer.registerInterceptor(new VerboseLoggingInterceptor());
|
|
||||||
restfulServer.setResourceProviders(new HashMapResourceProviderConceptMapDstu3(ourCtx));
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(restfulServer);
|
|
||||||
servletHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(servletHandler);
|
|
||||||
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
ourBase = "http://localhost:" + ourPort;
|
|
||||||
|
|
||||||
ourClient = ourCtx.newRestfulGenericClient(ourBase);
|
|
||||||
|
|
||||||
ourClient.create().resource(createConceptMap()).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConceptMap createConceptMap() {
|
static ConceptMap createConceptMap() {
|
||||||
ConceptMap conceptMap = new ConceptMap();
|
ConceptMap conceptMap = new ConceptMap();
|
||||||
conceptMap
|
conceptMap
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
package ca.uhn.fhir.cli;
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.VerboseLoggingInterceptor;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.r4.model.ConceptMap;
|
import org.hl7.fhir.r4.model.ConceptMap;
|
||||||
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
import org.hl7.fhir.r4.model.UriType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -36,27 +34,50 @@ public class ExportConceptMapToCsvCommandR4Test {
|
||||||
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
||||||
private static final String FILE = new File("./target/output_r4.csv").getAbsolutePath();
|
private static final String FILE = new File("./target/output_r4.csv").getAbsolutePath();
|
||||||
|
|
||||||
private static String ourBase;
|
|
||||||
private static IGenericClient ourClient;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
private static String ourVersion = "r4";
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@RegisterExtension
|
||||||
public void testExportConceptMapToCsvCommand() throws IOException {
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper(true);
|
||||||
ourLog.info("ConceptMap:\n" + ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(createConceptMap()));
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
App.main(new String[]{"export-conceptmap-to-csv",
|
private final FhirContext myCtx = FhirContext.forR4();
|
||||||
"-v", ourVersion,
|
private final String myVersion = "r4";
|
||||||
"-t", ourBase,
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before(){
|
||||||
|
myRestServerR4Helper.setConceptMapResourceProvider(new HashMapResourceProviderConceptMapR4(myCtx));
|
||||||
|
myRestServerR4Helper.getClient().create().resource(createConceptMap()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void afterEach() {
|
||||||
|
myRestServerR4Helper.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterAll(){
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testExportConceptMapToCsvCommand(boolean theIncludeTls) throws IOException {
|
||||||
|
ourLog.info("ConceptMap:\n" + myCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(createConceptMap()));
|
||||||
|
|
||||||
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
|
ExportConceptMapToCsvCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-f", FILE,
|
"-f", FILE,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
await().until(() -> new File(FILE).exists());
|
await().until(() -> new File(FILE).exists());
|
||||||
|
|
||||||
String expected = "\"SOURCE_CODE_SYSTEM\",\"SOURCE_CODE_SYSTEM_VERSION\",\"TARGET_CODE_SYSTEM\",\"TARGET_CODE_SYSTEM_VERSION\",\"SOURCE_CODE\",\"SOURCE_DISPLAY\",\"TARGET_CODE\",\"TARGET_DISPLAY\",\"EQUIVALENCE\",\"COMMENT\"\n" +
|
String expected = "\"SOURCE_CODE_SYSTEM\",\"SOURCE_CODE_SYSTEM_VERSION\",\"TARGET_CODE_SYSTEM\",\"TARGET_CODE_SYSTEM_VERSION\",\"SOURCE_CODE\",\"SOURCE_DISPLAY\",\"TARGET_CODE\",\"TARGET_DISPLAY\",\"EQUIVALENCE\",\"COMMENT\"\n" +
|
||||||
|
@ -78,36 +99,6 @@ public class ExportConceptMapToCsvCommandR4Test {
|
||||||
FileUtils.deleteQuietly(new File(FILE));
|
FileUtils.deleteQuietly(new File(FILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
ServletHandler servletHandler = new ServletHandler();
|
|
||||||
|
|
||||||
RestfulServer restfulServer = new RestfulServer(ourCtx);
|
|
||||||
restfulServer.registerInterceptor(new VerboseLoggingInterceptor());
|
|
||||||
restfulServer.setResourceProviders(new HashMapResourceProviderConceptMapR4(ourCtx));
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(restfulServer);
|
|
||||||
servletHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(servletHandler);
|
|
||||||
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
ourBase = "http://localhost:" + ourPort;
|
|
||||||
|
|
||||||
ourClient = ourCtx.newRestfulGenericClient(ourBase);
|
|
||||||
|
|
||||||
ourClient.create().resource(createConceptMap()).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConceptMap createConceptMap() {
|
static ConceptMap createConceptMap() {
|
||||||
ConceptMap conceptMap = new ConceptMap();
|
ConceptMap conceptMap = new ConceptMap();
|
||||||
conceptMap
|
conceptMap
|
||||||
|
|
|
@ -2,14 +2,9 @@ package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.VerboseLoggingInterceptor;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.ConceptMap;
|
import org.hl7.fhir.dstu3.model.ConceptMap;
|
||||||
import org.hl7.fhir.dstu3.model.ConceptMap.ConceptMapGroupComponent;
|
import org.hl7.fhir.dstu3.model.ConceptMap.ConceptMapGroupComponent;
|
||||||
|
@ -18,9 +13,11 @@ import org.hl7.fhir.dstu3.model.ConceptMap.TargetElementComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.dstu3.model.Enumerations.ConceptMapEquivalence;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -37,26 +34,27 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
||||||
private static final String FILENAME = "import-csv-to-conceptmap-command-test-input.csv";
|
private static final String FILENAME = "import-csv-to-conceptmap-command-test-input.csv";
|
||||||
|
|
||||||
private static String file;
|
private final FhirContext myCtx = FhirContext.forDstu3();
|
||||||
private static String ourBase;
|
private final String myVersion = "dstu3";
|
||||||
private static IGenericClient ourClient;
|
private String myFile;
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
private static String ourVersion = "dstu3";
|
|
||||||
|
|
||||||
private static RestfulServer restfulServer;
|
|
||||||
|
|
||||||
private static HashMapResourceProviderConceptMapDstu3 hashMapResourceProviderConceptMapDstu3;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@RegisterExtension
|
||||||
public void afterClearResourceProvider() {
|
public final RestServerDstu3Helper myRestServerDstu3Helper = new RestServerDstu3Helper(true);
|
||||||
HashMapResourceProviderConceptMapDstu3 resourceProvider = (HashMapResourceProviderConceptMapDstu3) restfulServer.getResourceProviders().iterator().next();
|
@RegisterExtension
|
||||||
resourceProvider.clear();
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before(){
|
||||||
|
myRestServerDstu3Helper.setConceptMapResourceProvider(new HashMapResourceProviderConceptMapDstu3(myCtx));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterAll(){
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -65,7 +63,7 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
String conceptMapUrl = conceptMap.getUrl();
|
String conceptMapUrl = conceptMap.getUrl();
|
||||||
|
|
||||||
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerDstu3Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(conceptMap)
|
.resource(conceptMap)
|
||||||
.conditional()
|
.conditional()
|
||||||
|
@ -78,11 +76,11 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
@Test
|
@Test
|
||||||
public void testConditionalUpdateResultsInUpdate() {
|
public void testConditionalUpdateResultsInUpdate() {
|
||||||
ConceptMap conceptMap = ExportConceptMapToCsvCommandDstu3Test.createConceptMap();
|
ConceptMap conceptMap = ExportConceptMapToCsvCommandDstu3Test.createConceptMap();
|
||||||
ourClient.create().resource(conceptMap).execute();
|
myRestServerDstu3Helper.getClient().create().resource(conceptMap).execute();
|
||||||
String conceptMapUrl = conceptMap.getUrl();
|
String conceptMapUrl = conceptMap.getUrl();
|
||||||
|
|
||||||
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerDstu3Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(conceptMap)
|
.resource(conceptMap)
|
||||||
.conditional()
|
.conditional()
|
||||||
|
@ -95,9 +93,9 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
@Test
|
@Test
|
||||||
public void testNonConditionalUpdate() {
|
public void testNonConditionalUpdate() {
|
||||||
ConceptMap conceptMap = ExportConceptMapToCsvCommandDstu3Test.createConceptMap();
|
ConceptMap conceptMap = ExportConceptMapToCsvCommandDstu3Test.createConceptMap();
|
||||||
ourClient.create().resource(conceptMap).execute();
|
myRestServerDstu3Helper.getClient().create().resource(conceptMap).execute();
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = myRestServerDstu3Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -106,7 +104,7 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
|
|
||||||
ConceptMap resultConceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
ConceptMap resultConceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerDstu3Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(resultConceptMap)
|
.resource(resultConceptMap)
|
||||||
.withId(resultConceptMap.getIdElement())
|
.withId(resultConceptMap.getIdElement())
|
||||||
|
@ -115,22 +113,27 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
assertNull(methodOutcome.getCreated());
|
assertNull(methodOutcome.getCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testImportCsvToConceptMapCommand() throws FHIRException {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testImportCsvToConceptMapCommandNoTls(boolean theIncludeTls) throws FHIRException {
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
File fileToImport = new File(classLoader.getResource(FILENAME).getFile());
|
File fileToImport = new File(classLoader.getResource(FILENAME).getFile());
|
||||||
ImportCsvToConceptMapCommandDstu3Test.file = fileToImport.getAbsolutePath();
|
myFile = fileToImport.getAbsolutePath();
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-i", VS_URL_1,
|
"-i", VS_URL_1,
|
||||||
"-o", VS_URL_2,
|
"-o", VS_URL_2,
|
||||||
"-f", file,
|
"-f", myFile,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerDstu3Helper
|
||||||
|
));
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = myRestServerDstu3Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -139,9 +142,9 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
|
|
||||||
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
ourLog.info(myCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/1", conceptMap.getId());
|
assertEquals(myRestServerDstu3Helper.getBase() + "/ConceptMap/1/_history/1", conceptMap.getId());
|
||||||
|
|
||||||
assertEquals(CM_URL, conceptMap.getUrl());
|
assertEquals(CM_URL, conceptMap.getUrl());
|
||||||
assertEquals(VS_URL_1, conceptMap.getSourceUriType().getValueAsString());
|
assertEquals(VS_URL_1, conceptMap.getSourceUriType().getValueAsString());
|
||||||
|
@ -317,16 +320,20 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
assertEquals(ConceptMapEquivalence.EQUAL, target.getEquivalence());
|
assertEquals(ConceptMapEquivalence.EQUAL, target.getEquivalence());
|
||||||
assertEquals("3d This is a comment.", target.getComment());
|
assertEquals("3d This is a comment.", target.getComment());
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-i", VS_URL_1,
|
"-i", VS_URL_1,
|
||||||
"-o", VS_URL_2,
|
"-o", VS_URL_2,
|
||||||
"-f", file,
|
"-f", myFile,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerDstu3Helper
|
||||||
|
));
|
||||||
|
|
||||||
response = ourClient
|
response = myRestServerDstu3Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -335,34 +342,7 @@ public class ImportCsvToConceptMapCommandDstu3Test {
|
||||||
|
|
||||||
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/2", conceptMap.getId());
|
assertEquals(myRestServerDstu3Helper.getBase() + "/ConceptMap/1/_history/2", conceptMap.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
ServletHandler servletHandler = new ServletHandler();
|
|
||||||
|
|
||||||
restfulServer = new RestfulServer(ourCtx);
|
|
||||||
restfulServer.registerInterceptor(new VerboseLoggingInterceptor());
|
|
||||||
restfulServer.setResourceProviders(new HashMapResourceProviderConceptMapDstu3(ourCtx));
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(restfulServer);
|
|
||||||
servletHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(servletHandler);
|
|
||||||
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
ourBase = "http://localhost:" + ourPort;
|
|
||||||
|
|
||||||
ourClient = ourCtx.newRestfulGenericClient(ourBase);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,9 @@ package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.VerboseLoggingInterceptor;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.ConceptMap;
|
import org.hl7.fhir.r4.model.ConceptMap;
|
||||||
|
@ -18,9 +13,11 @@ import org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent;
|
||||||
import org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent;
|
import org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent;
|
||||||
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -38,26 +35,27 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
private static final String CS_URL_3 = "http://example.com/codesystem/3";
|
||||||
private static final String FILENAME = "import-csv-to-conceptmap-command-test-input.csv";
|
private static final String FILENAME = "import-csv-to-conceptmap-command-test-input.csv";
|
||||||
|
|
||||||
private static String file;
|
|
||||||
private static String ourBase;
|
|
||||||
private static IGenericClient ourClient;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
private static String ourVersion = "r4";
|
|
||||||
|
|
||||||
private static RestfulServer restfulServer;
|
|
||||||
|
|
||||||
private static HashMapResourceProviderConceptMapR4 hashMapResourceProviderConceptMapR4;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
private final FhirContext myFhirContext = FhirContext.forR4();
|
||||||
public void afterClearResourceProvider() {
|
private final String myVersion = "r4";
|
||||||
HashMapResourceProviderConceptMapR4 resourceProvider = (HashMapResourceProviderConceptMapR4) restfulServer.getResourceProviders().iterator().next();
|
private String myFilePath;
|
||||||
resourceProvider.clear();
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before(){
|
||||||
|
myRestServerR4Helper.setConceptMapResourceProvider(new HashMapResourceProviderConceptMapR4(myFhirContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterAll(){
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -66,7 +64,7 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
String conceptMapUrl = conceptMap.getUrl();
|
String conceptMapUrl = conceptMap.getUrl();
|
||||||
|
|
||||||
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerR4Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(conceptMap)
|
.resource(conceptMap)
|
||||||
.conditional()
|
.conditional()
|
||||||
|
@ -80,11 +78,11 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
@Test
|
@Test
|
||||||
public void testConditionalUpdateResultsInUpdate() {
|
public void testConditionalUpdateResultsInUpdate() {
|
||||||
ConceptMap conceptMap = ExportConceptMapToCsvCommandR4Test.createConceptMap();
|
ConceptMap conceptMap = ExportConceptMapToCsvCommandR4Test.createConceptMap();
|
||||||
ourClient.create().resource(conceptMap).execute();
|
myRestServerR4Helper.getClient().create().resource(conceptMap).execute();
|
||||||
String conceptMapUrl = conceptMap.getUrl();
|
String conceptMapUrl = conceptMap.getUrl();
|
||||||
|
|
||||||
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
ourLog.info("Searching for existing ConceptMap with specified URL (i.e. ConceptMap.url): {}", conceptMapUrl);
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerR4Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(conceptMap)
|
.resource(conceptMap)
|
||||||
.conditional()
|
.conditional()
|
||||||
|
@ -98,9 +96,9 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
@Test
|
@Test
|
||||||
public void testNonConditionalUpdate() {
|
public void testNonConditionalUpdate() {
|
||||||
ConceptMap conceptMap = ExportConceptMapToCsvCommandR4Test.createConceptMap();
|
ConceptMap conceptMap = ExportConceptMapToCsvCommandR4Test.createConceptMap();
|
||||||
ourClient.create().resource(conceptMap).execute();
|
myRestServerR4Helper.getClient().create().resource(conceptMap).execute();
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = myRestServerR4Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -109,7 +107,7 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
|
|
||||||
ConceptMap resultConceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
ConceptMap resultConceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
MethodOutcome methodOutcome = ourClient
|
MethodOutcome methodOutcome = myRestServerR4Helper.getClient()
|
||||||
.update()
|
.update()
|
||||||
.resource(resultConceptMap)
|
.resource(resultConceptMap)
|
||||||
.withId(resultConceptMap.getIdElement())
|
.withId(resultConceptMap.getIdElement())
|
||||||
|
@ -121,22 +119,27 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
assertTrue(!Boolean.TRUE.equals(methodOutcome.getCreated()));
|
assertTrue(!Boolean.TRUE.equals(methodOutcome.getCreated()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testImportCsvToConceptMapCommand() throws FHIRException {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testImportCsvToConceptMapCommand(boolean theIncludeTls) throws Exception {
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
File fileToImport = new File(classLoader.getResource(FILENAME).getFile());
|
File fileToImport = new File(classLoader.getResource(FILENAME).getFile());
|
||||||
ImportCsvToConceptMapCommandR4Test.file = fileToImport.getAbsolutePath();
|
myFilePath = fileToImport.getAbsolutePath();
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-i", VS_URL_1,
|
"-i", VS_URL_1,
|
||||||
"-o", VS_URL_2,
|
"-o", VS_URL_2,
|
||||||
"-f", file,
|
"-f", myFilePath,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = myRestServerR4Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -145,9 +148,9 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
|
|
||||||
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/1", conceptMap.getId());
|
assertEquals(myRestServerR4Helper.getBase() + "/ConceptMap/1/_history/1", conceptMap.getId());
|
||||||
|
|
||||||
assertEquals(CM_URL, conceptMap.getUrl());
|
assertEquals(CM_URL, conceptMap.getUrl());
|
||||||
assertEquals(VS_URL_1, conceptMap.getSourceUriType().getValueAsString());
|
assertEquals(VS_URL_1, conceptMap.getSourceUriType().getValueAsString());
|
||||||
|
@ -323,16 +326,20 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
assertEquals(ConceptMapEquivalence.EQUAL, target.getEquivalence());
|
assertEquals(ConceptMapEquivalence.EQUAL, target.getEquivalence());
|
||||||
assertEquals("3d This is a comment.", target.getComment());
|
assertEquals("3d This is a comment.", target.getComment());
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", CM_URL,
|
"-u", CM_URL,
|
||||||
"-i", VS_URL_1,
|
"-i", VS_URL_1,
|
||||||
"-o", VS_URL_2,
|
"-o", VS_URL_2,
|
||||||
"-f", file,
|
"-f", myFilePath,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
response = ourClient
|
response = myRestServerR4Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value(CM_URL))
|
.where(ConceptMap.URL.matches().value(CM_URL))
|
||||||
|
@ -341,25 +348,30 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
|
|
||||||
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/2", conceptMap.getId());
|
assertEquals(myRestServerR4Helper.getBase() + "/ConceptMap/1/_history/2", conceptMap.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testImportCsvToConceptMapCommandWithByteOrderMark() throws FHIRException {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testImportCsvToConceptMapCommandWithByteOrderMark(boolean theIncludeTls) throws FHIRException {
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
File fileToImport = new File(classLoader.getResource("loinc-to-phenx.csv").getFile());
|
File fileToImport = new File(classLoader.getResource("loinc-to-phenx.csv").getFile());
|
||||||
ImportCsvToConceptMapCommandR4Test.file = fileToImport.getAbsolutePath();
|
myFilePath = fileToImport.getAbsolutePath();
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", "http://loinc.org/cm/loinc-to-phenx",
|
"-u", "http://loinc.org/cm/loinc-to-phenx",
|
||||||
"-i", "http://loinc.org",
|
"-i", "http://loinc.org",
|
||||||
"-o", "http://phenxtoolkit.org",
|
"-o", "http://phenxtoolkit.org",
|
||||||
"-f", file,
|
"-f", myFilePath,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
Bundle response = ourClient
|
Bundle response = myRestServerR4Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value("http://loinc.org/cm/loinc-to-phenx"))
|
.where(ConceptMap.URL.matches().value("http://loinc.org/cm/loinc-to-phenx"))
|
||||||
|
@ -368,9 +380,9 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
|
|
||||||
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
ConceptMap conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/1", conceptMap.getId());
|
assertEquals(myRestServerR4Helper.getBase() + "/ConceptMap/1/_history/1", conceptMap.getId());
|
||||||
|
|
||||||
assertEquals("http://loinc.org/cm/loinc-to-phenx", conceptMap.getUrl());
|
assertEquals("http://loinc.org/cm/loinc-to-phenx", conceptMap.getUrl());
|
||||||
assertEquals("http://loinc.org", conceptMap.getSourceUriType().getValueAsString());
|
assertEquals("http://loinc.org", conceptMap.getSourceUriType().getValueAsString());
|
||||||
|
@ -398,16 +410,20 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
assertEquals(ConceptMapEquivalence.EQUIVALENT, target.getEquivalence());
|
assertEquals(ConceptMapEquivalence.EQUIVALENT, target.getEquivalence());
|
||||||
assertNull(target.getComment());
|
assertNull(target.getComment());
|
||||||
|
|
||||||
App.main(new String[]{"import-csv-to-conceptmap",
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
"-v", ourVersion,
|
new String[]{
|
||||||
"-t", ourBase,
|
ImportCsvToConceptMapCommand.COMMAND,
|
||||||
|
"-v", myVersion,
|
||||||
"-u", "http://loinc.org/cm/loinc-to-phenx",
|
"-u", "http://loinc.org/cm/loinc-to-phenx",
|
||||||
"-i", "http://loinc.org",
|
"-i", "http://loinc.org",
|
||||||
"-o", "http://phenxtoolkit.org",
|
"-o", "http://phenxtoolkit.org",
|
||||||
"-f", file,
|
"-f", myFilePath,
|
||||||
"-l"});
|
"-l"
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
response = ourClient
|
response = myRestServerR4Helper.getClient()
|
||||||
.search()
|
.search()
|
||||||
.forResource(ConceptMap.class)
|
.forResource(ConceptMap.class)
|
||||||
.where(ConceptMap.URL.matches().value("http://loinc.org/cm/loinc-to-phenx"))
|
.where(ConceptMap.URL.matches().value("http://loinc.org/cm/loinc-to-phenx"))
|
||||||
|
@ -416,34 +432,6 @@ public class ImportCsvToConceptMapCommandR4Test {
|
||||||
|
|
||||||
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
conceptMap = (ConceptMap) response.getEntryFirstRep().getResource();
|
||||||
|
|
||||||
assertEquals("http://localhost:" + ourPort + "/ConceptMap/1/_history/2", conceptMap.getId());
|
assertEquals(myRestServerR4Helper.getBase() + "/ConceptMap/1/_history/2", conceptMap.getId());
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
ServletHandler servletHandler = new ServletHandler();
|
|
||||||
|
|
||||||
restfulServer = new RestfulServer(ourCtx);
|
|
||||||
restfulServer.registerInterceptor(new VerboseLoggingInterceptor());
|
|
||||||
restfulServer.setResourceProviders(new HashMapResourceProviderConceptMapR4(ourCtx));
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(restfulServer);
|
|
||||||
servletHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(servletHandler);
|
|
||||||
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
ourBase = "http://localhost:" + ourPort;
|
|
||||||
|
|
||||||
ourClient = ourCtx.newRestfulGenericClient(ourBase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,15 @@ package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
|
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
@ -17,7 +20,7 @@ import java.io.PrintStream;
|
||||||
import static ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider.RESP_PARAM_SUCCESS;
|
import static ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider.RESP_PARAM_SUCCESS;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
@ -31,8 +34,9 @@ class ReindexTerminologyCommandTest {
|
||||||
private BaseJpaSystemProvider<?, ?> myProvider = spy(new BaseJpaSystemProvider<>());
|
private BaseJpaSystemProvider<?, ?> myProvider = spy(new BaseJpaSystemProvider<>());
|
||||||
|
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public final RestfulServerExtension myRestfulServerExtension =
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper(true);
|
||||||
new RestfulServerExtension(myContext, myProvider);
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
|
||||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||||
|
@ -41,65 +45,89 @@ class ReindexTerminologyCommandTest {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void beforeEach(){
|
||||||
|
myRestServerR4Helper.registerProvider(myProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testProviderMethodInvoked() {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testProviderMethodInvoked(boolean theIncludeTls) {
|
||||||
System.setOut(new PrintStream(outputStreamCaptor));
|
System.setOut(new PrintStream(outputStreamCaptor));
|
||||||
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
||||||
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
||||||
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
||||||
"-v", "r4",
|
"-v", "r4"
|
||||||
"-t", myRestfulServerExtension.getBaseUrl()
|
},
|
||||||
});
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
assertThat(outputStreamCaptor.toString().trim(),
|
assertThat(outputStreamCaptor.toString().trim(),
|
||||||
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"true\"/>"));
|
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"true\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testNoVersionThrows() {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testNoVersionThrows(boolean theIncludeTls) {
|
||||||
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
||||||
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
||||||
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
||||||
|
|
||||||
Error thrown = assertThrows(Error.class, () ->
|
try {
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
|
ReindexTerminologyCommand.REINDEX_TERMINOLOGY
|
||||||
|
},
|
||||||
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
fail();
|
||||||
|
} catch (Error e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Missing required option: v"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testNoTargetThrows(boolean theIncludeTls) {
|
||||||
|
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
||||||
|
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
||||||
|
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
||||||
|
|
||||||
|
try {
|
||||||
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
||||||
"-t", myRestfulServerExtension.getBaseUrl()
|
"-v", "r4"
|
||||||
})
|
},
|
||||||
);
|
null, theIncludeTls, myRestServerR4Helper
|
||||||
assertThat(thrown.getMessage(), containsString("Missing required option: v"));
|
));
|
||||||
|
fail();
|
||||||
|
} catch (Error e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Missing required option: t"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testNoTargetThrows() {
|
@ValueSource(booleans = {true, false})
|
||||||
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
public void testHandleUnexpectedResponse(boolean theIncludeTls) {
|
||||||
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, true);
|
|
||||||
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
|
||||||
|
|
||||||
Error thrown = assertThrows(Error.class, () ->
|
|
||||||
App.main(new String[]{ReindexTerminologyCommand.REINDEX_TERMINOLOGY, "-v", "r4"})
|
|
||||||
);
|
|
||||||
assertThat(thrown.getMessage(), containsString("Missing required option: t"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHandleUnexpectedResponse() {
|
|
||||||
System.setOut(new PrintStream(outputStreamCaptor));
|
System.setOut(new PrintStream(outputStreamCaptor));
|
||||||
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
||||||
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
||||||
"-v", "r4",
|
"-v", "r4"
|
||||||
"-t", myRestfulServerExtension.getBaseUrl()
|
},
|
||||||
});
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
assertThat(outputStreamCaptor.toString().trim(),
|
assertThat(outputStreamCaptor.toString().trim(),
|
||||||
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"false\"/>"));
|
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"false\"/>"));
|
||||||
|
@ -110,8 +138,9 @@ class ReindexTerminologyCommandTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testHandleServiceError() {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void testHandleServiceError(boolean theIncludeTls) {
|
||||||
System.setOut(new PrintStream(outputStreamCaptor));
|
System.setOut(new PrintStream(outputStreamCaptor));
|
||||||
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
IBaseParameters retVal = ParametersUtil.newInstance(myContext);
|
||||||
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, false);
|
ParametersUtil.addParameterToParametersBoolean(myContext, retVal, RESP_PARAM_SUCCESS, false);
|
||||||
|
@ -119,11 +148,13 @@ class ReindexTerminologyCommandTest {
|
||||||
"Freetext service is not configured. Operation didn't run.");
|
"Freetext service is not configured. Operation didn't run.");
|
||||||
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
doReturn(retVal).when(myProvider).reindexTerminology(any());
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
ReindexTerminologyCommand.REINDEX_TERMINOLOGY,
|
||||||
"-v", "r4",
|
"-v", "r4"
|
||||||
"-t", myRestfulServerExtension.getBaseUrl()
|
},
|
||||||
});
|
"-t", theIncludeTls, myRestServerR4Helper
|
||||||
|
));
|
||||||
|
|
||||||
assertThat(outputStreamCaptor.toString().trim(),
|
assertThat(outputStreamCaptor.toString().trim(),
|
||||||
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"false\"/>"));
|
outputStreamCaptor.toString().trim(), containsString("<valueBoolean value=\"false\"/>"));
|
||||||
|
|
|
@ -5,20 +5,21 @@ import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||||
import ca.uhn.fhir.jpa.term.UploadStatistics;
|
import ca.uhn.fhir.jpa.term.UploadStatistics;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.BaseRestServerHelper;
|
||||||
|
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
||||||
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.TestInfo;
|
import org.junit.jupiter.api.TestInfo;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
|
@ -69,8 +70,6 @@ public class UploadTerminologyCommandTest {
|
||||||
private final String myICD10URL = "http://hl7.org/fhir/sid/icd-10-cm";
|
private final String myICD10URL = "http://hl7.org/fhir/sid/icd-10-cm";
|
||||||
private final String myICD10FileName = new File("src/test/resources").getAbsolutePath() + "/icd10cm_tabular_2021.xml";
|
private final String myICD10FileName = new File("src/test/resources").getAbsolutePath() + "/icd10cm_tabular_2021.xml";
|
||||||
private File myICD10File = new File(myICD10FileName);
|
private File myICD10File = new File(myICD10FileName);
|
||||||
private Server myServer;
|
|
||||||
private int myPort;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
protected ITermLoaderSvc myTermLoaderSvc;
|
protected ITermLoaderSvc myTermLoaderSvc;
|
||||||
|
@ -82,35 +81,43 @@ public class UploadTerminologyCommandTest {
|
||||||
System.setProperty("test", "true");
|
System.setProperty("test", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Stream<String> paramsProvider() {
|
static Stream<Arguments> paramsProvider(){
|
||||||
return Stream.of(FHIR_VERSION_DSTU3, FHIR_VERSION_R4);
|
return Stream.of(
|
||||||
|
// [0] theFhirVersion, [1] theIncludeTls
|
||||||
|
Arguments.arguments(FHIR_VERSION_DSTU3, true),
|
||||||
|
Arguments.arguments(FHIR_VERSION_DSTU3, false),
|
||||||
|
Arguments.arguments(FHIR_VERSION_R4, true),
|
||||||
|
Arguments.arguments(FHIR_VERSION_R4, false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public final RestServerDstu3Helper myRestServerDstu3Helper = new RestServerDstu3Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
private BaseRestServerHelper myBaseRestServerHelper;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeEach(TestInfo testInfo) throws Exception {
|
public void beforeEach(TestInfo testInfo) throws Exception {
|
||||||
writeConceptAndHierarchyFiles();
|
writeConceptAndHierarchyFiles();
|
||||||
if (testInfo.getDisplayName().endsWith(FHIR_VERSION_DSTU3)) {
|
if (testInfo.getDisplayName().contains(FHIR_VERSION_DSTU3)) {
|
||||||
myCtx = FhirContext.forDstu3();
|
myCtx = FhirContext.forDstu3();
|
||||||
} else if (testInfo.getDisplayName().endsWith(FHIR_VERSION_R4)) {
|
myRestServerDstu3Helper.registerProvider(new TerminologyUploaderProvider(myCtx, myTermLoaderSvc));
|
||||||
|
myBaseRestServerHelper = myRestServerDstu3Helper;
|
||||||
|
} else if (testInfo.getDisplayName().contains(FHIR_VERSION_R4)) {
|
||||||
myCtx = FhirContext.forR4();
|
myCtx = FhirContext.forR4();
|
||||||
|
myRestServerR4Helper.registerProvider(new TerminologyUploaderProvider(myCtx, myTermLoaderSvc));
|
||||||
|
myBaseRestServerHelper = myRestServerR4Helper;
|
||||||
} else {
|
} else {
|
||||||
fail("Unknown FHIR Version param provided: " + testInfo.getDisplayName());
|
fail("Unknown FHIR Version param provided: " + testInfo.getDisplayName());
|
||||||
}
|
}
|
||||||
myServer = new Server(0);
|
|
||||||
TerminologyUploaderProvider provider = new TerminologyUploaderProvider(myCtx, myTermLoaderSvc);
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
RestfulServer servlet = new RestfulServer(myCtx);
|
|
||||||
servlet.registerProvider(provider);
|
|
||||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
myServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(myServer);
|
|
||||||
myPort = JettyUtil.getPortForStartedServer(myServer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void afterEach() throws Exception {
|
public void afterEach() throws Exception {
|
||||||
JettyUtil.closeServer(myServer);
|
|
||||||
FileUtils.deleteQuietly(myConceptsFile);
|
FileUtils.deleteQuietly(myConceptsFile);
|
||||||
FileUtils.deleteQuietly(myHierarchyFile);
|
FileUtils.deleteQuietly(myHierarchyFile);
|
||||||
FileUtils.deleteQuietly(myCodeSystemFile);
|
FileUtils.deleteQuietly(myCodeSystemFile);
|
||||||
|
@ -122,7 +129,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAdd(String theFhirVersion) throws IOException {
|
public void testDeltaAdd(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
||||||
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
||||||
|
@ -131,15 +138,17 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myConceptsFileName,
|
"-d", myConceptsFileName,
|
||||||
"-d", myHierarchyFileName
|
"-d", myHierarchyFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -151,7 +160,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAddUsingCodeSystemResource(String theFhirVersion) throws IOException {
|
public void testDeltaAddUsingCodeSystemResource(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
try (FileWriter w = new FileWriter(myCodeSystemFile, false)) {
|
try (FileWriter w = new FileWriter(myCodeSystemFile, false)) {
|
||||||
org.hl7.fhir.dstu3.model.CodeSystem cs = new org.hl7.fhir.dstu3.model.CodeSystem();
|
org.hl7.fhir.dstu3.model.CodeSystem cs = new org.hl7.fhir.dstu3.model.CodeSystem();
|
||||||
|
@ -170,14 +179,16 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.r4.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.r4.model.IdType("CodeSystem/101")));
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myCodeSystemFileName
|
"-d", myCodeSystemFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -190,7 +201,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAddInvalidResource(String theFhirVersion) throws IOException {
|
public void testDeltaAddInvalidResource(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
try (FileWriter w = new FileWriter(myCodeSystemFile, false)) {
|
try (FileWriter w = new FileWriter(myCodeSystemFile, false)) {
|
||||||
org.hl7.fhir.dstu3.model.Patient patient = new org.hl7.fhir.dstu3.model.Patient();
|
org.hl7.fhir.dstu3.model.Patient patient = new org.hl7.fhir.dstu3.model.Patient();
|
||||||
|
@ -208,14 +219,16 @@ public class UploadTerminologyCommandTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myCodeSystemFileName
|
"-d", myCodeSystemFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
fail();
|
fail();
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
assertThat(e.toString(), containsString("HTTP 400 Bad Request: " + Msg.code(362) + "Request has parameter codeSystem of type Patient but method expects type CodeSystem"));
|
assertThat(e.toString(), containsString("HTTP 400 Bad Request: " + Msg.code(362) + "Request has parameter codeSystem of type Patient but method expects type CodeSystem"));
|
||||||
|
@ -224,20 +237,23 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAddInvalidFileType(String theFhirVersion) throws IOException {
|
public void testDeltaAddInvalidFileType(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
try (FileWriter w = new FileWriter(myTextFileName, false)) {
|
try (FileWriter w = new FileWriter(myTextFileName, false)) {
|
||||||
w.append("Help I'm a Bug");
|
w.append("Help I'm a Bug");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myTextFileName
|
"-d", myTextFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
fail();
|
fail();
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
assertThat(e.toString(), containsString("Don't know how to handle file:"));
|
assertThat(e.toString(), containsString("Don't know how to handle file:"));
|
||||||
|
@ -246,19 +262,21 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAddUsingCompressedFile(String theFhirVersion) throws IOException {
|
public void testDeltaAddUsingCompressedFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
writeArchiveFile(myConceptsFile, myHierarchyFile);
|
writeArchiveFile(myConceptsFile, myHierarchyFile);
|
||||||
|
|
||||||
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.r4.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadDeltaAdd(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.r4.model.IdType("CodeSystem/101")));
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myArchiveFileName
|
"-d", myArchiveFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadDeltaAdd(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -270,17 +288,20 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaAddInvalidFileName(String theFhirVersion) throws IOException {
|
public void testDeltaAddInvalidFileName(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
try {
|
try {
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "ADD",
|
"-m", "ADD",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myConceptsFileName + "/foo.csv",
|
"-d", myConceptsFileName + "/foo.csv",
|
||||||
"-d", myHierarchyFileName
|
"-d", myHierarchyFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
fail();
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
assertThat(e.toString(), Matchers.containsString("FileNotFoundException: target/concepts.csv/foo.csv"));
|
assertThat(e.toString(), Matchers.containsString("FileNotFoundException: target/concepts.csv/foo.csv"));
|
||||||
}
|
}
|
||||||
|
@ -288,7 +309,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testDeltaRemove(String theFhirVersion) throws IOException {
|
public void testDeltaRemove(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
when(myTermLoaderSvc.loadDeltaRemove(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadDeltaRemove(eq("http://foo"), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
||||||
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
||||||
|
@ -297,15 +318,17 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "REMOVE",
|
"-m", "REMOVE",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myConceptsFileName,
|
"-d", myConceptsFileName,
|
||||||
"-d", myHierarchyFileName
|
"-d", myHierarchyFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadDeltaRemove(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadDeltaRemove(eq("http://foo"), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -317,7 +340,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testSnapshot(String theFhirVersion) throws IOException {
|
public void testSnapshot(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
when(myTermLoaderSvc.loadCustom(any(), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadCustom(any(), anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
||||||
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
||||||
|
@ -326,15 +349,17 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "SNAPSHOT",
|
"-m", "SNAPSHOT",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myConceptsFileName,
|
"-d", myConceptsFileName,
|
||||||
"-d", myHierarchyFileName
|
"-d", myHierarchyFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -346,7 +371,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testPropertiesFile(String theFhirVersion) throws IOException {
|
public void testPropertiesFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
try (FileWriter w = new FileWriter(myPropertiesFileName, false)) {
|
try (FileWriter w = new FileWriter(myPropertiesFileName, false)) {
|
||||||
w.append("a=b\n");
|
w.append("a=b\n");
|
||||||
}
|
}
|
||||||
|
@ -359,14 +384,16 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "SNAPSHOT",
|
"-m", "SNAPSHOT",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myPropertiesFileName,
|
"-d", myPropertiesFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -378,7 +405,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testSnapshotLargeFile(String theFhirVersion) throws IOException {
|
public void testSnapshotLargeFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
UploadTerminologyCommand.setTransferSizeLimitForUnitTest(10);
|
UploadTerminologyCommand.setTransferSizeLimitForUnitTest(10);
|
||||||
|
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
|
@ -389,15 +416,17 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-m", "SNAPSHOT",
|
"-m", "SNAPSHOT",
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", "http://foo",
|
"-u", "http://foo",
|
||||||
"-d", myConceptsFileName,
|
"-d", myConceptsFileName,
|
||||||
"-d", myHierarchyFileName
|
"-d", myHierarchyFileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadCustom(any(), myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
@ -409,7 +438,7 @@ public class UploadTerminologyCommandTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testUploadICD10UsingCompressedFile(String theFhirVersion) throws IOException {
|
public void testUploadICD10UsingCompressedFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
when(myTermLoaderSvc.loadIcd10cm(anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadIcd10cm(anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
||||||
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
||||||
|
@ -418,13 +447,15 @@ public class UploadTerminologyCommandTest {
|
||||||
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
fail("Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.main(new String[]{
|
App.main(myTlsAuthenticationTestHelper.createBaseRequestGeneratingCommandArgs(
|
||||||
|
new String[]{
|
||||||
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
UploadTerminologyCommand.UPLOAD_TERMINOLOGY,
|
||||||
"-v", theFhirVersion,
|
"-v", theFhirVersion,
|
||||||
"-t", "http://localhost:" + myPort,
|
|
||||||
"-u", myICD10URL,
|
"-u", myICD10URL,
|
||||||
"-d", myICD10FileName
|
"-d", myICD10FileName
|
||||||
});
|
},
|
||||||
|
"-t", theIncludeTls, myBaseRestServerHelper
|
||||||
|
));
|
||||||
|
|
||||||
verify(myTermLoaderSvc, times(1)).loadIcd10cm(myDescriptorListCaptor.capture(), any());
|
verify(myTermLoaderSvc, times(1)).loadIcd10cm(myDescriptorListCaptor.capture(), any());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
package ca.uhn.fhir.cli.client;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class HapiFhirCliRestfulClientFactoryTest extends BaseFhirVersionParameterizedTest{
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) throws Exception {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
HapiFhirCliRestfulClientFactory clientFactory = new HapiFhirCliRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
HttpClient client = clientFactory.getNativeHttpClient();
|
||||||
|
|
||||||
|
HttpUriRequest request = new HttpGet(fhirVersionParams.getPatientEndpoint());
|
||||||
|
HttpResponse response = client.execute(request);
|
||||||
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
String json = EntityUtils.toString(response.getEntity());
|
||||||
|
IBaseResource bundle = fhirVersionParams.parseResource(json);
|
||||||
|
assertEquals(fhirVersionParams.getFhirVersion(), bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttps(FhirVersionEnum theFhirVersion) throws Exception {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
HapiFhirCliRestfulClientFactory clientFactory = new HapiFhirCliRestfulClientFactory(fhirVersionParams.getFhirContext(), getTlsAuthentication());
|
||||||
|
HttpClient authenticatedClient = clientFactory.getNativeHttpClient();
|
||||||
|
|
||||||
|
HttpUriRequest request = new HttpGet(fhirVersionParams.getSecuredPatientEndpoint());
|
||||||
|
HttpResponse response = authenticatedClient.execute(request);
|
||||||
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
String json = EntityUtils.toString(response.getEntity());
|
||||||
|
IBaseResource bundle = fhirVersionParams.parseResource(json);
|
||||||
|
assertEquals(fhirVersionParams.getFhirVersion(), bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
HapiFhirCliRestfulClientFactory clientFactory = new HapiFhirCliRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
HttpClient unauthenticatedClient = clientFactory.getNativeHttpClient();
|
||||||
|
|
||||||
|
try{
|
||||||
|
HttpUriRequest request = new HttpGet(fhirVersionParams.getSecuredPatientEndpoint());
|
||||||
|
unauthenticatedClient.execute(request);
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttp(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String base = fhirVersionParams.getBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new HapiFhirCliRestfulClientFactory(context));
|
||||||
|
IBaseResource bundle = context.newRestfulGenericClient(base).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttps(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String secureBase = fhirVersionParams.getSecureBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new HapiFhirCliRestfulClientFactory(context, getTlsAuthentication()));
|
||||||
|
IBaseResource bundle = context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String secureBase = fhirVersionParams.getSecureBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new HapiFhirCliRestfulClientFactory(context));
|
||||||
|
try {
|
||||||
|
context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertTrue(e.getMessage().contains("HAPI-1357: Failed to retrieve the server metadata statement during client initialization"));
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getCause().getCause().getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientProtocolChanges(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
String secureBase = fhirVersionParams.getSecureBase();
|
||||||
|
String base = fhirVersionParams.getBase();
|
||||||
|
|
||||||
|
// https
|
||||||
|
HapiFhirCliRestfulClientFactory restfulClientFactory = new HapiFhirCliRestfulClientFactory(context, getTlsAuthentication());
|
||||||
|
context.setRestfulClientFactory(restfulClientFactory);
|
||||||
|
IBaseResource bundle = context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
|
||||||
|
// http
|
||||||
|
restfulClientFactory.useHttp();
|
||||||
|
bundle = context.newRestfulGenericClient(base).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
|
||||||
|
// https
|
||||||
|
restfulClientFactory.useHttps(getTlsAuthentication());
|
||||||
|
bundle = context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testSetHttpClient(FhirVersionEnum theFhirVersion){
|
||||||
|
try {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
FhirContext fhirContext = fhirVersionParams.getFhirContext();
|
||||||
|
HapiFhirCliRestfulClientFactory hapiFhirCliRestfulClientFactory = new HapiFhirCliRestfulClientFactory(fhirContext);
|
||||||
|
hapiFhirCliRestfulClientFactory.setHttpClient(new Object());
|
||||||
|
} catch (UnsupportedOperationException e){
|
||||||
|
assertEquals(Msg.code(2119), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testSetProxy(FhirVersionEnum theFhirVersion){
|
||||||
|
try {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
FhirContext fhirContext = fhirVersionParams.getFhirContext();
|
||||||
|
HapiFhirCliRestfulClientFactory hapiFhirCliRestfulClientFactory = new HapiFhirCliRestfulClientFactory(fhirContext);
|
||||||
|
hapiFhirCliRestfulClientFactory.setProxy("proxy", 1);
|
||||||
|
} catch (UnsupportedOperationException e){
|
||||||
|
assertEquals(Msg.code(2120), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-cli</artifactId>
|
<artifactId>hapi-fhir-cli</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -57,6 +57,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Unit test dependencies -->
|
<!-- Unit test dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -27,12 +27,15 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.client.api.Header;
|
import ca.uhn.fhir.rest.client.api.Header;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Restful client factory based on OkHttp.
|
* A Restful client factory based on OkHttp.
|
||||||
|
@ -53,7 +56,7 @@ public class OkHttpRestfulClientFactory extends RestfulClientFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IHttpClient getHttpClient(String theServerBase) {
|
protected IHttpClient getHttpClient(String theServerBase) {
|
||||||
return new OkHttpRestfulClient(getNativeClient(), new StringBuilder(theServerBase), null, null, null, null);
|
return getHttpClient(new StringBuilder(theServerBase), null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
package ca.uhn.fhir.okhttp;
|
package ca.uhn.fhir.okhttp;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class OkHttpRestfulClientFactoryTest {
|
public class OkHttpRestfulClientFactoryTest extends BaseFhirVersionParameterizedTest {
|
||||||
|
|
||||||
private OkHttpRestfulClientFactory clientFactory;
|
private OkHttpRestfulClientFactory clientFactory;
|
||||||
|
|
||||||
|
@ -46,14 +60,77 @@ public class OkHttpRestfulClientFactoryTest {
|
||||||
public void testSocketTimeout() {
|
public void testSocketTimeout() {
|
||||||
clientFactory.setSocketTimeout(1515);
|
clientFactory.setSocketTimeout(1515);
|
||||||
|
|
||||||
assertEquals(1515, ((OkHttpClient)clientFactory.getNativeClient()).readTimeoutMillis());
|
assertEquals(1515, ((OkHttpClient) clientFactory.getNativeClient()).readTimeoutMillis());
|
||||||
assertEquals(1515, ((OkHttpClient)clientFactory.getNativeClient()).writeTimeoutMillis());
|
assertEquals(1515, ((OkHttpClient) clientFactory.getNativeClient()).writeTimeoutMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConnectTimeout() {
|
public void testConnectTimeout() {
|
||||||
clientFactory.setConnectTimeout(1516);
|
clientFactory.setConnectTimeout(1516);
|
||||||
|
|
||||||
assertEquals(1516, ((OkHttpClient)clientFactory.getNativeClient()).connectTimeoutMillis());
|
assertEquals(1516, ((OkHttpClient) clientFactory.getNativeClient()).connectTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) throws Exception {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
OkHttpRestfulClientFactory clientFactory = new OkHttpRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
OkHttpClient client = (OkHttpClient) clientFactory.getNativeClient();
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(fhirVersionParams.getPatientEndpoint())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
assertEquals(200, response.code());
|
||||||
|
String json = response.body().string();
|
||||||
|
IBaseResource bundle = fhirVersionParams.getFhirContext().newJsonParser().parseResource(json);
|
||||||
|
assertEquals(fhirVersionParams.getFhirVersion(), bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
OkHttpRestfulClientFactory clientFactory = new OkHttpRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
OkHttpClient unauthenticatedClient = (OkHttpClient) clientFactory.getNativeClient();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(fhirVersionParams.getSecuredPatientEndpoint())
|
||||||
|
.build();
|
||||||
|
unauthenticatedClient.newCall(request).execute();
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttp(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String base = fhirVersionParams.getBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new OkHttpRestfulClientFactory(context));
|
||||||
|
IBaseResource bundle = context.newRestfulGenericClient(base).search().forResource("Patient").execute();
|
||||||
|
assertEquals(theFhirVersion, bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testGenericClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
String secureBase = fhirVersionParams.getSecureBase();
|
||||||
|
FhirContext context = fhirVersionParams.getFhirContext();
|
||||||
|
context.setRestfulClientFactory(new OkHttpRestfulClientFactory(context));
|
||||||
|
try {
|
||||||
|
context.newRestfulGenericClient(secureBase).search().forResource("Patient").execute();
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertTrue(e.getMessage().contains("HAPI-1357: Failed to retrieve the server metadata statement during client initialization"));
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getCause().getCause().getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ package ca.uhn.fhir.rest.client.apache;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.List;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import java.util.Map;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import java.util.concurrent.TimeUnit;
|
import ca.uhn.fhir.rest.client.api.Header;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.auth.AuthScope;
|
import org.apache.http.auth.AuthScope;
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
|
@ -37,11 +37,11 @@ import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
|
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.util.List;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import java.util.Map;
|
||||||
import ca.uhn.fhir.rest.client.api.Header;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
|
||||||
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Restful Factory to create clients, requests and responses based on the Apache httpclient library.
|
* A Restful Factory to create clients, requests and responses based on the Apache httpclient library.
|
||||||
|
@ -71,25 +71,19 @@ public class ApacheRestfulClientFactory extends RestfulClientFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized ApacheHttpClient getHttpClient(String theServerBase) {
|
protected synchronized IHttpClient getHttpClient(String theServerBase) {
|
||||||
return new ApacheHttpClient(getNativeHttpClient(), new StringBuilder(theServerBase), null, null, null, null);
|
return getHttpClient(new StringBuilder(theServerBase), null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
|
public synchronized IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
|
||||||
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||||
return new ApacheHttpClient(getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType,
|
return new ApacheHttpClient(getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
|
||||||
theHeaders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpClient getNativeHttpClient() {
|
public HttpClient getNativeHttpClient() {
|
||||||
if (myHttpClient == null) {
|
if (myHttpClient == null) {
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000,
|
|
||||||
TimeUnit.MILLISECONDS);
|
|
||||||
connectionManager.setMaxTotal(getPoolMaxTotal());
|
|
||||||
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
|
||||||
|
|
||||||
//TODO: Use of a deprecated method should be resolved.
|
//TODO: Use of a deprecated method should be resolved.
|
||||||
RequestConfig defaultRequestConfig =
|
RequestConfig defaultRequestConfig =
|
||||||
RequestConfig.custom()
|
RequestConfig.custom()
|
||||||
|
@ -102,11 +96,15 @@ public class ApacheRestfulClientFactory extends RestfulClientFactory {
|
||||||
|
|
||||||
HttpClientBuilder builder = getHttpClientBuilder()
|
HttpClientBuilder builder = getHttpClientBuilder()
|
||||||
.useSystemProperties()
|
.useSystemProperties()
|
||||||
.setConnectionManager(connectionManager)
|
|
||||||
.setDefaultRequestConfig(defaultRequestConfig)
|
.setDefaultRequestConfig(defaultRequestConfig)
|
||||||
.disableCookieManagement();
|
.disableCookieManagement();
|
||||||
|
|
||||||
if (myProxy != null && StringUtils.isNotBlank(getProxyUsername()) && StringUtils.isNotBlank(getProxyPassword())) {
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
connectionManager.setMaxTotal(getPoolMaxTotal());
|
||||||
|
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
|
||||||
|
if (myProxy != null && isNotBlank(getProxyUsername()) && isNotBlank(getProxyPassword())) {
|
||||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||||
credsProvider.setCredentials(new AuthScope(myProxy.getHostName(), myProxy.getPort()),
|
credsProvider.setCredentials(new AuthScope(myProxy.getHostName(), myProxy.getPort()),
|
||||||
new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword()));
|
new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword()));
|
||||||
|
|
|
@ -19,25 +19,35 @@ package ca.uhn.fhir.rest.client.impl;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||||
|
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||||
|
import ca.uhn.fhir.rest.client.method.BaseMethodBinding;
|
||||||
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.*;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import java.lang.reflect.Method;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import java.lang.reflect.Proxy;
|
||||||
import ca.uhn.fhir.rest.client.api.*;
|
import java.util.Collections;
|
||||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
import java.util.HashMap;
|
||||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
import java.util.HashSet;
|
||||||
import ca.uhn.fhir.rest.client.method.BaseMethodBinding;
|
import java.util.Map;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for a REST client factory implementation
|
* Base class for a REST client factory implementation
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
package ca.uhn.fhir.rest.client.tls;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.PathType;
|
||||||
|
import ca.uhn.fhir.tls.StoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import ca.uhn.fhir.tls.TrustStoreInfo;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
|
||||||
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||||
|
import org.apache.http.ssl.PrivateKeyStrategy;
|
||||||
|
import org.apache.http.ssl.SSLContextBuilder;
|
||||||
|
import org.apache.http.ssl.SSLContexts;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
public class TlsAuthenticationSvc {
|
||||||
|
|
||||||
|
private TlsAuthenticationSvc(){}
|
||||||
|
|
||||||
|
public static SSLContext createSslContext(@Nonnull TlsAuthentication theTlsAuthentication){
|
||||||
|
Validate.notNull(theTlsAuthentication, "theTlsAuthentication cannot be null");
|
||||||
|
|
||||||
|
try{
|
||||||
|
SSLContextBuilder contextBuilder = SSLContexts.custom();
|
||||||
|
|
||||||
|
if(theTlsAuthentication.getKeyStoreInfo().isPresent()){
|
||||||
|
KeyStoreInfo keyStoreInfo = theTlsAuthentication.getKeyStoreInfo().get();
|
||||||
|
PrivateKeyStrategy privateKeyStrategy = null;
|
||||||
|
if(isNotBlank(keyStoreInfo.getAlias())){
|
||||||
|
privateKeyStrategy = (aliases, socket) -> keyStoreInfo.getAlias();
|
||||||
|
}
|
||||||
|
KeyStore keyStore = createKeyStore(keyStoreInfo);
|
||||||
|
contextBuilder.loadKeyMaterial(keyStore, keyStoreInfo.getKeyPass(), privateKeyStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(theTlsAuthentication.getTrustStoreInfo().isPresent()){
|
||||||
|
TrustStoreInfo trustStoreInfo = theTlsAuthentication.getTrustStoreInfo().get();
|
||||||
|
KeyStore trustStore = createKeyStore(trustStoreInfo);
|
||||||
|
contextBuilder.loadTrustMaterial(trustStore, TrustSelfSignedStrategy.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contextBuilder.build();
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
throw new TlsAuthenticationException(Msg.code(2102)+"Failed to create SSLContext", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyStore createKeyStore(StoreInfo theStoreInfo){
|
||||||
|
try {
|
||||||
|
KeyStore keyStore = KeyStore.getInstance(theStoreInfo.getType().toString());
|
||||||
|
|
||||||
|
if(PathType.RESOURCE.equals(theStoreInfo.getPathType())){
|
||||||
|
try(InputStream inputStream = TlsAuthenticationSvc.class.getResourceAsStream(theStoreInfo.getFilePath())){
|
||||||
|
validateKeyStoreExists(inputStream);
|
||||||
|
keyStore.load(inputStream, theStoreInfo.getStorePass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(PathType.FILE.equals(theStoreInfo.getPathType())){
|
||||||
|
try(InputStream inputStream = new FileInputStream(theStoreInfo.getFilePath())){
|
||||||
|
validateKeyStoreExists(inputStream);
|
||||||
|
keyStore.load(inputStream, theStoreInfo.getStorePass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyStore;
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
throw new TlsAuthenticationException(Msg.code(2103)+"Failed to create KeyStore", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateKeyStoreExists(InputStream theInputStream){
|
||||||
|
if(theInputStream == null){
|
||||||
|
throw new TlsAuthenticationException(Msg.code(2116)+"Keystore does not exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static X509TrustManager createTrustManager(Optional<TrustStoreInfo> theTrustStoreInfo) {
|
||||||
|
try {
|
||||||
|
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
if (theTrustStoreInfo.isEmpty()) {
|
||||||
|
trustManagerFactory.init((KeyStore) null); // Load Trust Manager Factory with default Java truststore
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TrustStoreInfo trustStoreInfo = theTrustStoreInfo.get();
|
||||||
|
KeyStore trustStore = createKeyStore(trustStoreInfo);
|
||||||
|
trustManagerFactory.init(trustStore);
|
||||||
|
}
|
||||||
|
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
|
||||||
|
if (trustManager instanceof X509TrustManager) {
|
||||||
|
return (X509TrustManager) trustManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new TlsAuthenticationException(Msg.code(2104)+"Could not find X509TrustManager");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new TlsAuthenticationException(Msg.code(2105)+"Failed to create X509TrustManager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HostnameVerifier createHostnameVerifier(Optional<TrustStoreInfo> theTrustStoreInfo){
|
||||||
|
return theTrustStoreInfo.isPresent() ? new DefaultHostnameVerifier() : new NoopHostnameVerifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TlsAuthenticationException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1l;
|
||||||
|
|
||||||
|
public TlsAuthenticationException(String theMessage, Throwable theCause) {
|
||||||
|
super(theMessage, theCause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TlsAuthenticationException(String theMessage) {
|
||||||
|
super(theMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package ca.uhn.fhir.rest.client.tls;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreType;
|
||||||
|
import ca.uhn.fhir.tls.PathType;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class StoreInfoTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPathTypeFile(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertEquals("/my-file.p12", keyStoreInfo.getFilePath());
|
||||||
|
assertEquals(PathType.FILE, keyStoreInfo.getPathType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPathTypeResource(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("classpath:/my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertEquals("/my-file.p12", keyStoreInfo.getFilePath());
|
||||||
|
assertEquals(PathType.RESOURCE, keyStoreInfo.getPathType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPathTypeInvalid(){
|
||||||
|
try {
|
||||||
|
new KeyStoreInfo("invalid:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2117)+"Invalid path prefix", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFileTypeP12(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertEquals(KeyStoreType.PKCS12, keyStoreInfo.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFileTypeJks(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.jks", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertEquals(KeyStoreType.JKS, keyStoreInfo.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFileTypeInvalid(){
|
||||||
|
try {
|
||||||
|
new KeyStoreInfo("file:///my-file.invalid", "storePassword" , "keyPassword", "alias");
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2121)+"Invalid KeyStore Type", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStorePass(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertTrue(StringUtils.equals("storePassword", new String(keyStoreInfo.getStorePass())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeyPass(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertTrue(StringUtils.equals("keyPassword", new String(keyStoreInfo.getKeyPass())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAlias(){
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("file:///my-file.p12", "storePassword" , "keyPassword", "alias");
|
||||||
|
assertEquals("alias", keyStoreInfo.getAlias());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
package ca.uhn.fhir.rest.client.tls;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import ca.uhn.fhir.tls.TrustStoreInfo;
|
||||||
|
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
|
||||||
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class TlsAuthenticationSvcTest {
|
||||||
|
|
||||||
|
private KeyStoreInfo myServerKeyStoreInfo;
|
||||||
|
private TrustStoreInfo myServerTrustStoreInfo;
|
||||||
|
private TlsAuthentication myServerTlsAuthentication;
|
||||||
|
|
||||||
|
private KeyStoreInfo myClientKeyStoreInfo;
|
||||||
|
private TrustStoreInfo myClientTrustStoreInfo;
|
||||||
|
private TlsAuthentication myClientTlsAuthentication;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void beforeEach(){
|
||||||
|
myServerKeyStoreInfo = new KeyStoreInfo("classpath:/server-keystore.p12", "changeit", "changeit", "server");
|
||||||
|
myServerTrustStoreInfo = new TrustStoreInfo("classpath:/server-truststore.p12", "changeit", "client");
|
||||||
|
myServerTlsAuthentication = new TlsAuthentication(Optional.of(myServerKeyStoreInfo), Optional.of(myServerTrustStoreInfo));
|
||||||
|
|
||||||
|
myClientKeyStoreInfo = new KeyStoreInfo("classpath:/client-keystore.p12", "changeit", "changeit", "client");
|
||||||
|
myClientTrustStoreInfo = new TrustStoreInfo("classpath:/client-truststore.p12", "changeit", "server");
|
||||||
|
myClientTlsAuthentication = new TlsAuthentication(Optional.of(myClientKeyStoreInfo), Optional.of(myClientTrustStoreInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSslContextEmpty(){
|
||||||
|
TlsAuthentication emptyAuthentication = null;
|
||||||
|
try {
|
||||||
|
TlsAuthenticationSvc.createSslContext(emptyAuthentication);
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals("theTlsAuthentication cannot be null", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSslContextPresent(){
|
||||||
|
SSLContext result = TlsAuthenticationSvc.createSslContext(myServerTlsAuthentication);
|
||||||
|
assertEquals("TLS", result.getProtocol());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSslContextPresentInvalid(){
|
||||||
|
KeyStoreInfo invalidKeyStoreInfo = new KeyStoreInfo("file:///INVALID.p12", "changeit", "changeit", "server");
|
||||||
|
TlsAuthentication invalidTlsAuthentication = new TlsAuthentication(Optional.of(invalidKeyStoreInfo), Optional.of(myServerTrustStoreInfo));
|
||||||
|
try {
|
||||||
|
TlsAuthenticationSvc.createSslContext(invalidTlsAuthentication);
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2102)+"Failed to create SSLContext", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateKeyStoreP12() throws Exception {
|
||||||
|
KeyStore keyStore = TlsAuthenticationSvc.createKeyStore(myServerKeyStoreInfo);
|
||||||
|
assertNotNull(keyStore.getKey(myServerKeyStoreInfo.getAlias(), myServerKeyStoreInfo.getKeyPass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateKeyStoreJKS() throws Exception {
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("classpath:/keystore.jks", "changeit", "changeit", "client");
|
||||||
|
KeyStore keyStore = TlsAuthenticationSvc.createKeyStore(keyStoreInfo);
|
||||||
|
assertNotNull(keyStore.getKey(keyStoreInfo.getAlias(), keyStoreInfo.getKeyPass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateKeyStoreNonExistentFile() {
|
||||||
|
KeyStoreInfo keyStoreInfo = new KeyStoreInfo("classpath:/non-existent.p12", "changeit", "changeit", "server");
|
||||||
|
try {
|
||||||
|
TlsAuthenticationSvc.createKeyStore(keyStoreInfo);
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2103)+"Failed to create KeyStore", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustStoreJks() throws Exception {
|
||||||
|
TrustStoreInfo trustStoreInfo = new TrustStoreInfo("classpath:/truststore.jks", "changeit", "client");
|
||||||
|
KeyStore keyStore = TlsAuthenticationSvc.createKeyStore(trustStoreInfo);
|
||||||
|
assertNotNull(keyStore.getCertificate(trustStoreInfo.getAlias()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustStoreP12() throws Exception {
|
||||||
|
KeyStore keyStore = TlsAuthenticationSvc.createKeyStore(myServerTrustStoreInfo);
|
||||||
|
assertNotNull(keyStore.getCertificate(myServerTrustStoreInfo.getAlias()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustStoreNonExistentFile() throws Exception {
|
||||||
|
TrustStoreInfo trustStoreInfo = new TrustStoreInfo("classpath:/non-existent.p12", "changeit", "server");
|
||||||
|
try {
|
||||||
|
TlsAuthenticationSvc.createKeyStore(trustStoreInfo);
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2103)+"Failed to create KeyStore", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustManager() throws Exception {
|
||||||
|
X509TrustManager trustManager = TlsAuthenticationSvc.createTrustManager(Optional.of(myClientTrustStoreInfo));
|
||||||
|
KeyStore keyStore = TlsAuthenticationSvc.createKeyStore(myServerKeyStoreInfo);
|
||||||
|
Certificate serverCertificate = keyStore.getCertificate(myServerKeyStoreInfo.getAlias());
|
||||||
|
|
||||||
|
assertEquals(1, trustManager.getAcceptedIssuers().length);
|
||||||
|
assertEquals(serverCertificate, trustManager.getAcceptedIssuers()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustManagerNoTrustStore() {
|
||||||
|
// trust manager should contain common certifications if no trust store information is used
|
||||||
|
X509TrustManager trustManager = TlsAuthenticationSvc.createTrustManager(Optional.empty());
|
||||||
|
assertNotEquals(0, trustManager.getAcceptedIssuers().length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTrustManagerInvalid() {
|
||||||
|
TrustStoreInfo invalidKeyStoreInfo = new TrustStoreInfo("file:///INVALID.p12", "changeit", "client");
|
||||||
|
try {
|
||||||
|
TlsAuthenticationSvc.createTrustManager(Optional.of(invalidKeyStoreInfo));
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(Msg.code(2105)+"Failed to create X509TrustManager", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateHostnameVerifierEmptyTrustStoreInfo(){
|
||||||
|
Optional<TrustStoreInfo> trustStoreInfo = Optional.empty();
|
||||||
|
HostnameVerifier result = TlsAuthenticationSvc.createHostnameVerifier(trustStoreInfo);
|
||||||
|
assertEquals(NoopHostnameVerifier.class, result.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateHostnameVerifierPresentTrustStoreInfo(){
|
||||||
|
Optional<TrustStoreInfo> trustStoreInfo = Optional.of(myServerTrustStoreInfo);
|
||||||
|
HostnameVerifier result = TlsAuthenticationSvc.createHostnameVerifier(trustStoreInfo);
|
||||||
|
assertEquals(DefaultHostnameVerifier.class, result.getClass());
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 3776
|
||||||
|
jira: SMILE-651
|
||||||
|
title: "Previously, the HAPI FHIR CLI commands that made HTTP requests could only be used for HTTP endpoints.
|
||||||
|
This feature adds support for HTTPS endpoints by using TLS authentication for `ExampleDataUploader`,
|
||||||
|
`ExportConceptMapToCsvCommand`, `ImportCsvToConceptMapCommand`, `ReindexTerminologyCommand` and
|
||||||
|
`UploadTerminologyCommand`."
|
|
@ -11,7 +11,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
package ca.uhn.fhir.jaxrs.client;
|
package ca.uhn.fhir.jaxrs.client;
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.Client;
|
|
||||||
import javax.ws.rs.client.ClientBuilder;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JAX-RS Server
|
* HAPI FHIR JAX-RS Server
|
||||||
|
@ -28,10 +21,20 @@ import javax.ws.rs.client.ClientBuilder;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.client.api.Header;
|
import ca.uhn.fhir.rest.client.api.Header;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.tls.TlsAuthenticationSvc;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.ws.rs.client.Client;
|
||||||
|
import javax.ws.rs.client.ClientBuilder;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Restful Client Factory, based on Jax Rs
|
* A Restful Client Factory, based on Jax Rs
|
||||||
|
|
|
@ -1,29 +1,44 @@
|
||||||
package ca.uhn.fhir.jaxrs.client;
|
package ca.uhn.fhir.jaxrs.client;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
|
import com.google.common.net.MediaType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import javax.ws.rs.client.Client;
|
import javax.ws.rs.client.Client;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.hasItem;
|
import static org.hamcrest.CoreMatchers.hasItem;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.core.IsNot.not;
|
import static org.hamcrest.core.IsNot.not;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Sebastien Riviere on 31/07/2017.
|
* Created by Sebastien Riviere on 31/07/2017.
|
||||||
*/
|
*/
|
||||||
public class JaxRsRestfulClientFactoryTest {
|
public class JaxRsRestfulClientFactoryTest extends BaseFhirVersionParameterizedTest {
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(JaxRsRestfulClientFactoryTest.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(JaxRsRestfulClientFactoryTest.class);
|
||||||
private final FhirContext context = FhirContext.forDstu2();
|
private final FhirContext context = FhirContext.forDstu2();
|
||||||
private JaxRsRestfulClientFactory factory;
|
private JaxRsRestfulClientFactory factory;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void beforeEach() throws Exception {
|
||||||
|
factory = new JaxRsRestfulClientFactory(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptyConstructorTest() {
|
public void emptyConstructorTest() {
|
||||||
assertNotNull(new JaxRsRestfulClientFactory());
|
assertNotNull(new JaxRsRestfulClientFactory());
|
||||||
|
@ -52,8 +67,39 @@ public class JaxRsRestfulClientFactoryTest {
|
||||||
assertThat(result.getConfiguration().getClasses(), hasItem(ca.uhn.fhir.jaxrs.client.MyFilter.class));
|
assertThat(result.getConfiguration().getClasses(), hasItem(ca.uhn.fhir.jaxrs.client.MyFilter.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@ParameterizedTest
|
||||||
public void setUp() {
|
@MethodSource("baseParamsProvider")
|
||||||
factory = new JaxRsRestfulClientFactory(context);
|
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
JaxRsRestfulClientFactory factory = new JaxRsRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
Client client = factory.getNativeClientClient();
|
||||||
|
|
||||||
|
Response response = client
|
||||||
|
.target(fhirVersionParams.getPatientEndpoint())
|
||||||
|
.request(MediaType.JSON_UTF_8.toString())
|
||||||
|
.get(Response.class);
|
||||||
|
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
String json = response.readEntity(String.class);
|
||||||
|
IBaseResource bundle = fhirVersionParams.parseResource(json);
|
||||||
|
assertEquals(fhirVersionParams.getFhirVersion(), bundle.getStructureFhirVersionEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testNativeClientHttpsNoCredentials(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
JaxRsRestfulClientFactory factory = new JaxRsRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
Client unauthenticatedClient = factory.getNativeClientClient();
|
||||||
|
|
||||||
|
try {
|
||||||
|
unauthenticatedClient
|
||||||
|
.target(fhirVersionParams.getSecuredPatientEndpoint())
|
||||||
|
.request(MediaType.JSON_UTF_8.toString())
|
||||||
|
.get(Response.class);
|
||||||
|
fail();
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(SSLHandshakeException.class, e.getCause().getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -38,6 +38,12 @@
|
||||||
<version>${fhir_core_version}</version>
|
<version>${fhir_core_version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>org.hl7.fhir.dstu3</artifactId>
|
||||||
|
<version>${fhir_core_version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- General -->
|
<!-- General -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
@ -173,6 +179,15 @@
|
||||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<nonFilteredFileExtensions>
|
||||||
|
<nonFilteredFileExtension>p12</nonFilteredFileExtension>
|
||||||
|
</nonFilteredFileExtensions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package ca.uhn.fhir.test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
|
import ca.uhn.fhir.test.utilities.BaseRestServerHelper;
|
||||||
|
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
||||||
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class BaseFhirVersionParameterizedTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final RestServerR4Helper myRestServerR4Helper = new RestServerR4Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public final RestServerDstu3Helper myRestServerDstu3Helper = new RestServerDstu3Helper(true);
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
protected final FhirContext myR4FhirContext = FhirContext.forR4();
|
||||||
|
protected final FhirContext myDstu3FhirContext = FhirContext.forDstu3();
|
||||||
|
|
||||||
|
protected static Stream<Arguments> baseParamsProvider(){
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.arguments(FhirVersionEnum.R4),
|
||||||
|
Arguments.arguments(FhirVersionEnum.DSTU3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FhirVersionParams getFhirVersionParams(FhirVersionEnum theFhirVersion){
|
||||||
|
switch(theFhirVersion){
|
||||||
|
case R4:
|
||||||
|
return new FhirVersionParams(myRestServerR4Helper, myR4FhirContext);
|
||||||
|
case DSTU3:
|
||||||
|
return new FhirVersionParams(myRestServerDstu3Helper, myDstu3FhirContext);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException(Msg.code(2114)+"Unknown FHIR Version param provided: " + theFhirVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TlsAuthentication getTlsAuthentication(){
|
||||||
|
return myTlsAuthenticationTestHelper.getTlsAuthentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class FhirVersionParams {
|
||||||
|
private final BaseRestServerHelper myBaseRestServerHelper;
|
||||||
|
private final FhirContext myFhirContext;
|
||||||
|
private final FhirVersionEnum myFhirVersion;
|
||||||
|
|
||||||
|
public FhirVersionParams(BaseRestServerHelper theBaseRestServerHelper, FhirContext theFhirContext) {
|
||||||
|
myBaseRestServerHelper = theBaseRestServerHelper;
|
||||||
|
myFhirContext = theFhirContext;
|
||||||
|
myFhirVersion = theFhirContext.getVersion().getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FhirContext getFhirContext() {
|
||||||
|
return myFhirContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FhirVersionEnum getFhirVersion() {
|
||||||
|
return myFhirVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBase(){
|
||||||
|
return myBaseRestServerHelper.getBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecureBase(){
|
||||||
|
return myBaseRestServerHelper.getSecureBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPatientEndpoint(){
|
||||||
|
return getBase()+"/Patient";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecuredPatientEndpoint(){
|
||||||
|
return getSecureBase()+"/Patient";
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBaseResource parseResource(String json){
|
||||||
|
return myFhirContext.newJsonParser().parseResource(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
package ca.uhn.fhir.test.utilities;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreType;
|
||||||
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
|
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class BaseRestServerHelper {
|
||||||
|
|
||||||
|
private final String SERVER_KEYSTORE_PATH = "/tls/server-keystore.p12";
|
||||||
|
private final String SERVER_TRUSTSTORE_PATH = "/tls/server-truststore.p12";
|
||||||
|
private final String PASSWORD = "changeit";
|
||||||
|
|
||||||
|
protected final FhirContext myFhirContext;
|
||||||
|
protected int myListenerPort;
|
||||||
|
protected int myHttpsListenerPort;
|
||||||
|
protected Server myListenerServer;
|
||||||
|
protected String myBase;
|
||||||
|
protected String mySecureBase;
|
||||||
|
protected IGenericClient myClient;
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public TlsAuthenticationTestHelper myTlsAuthenticationTestHelper = new TlsAuthenticationTestHelper();
|
||||||
|
|
||||||
|
public BaseRestServerHelper(FhirContext theFhirContext) {
|
||||||
|
myFhirContext = theFhirContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void afterEach() throws Exception {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IGenericClient getClient() {
|
||||||
|
return myClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startServer(Servlet theServlet) throws Exception {
|
||||||
|
myListenerServer = new Server(0);
|
||||||
|
|
||||||
|
myFhirContext.getRestfulClientFactory().setSocketTimeout(120000);
|
||||||
|
|
||||||
|
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||||
|
proxyHandler.setContextPath("/");
|
||||||
|
|
||||||
|
ServletHolder targetServletHolder = new ServletHolder();
|
||||||
|
targetServletHolder.setServlet(theServlet);
|
||||||
|
proxyHandler.addServlet(targetServletHolder, "/target/*");
|
||||||
|
|
||||||
|
myListenerServer.setHandler(proxyHandler);
|
||||||
|
|
||||||
|
SslContextFactory sslContextFactory = getSslContextFactory();
|
||||||
|
|
||||||
|
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||||
|
httpsConfig.setSecureScheme("https");
|
||||||
|
httpsConfig.setSecurePort(0);
|
||||||
|
|
||||||
|
ServerConnector sslConnector = new ServerConnector(myListenerServer,
|
||||||
|
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
|
||||||
|
new HttpConnectionFactory(httpsConfig));
|
||||||
|
sslConnector.setPort(0);
|
||||||
|
|
||||||
|
myListenerServer.addConnector(sslConnector);
|
||||||
|
myListenerServer.start();
|
||||||
|
|
||||||
|
assignHttpAndHttpsPorts();
|
||||||
|
|
||||||
|
myBase = "http://localhost:" + myListenerPort + "/target";
|
||||||
|
mySecureBase = "https://localhost:" + myHttpsListenerPort + "/target";
|
||||||
|
|
||||||
|
myFhirContext.getRestfulClientFactory().setConnectTimeout(60000);
|
||||||
|
myFhirContext.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
|
|
||||||
|
myClient = myFhirContext.newRestfulGenericClient(myBase);
|
||||||
|
myClient.registerInterceptor(new LoggingInterceptor(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assignHttpAndHttpsPorts() {
|
||||||
|
myListenerPort = ((ServerConnector)myListenerServer.getConnectors()[0]).getLocalPort();
|
||||||
|
myHttpsListenerPort = ((ServerConnector)myListenerServer.getConnectors()[1]).getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SslContextFactory getSslContextFactory() throws Exception{
|
||||||
|
try {
|
||||||
|
SslContextFactory sslContextFactory = new SslContextFactory.Server();
|
||||||
|
|
||||||
|
KeyStore keyStore = KeyStore.getInstance(KeyStoreType.PKCS12.toString());
|
||||||
|
keyStore.load(BaseRestServerHelper.class.getResourceAsStream(SERVER_KEYSTORE_PATH), PASSWORD.toCharArray());
|
||||||
|
sslContextFactory.setKeyStore(keyStore);
|
||||||
|
sslContextFactory.setKeyStorePassword(PASSWORD);
|
||||||
|
|
||||||
|
KeyStore trustStore = KeyStore.getInstance(KeyStoreType.PKCS12.toString());
|
||||||
|
trustStore.load(BaseRestServerHelper.class.getResourceAsStream(SERVER_TRUSTSTORE_PATH), PASSWORD.toCharArray());
|
||||||
|
sslContextFactory.setTrustStore(trustStore);
|
||||||
|
|
||||||
|
return sslContextFactory;
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
throw new RuntimeException(Msg.code(2123)+"Failed to obtain SslContextFactory", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBase() {
|
||||||
|
return myBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecureBase() {
|
||||||
|
return mySecureBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() throws Exception {
|
||||||
|
JettyUtil.closeServer(myListenerServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void clearDataAndCounts();
|
||||||
|
|
||||||
|
public abstract void setFailNextPut(boolean theFailNextPut);
|
||||||
|
|
||||||
|
public abstract List<Object> getInterceptors();
|
||||||
|
|
||||||
|
public abstract void unregisterInterceptor(Object theNext);
|
||||||
|
|
||||||
|
public abstract void clearCounts();
|
||||||
|
|
||||||
|
public abstract long getPatientCountSearch();
|
||||||
|
|
||||||
|
public abstract long getPatientCountDelete();
|
||||||
|
|
||||||
|
public abstract long getPatientCountUpdate();
|
||||||
|
|
||||||
|
public abstract long getPatientCountRead();
|
||||||
|
|
||||||
|
public abstract long getObservationCountSearch();
|
||||||
|
|
||||||
|
public abstract long getObservationCountDelete();
|
||||||
|
|
||||||
|
public abstract long getObservationCountUpdate();
|
||||||
|
|
||||||
|
public abstract long getObservationCountRead();
|
||||||
|
|
||||||
|
public abstract boolean registerInterceptor(Object theInterceptorAdapter);
|
||||||
|
|
||||||
|
public abstract IResourceProvider getObservationResourceProvider();
|
||||||
|
|
||||||
|
public abstract IResourceProvider getPatientResourceProvider();
|
||||||
|
|
||||||
|
public abstract IResourceProvider getConceptMapResourceProvider();
|
||||||
|
|
||||||
|
public abstract IIdType createPatientWithId(String theId);
|
||||||
|
|
||||||
|
public abstract IIdType createPatient(IBaseResource theBaseResource);
|
||||||
|
|
||||||
|
public abstract IIdType createObservationForPatient(IIdType theFirstTargetPatientId);
|
||||||
|
|
||||||
|
public abstract IIdType createObservation(IBaseResource theBaseResource);
|
||||||
|
|
||||||
|
public void setServerAddressStrategy(boolean theUseHttps){
|
||||||
|
String path = theUseHttps ? mySecureBase : myBase;
|
||||||
|
HardcodedServerAddressStrategy strategy = new HardcodedServerAddressStrategy(path);
|
||||||
|
setServerAddressStrategy(strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void setServerAddressStrategy(IServerAddressStrategy theServerAddressStrategy);
|
||||||
|
}
|
|
@ -0,0 +1,354 @@
|
||||||
|
package ca.uhn.fhir.test.utilities;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
|
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
||||||
|
import ca.uhn.test.concurrency.IPointcutLatch;
|
||||||
|
import ca.uhn.test.concurrency.PointcutLatch;
|
||||||
|
import org.hl7.fhir.dstu3.model.ConceptMap;
|
||||||
|
import org.hl7.fhir.dstu3.model.Observation;
|
||||||
|
import org.hl7.fhir.dstu3.model.Organization;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RestServerDstu3Helper extends BaseRestServerHelper implements IPointcutLatch, BeforeEachCallback, AfterEachCallback {
|
||||||
|
protected final MyRestfulServer myRestServer;
|
||||||
|
|
||||||
|
public RestServerDstu3Helper() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestServerDstu3Helper(boolean theInitialize) {
|
||||||
|
super(FhirContext.forDstu3());
|
||||||
|
myRestServer = new MyRestfulServer(myFhirContext);
|
||||||
|
if(theInitialize){
|
||||||
|
try {
|
||||||
|
myRestServer.initialize();
|
||||||
|
} catch (ServletException e) {
|
||||||
|
throw new RuntimeException(Msg.code(2112)+"Failed to initialize server", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEach(ExtensionContext context) throws Exception {
|
||||||
|
startServer(myRestServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterEach(ExtensionContext context) throws Exception {
|
||||||
|
super.afterEach();
|
||||||
|
myRestServer.getInterceptorService().unregisterAllAnonymousInterceptors();
|
||||||
|
myRestServer.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearDataAndCounts() {
|
||||||
|
myRestServer.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFailNextPut(boolean theFailNextPut) {
|
||||||
|
myRestServer.setFailNextPut(theFailNextPut);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Object> getInterceptors() {
|
||||||
|
return myRestServer.getInterceptorService().getAllRegisteredInterceptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterInterceptor(Object theInterceptor) {
|
||||||
|
myRestServer.getInterceptorService().unregisterInterceptor(theInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearCounts() {
|
||||||
|
myRestServer.clearCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountSearch() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountDelete() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountUpdate() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountRead() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountSearch() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountDelete() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountUpdate() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountRead() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean registerInterceptor(Object theInterceptor) {
|
||||||
|
return myRestServer.getInterceptorService().registerInterceptor(theInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
myRestServer.getPlainProvider().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setExpectedCount(int theCount) {
|
||||||
|
myRestServer.getPlainProvider().setExpectedCount(theCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HookParams> awaitExpected() throws InterruptedException {
|
||||||
|
return myRestServer.getPlainProvider().awaitExpected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerProvider(Object theProvider) {
|
||||||
|
myRestServer.registerProvider(theProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MyPlainProvider implements IPointcutLatch {
|
||||||
|
private final PointcutLatch myPointcutLatch = new PointcutLatch("Transaction Counting Provider");
|
||||||
|
private final List<IBaseBundle> myTransactions = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
public synchronized IBaseBundle transaction(@TransactionParam IBaseBundle theBundle) {
|
||||||
|
myPointcutLatch.call(theBundle);
|
||||||
|
myTransactions.add(theBundle);
|
||||||
|
return theBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
myPointcutLatch.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setExpectedCount(int theCount) {
|
||||||
|
myPointcutLatch.setExpectedCount(theCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HookParams> awaitExpected() throws InterruptedException {
|
||||||
|
return myPointcutLatch.awaitExpected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IBaseBundle> getTransactions() {
|
||||||
|
return Collections.unmodifiableList(new ArrayList<>(myTransactions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyRestfulServer extends RestfulServer {
|
||||||
|
private boolean myFailNextPut;
|
||||||
|
private HashMapResourceProvider<Patient> myPatientResourceProvider;
|
||||||
|
private HashMapResourceProvider<Observation> myObservationResourceProvider;
|
||||||
|
private HashMapResourceProvider<Organization> myOrganizationResourceProvider;
|
||||||
|
private HashMapResourceProvider<ConceptMap> myConceptMapResourceProvider;
|
||||||
|
private MyPlainProvider myPlainProvider;
|
||||||
|
|
||||||
|
public MyRestfulServer(FhirContext theFhirContext) {
|
||||||
|
super(theFhirContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyPlainProvider getPlainProvider() {
|
||||||
|
return myPlainProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailNextPut(boolean theFailNextPut) {
|
||||||
|
myFailNextPut = theFailNextPut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCounts() {
|
||||||
|
for (IResourceProvider next : getResourceProviders()) {
|
||||||
|
if (next instanceof HashMapResourceProvider) {
|
||||||
|
HashMapResourceProvider provider = (HashMapResourceProvider) next;
|
||||||
|
provider.clearCounts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myPlainProvider.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearDataAndCounts() {
|
||||||
|
for (IResourceProvider next : getResourceProviders()) {
|
||||||
|
if (next instanceof HashMapResourceProvider) {
|
||||||
|
HashMapResourceProvider provider = (HashMapResourceProvider) next;
|
||||||
|
provider.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Observation> getObservationResourceProvider() {
|
||||||
|
return myObservationResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Organization> getOrganizationResourceProvider() {
|
||||||
|
return myOrganizationResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<ConceptMap> getConceptMapResourceProvider() {
|
||||||
|
return myConceptMapResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
|
return myPatientResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() throws ServletException {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
FhirContext fhirContext = getFhirContext();
|
||||||
|
myPatientResourceProvider = new MyHashMapResourceProvider(fhirContext, Patient.class);
|
||||||
|
registerProvider(myPatientResourceProvider);
|
||||||
|
myObservationResourceProvider = new MyHashMapResourceProvider(fhirContext, Observation.class);
|
||||||
|
registerProvider(myObservationResourceProvider);
|
||||||
|
myOrganizationResourceProvider = new MyHashMapResourceProvider(fhirContext, Organization.class);
|
||||||
|
registerProvider(myOrganizationResourceProvider);
|
||||||
|
myConceptMapResourceProvider = new MyHashMapResourceProvider(fhirContext, ConceptMap.class);
|
||||||
|
registerProvider(myConceptMapResourceProvider);
|
||||||
|
|
||||||
|
myPlainProvider = new MyPlainProvider();
|
||||||
|
registerProvider(myPlainProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
||||||
|
myConceptMapResourceProvider.getStoredResources().forEach(c -> theResourceProvider.store(c));
|
||||||
|
|
||||||
|
unregisterProvider(myConceptMapResourceProvider);
|
||||||
|
registerProvider(theResourceProvider);
|
||||||
|
myConceptMapResourceProvider = theResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class MyHashMapResourceProvider<T extends IBaseResource> extends HashMapResourceProvider<T> {
|
||||||
|
public MyHashMapResourceProvider(FhirContext theContext, Class theType) {
|
||||||
|
super(theContext, theType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodOutcome update(T theResource, String theConditional, RequestDetails theRequestDetails) {
|
||||||
|
if (myFailNextPut) {
|
||||||
|
throw new PreconditionFailedException(Msg.code(2113)+"Failed update operation");
|
||||||
|
}
|
||||||
|
return super.update(theResource, theConditional, theRequestDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<Observation> getObservationResourceProvider() {
|
||||||
|
return myRestServer.getObservationResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
|
return myRestServer.getPatientResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<ConceptMap> getConceptMapResourceProvider() {
|
||||||
|
return myRestServer.getConceptMapResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createPatientWithId(String theId) {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId("Patient/" + theId);
|
||||||
|
patient.addIdentifier().setSystem("http://foo").setValue(theId);
|
||||||
|
return this.createPatient(patient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createPatient(IBaseResource theBaseResource) {
|
||||||
|
return myRestServer.getPatientResourceProvider().store((Patient) theBaseResource);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createObservationForPatient(IIdType theFirstTargetPatientId) {
|
||||||
|
Observation observation = new Observation();
|
||||||
|
observation.setSubject(new Reference(theFirstTargetPatientId));
|
||||||
|
return this.createObservation(observation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createObservation(IBaseResource theBaseResource) {
|
||||||
|
return myRestServer.getObservationResourceProvider().store((Observation) theBaseResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setServerAddressStrategy(IServerAddressStrategy theServerAddressStrategy) {
|
||||||
|
myRestServer.setServerAddressStrategy(theServerAddressStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
||||||
|
myRestServer.setConceptMapResourceProvider(theResourceProvider);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,387 @@
|
||||||
|
package ca.uhn.fhir.test.utilities;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
|
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
|
||||||
|
import ca.uhn.fhir.rest.server.IncomingRequestAddressStrategy;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.ConceptMap;
|
||||||
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEachCallback, AfterEachCallback {
|
||||||
|
protected final MyRestfulServer myRestServer;
|
||||||
|
|
||||||
|
public RestServerR4Helper() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestServerR4Helper(boolean theInitialize) {
|
||||||
|
super(FhirContext.forR4Cached());
|
||||||
|
myRestServer = new MyRestfulServer(myFhirContext);
|
||||||
|
if(theInitialize){
|
||||||
|
try {
|
||||||
|
myRestServer.initialize();
|
||||||
|
} catch (ServletException e) {
|
||||||
|
throw new RuntimeException(Msg.code(2110)+"Failed to initialize server", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEach(ExtensionContext context) throws Exception {
|
||||||
|
startServer(myRestServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterEach(ExtensionContext context) throws Exception {
|
||||||
|
super.afterEach();
|
||||||
|
myRestServer.getInterceptorService().unregisterAllAnonymousInterceptors();
|
||||||
|
myRestServer.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Bundle> getTransactions() {
|
||||||
|
return myRestServer
|
||||||
|
.getPlainProvider()
|
||||||
|
.getTransactions()
|
||||||
|
.stream()
|
||||||
|
.map(t -> (Bundle) t)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearDataAndCounts() {
|
||||||
|
myRestServer.clearDataAndCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFailNextPut(boolean theFailNextPut) {
|
||||||
|
myRestServer.setFailNextPut(theFailNextPut);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Object> getInterceptors() {
|
||||||
|
return myRestServer.getInterceptorService().getAllRegisteredInterceptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterInterceptor(Object theInterceptor) {
|
||||||
|
myRestServer.getInterceptorService().unregisterInterceptor(theInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearCounts() {
|
||||||
|
myRestServer.clearCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountSearch() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountDelete() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountUpdate() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPatientCountRead() {
|
||||||
|
return myRestServer.getPatientResourceProvider().getCountRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountSearch() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountDelete() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountUpdate() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getObservationCountRead() {
|
||||||
|
return myRestServer.getObservationResourceProvider().getCountRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean registerInterceptor(Object theInterceptor) {
|
||||||
|
return myRestServer.getInterceptorService().registerInterceptor(theInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerProvider(Object theProvider) {
|
||||||
|
myRestServer.registerProvider(theProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpectedCount(int theCount) {
|
||||||
|
myRestServer.getPlainProvider().setExpectedCount(theCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HookParams> awaitExpected() throws InterruptedException {
|
||||||
|
return myRestServer.getPlainProvider().awaitExpected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<Observation> getObservationResourceProvider() {
|
||||||
|
return myRestServer.getObservationResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
|
return myRestServer.getPatientResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMapResourceProvider<ConceptMap> getConceptMapResourceProvider() {
|
||||||
|
return myRestServer.getConceptMapResourceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
||||||
|
myRestServer.setConceptMapResourceProvider(theResourceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createPatientWithId(String theId) {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId("Patient/" + theId);
|
||||||
|
patient.addIdentifier().setSystem("http://foo").setValue(theId);
|
||||||
|
return this.createPatient(patient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createPatient(IBaseResource theBaseResource) {
|
||||||
|
return myRestServer.getPatientResourceProvider().store((Patient) theBaseResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createObservationForPatient(IIdType thePatientId) {
|
||||||
|
Observation observation = new Observation();
|
||||||
|
observation.setSubject(new Reference(thePatientId));
|
||||||
|
return this.createObservation(observation);
|
||||||
|
//TODO maybe add some data to this obs?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createObservation(IBaseResource theBaseResource) {
|
||||||
|
return myRestServer.getObservationResourceProvider().store((Observation) theBaseResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRequestUrls() {
|
||||||
|
return myRestServer.myRequestUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRequestVerbs() {
|
||||||
|
return myRestServer.myRequestVerbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
||||||
|
myRestServer.setObservationResourceProvider(theResourceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Map<String, String>> getRequestHeaders() {
|
||||||
|
return myRestServer.myRequestHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IInterceptorService getInterceptorService() {
|
||||||
|
return myRestServer.getInterceptorService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setServerAddressStrategy(IServerAddressStrategy theServerAddressStrategy){
|
||||||
|
myRestServer.setServerAddressStrategy(theServerAddressStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyRestfulServer extends RestfulServer {
|
||||||
|
private boolean myFailNextPut;
|
||||||
|
private HashMapResourceProvider<Patient> myPatientResourceProvider;
|
||||||
|
private HashMapResourceProvider<Observation> myObservationResourceProvider;
|
||||||
|
private HashMapResourceProvider<Organization> myOrganizationResourceProvider;
|
||||||
|
private HashMapResourceProvider<ConceptMap> myConceptMapResourceProvider;
|
||||||
|
private RestServerDstu3Helper.MyPlainProvider myPlainProvider;
|
||||||
|
private final List<String> myRequestUrls = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private final List<String> myRequestVerbs = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private final List<Map<String, String>> myRequestHeaders= Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
public MyRestfulServer(FhirContext theFhirContext) {
|
||||||
|
super(theFhirContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestServerDstu3Helper.MyPlainProvider getPlainProvider() {
|
||||||
|
return myPlainProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFailNextPut(boolean theFailNextPut) {
|
||||||
|
myFailNextPut = theFailNextPut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCounts() {
|
||||||
|
for (IResourceProvider next : getResourceProviders()) {
|
||||||
|
if (next instanceof HashMapResourceProvider) {
|
||||||
|
HashMapResourceProvider provider = (HashMapResourceProvider) next;
|
||||||
|
provider.clearCounts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myPlainProvider.clear();
|
||||||
|
myRequestUrls.clear();
|
||||||
|
myRequestVerbs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void service(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
|
||||||
|
Request request = (Request) theReq;
|
||||||
|
|
||||||
|
Map<String, String> headers = pullOutHeaders(theReq);
|
||||||
|
myRequestHeaders.add(headers);
|
||||||
|
myRequestUrls.add(request.getOriginalURI());
|
||||||
|
myRequestVerbs.add(request.getMethod());
|
||||||
|
super.service(theReq, theResp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String,String> pullOutHeaders(HttpServletRequest theReq) {
|
||||||
|
Enumeration<String> headerNames = theReq.getHeaderNames();
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
while (headerNames.hasMoreElements()) {
|
||||||
|
String headerName = headerNames.nextElement();
|
||||||
|
headers.put(headerName, theReq.getHeader(headerName));
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearDataAndCounts() {
|
||||||
|
for (IResourceProvider next : getResourceProviders()) {
|
||||||
|
if (next instanceof HashMapResourceProvider) {
|
||||||
|
HashMapResourceProvider provider = (HashMapResourceProvider) next;
|
||||||
|
provider.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Observation> getObservationResourceProvider() {
|
||||||
|
return myObservationResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Organization> getOrganizationResourceProvider() {
|
||||||
|
return myOrganizationResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<ConceptMap> getConceptMapResourceProvider() {
|
||||||
|
return myConceptMapResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
|
return myPatientResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() throws ServletException {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
FhirContext fhirContext = getFhirContext();
|
||||||
|
myPatientResourceProvider = new MyHashMapResourceProvider(fhirContext, Patient.class);
|
||||||
|
registerProvider(myPatientResourceProvider);
|
||||||
|
myObservationResourceProvider = new MyHashMapResourceProvider(fhirContext, Observation.class);
|
||||||
|
registerProvider(myObservationResourceProvider);
|
||||||
|
myOrganizationResourceProvider = new MyHashMapResourceProvider(fhirContext, Organization.class);
|
||||||
|
registerProvider(myOrganizationResourceProvider);
|
||||||
|
myConceptMapResourceProvider = new MyHashMapResourceProvider(fhirContext, ConceptMap.class);
|
||||||
|
registerProvider(myConceptMapResourceProvider);
|
||||||
|
|
||||||
|
myPlainProvider = new RestServerDstu3Helper.MyPlainProvider();
|
||||||
|
registerProvider(myPlainProvider);
|
||||||
|
|
||||||
|
setPagingProvider(new FifoMemoryPagingProvider(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
||||||
|
myObservationResourceProvider.getStoredResources().forEach(o -> theResourceProvider.store(o));
|
||||||
|
|
||||||
|
unregisterProvider(myObservationResourceProvider);
|
||||||
|
registerProvider(theResourceProvider);
|
||||||
|
myObservationResourceProvider = theResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
||||||
|
myConceptMapResourceProvider.getStoredResources().forEach(c -> theResourceProvider.store(c));
|
||||||
|
|
||||||
|
unregisterProvider(myConceptMapResourceProvider);
|
||||||
|
registerProvider(theResourceProvider);
|
||||||
|
myConceptMapResourceProvider = theResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class MyHashMapResourceProvider<T extends IBaseResource> extends HashMapResourceProvider<T> {
|
||||||
|
public MyHashMapResourceProvider(FhirContext theContext, Class theType) {
|
||||||
|
super(theContext, theType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodOutcome update(T theResource, String theConditional, RequestDetails theRequestDetails) {
|
||||||
|
if (myFailNextPut) {
|
||||||
|
throw new PreconditionFailedException(Msg.code(2111)+"Failed update operation");
|
||||||
|
}
|
||||||
|
return super.update(theResource, theConditional, theRequestDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
package ca.uhn.fhir.test.utilities;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.tls.KeyStoreInfo;
|
||||||
|
import ca.uhn.fhir.tls.TlsAuthentication;
|
||||||
|
import ca.uhn.fhir.tls.TrustStoreInfo;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class TlsAuthenticationTestHelper implements AfterEachCallback {
|
||||||
|
|
||||||
|
private static final String KEYSTORE_RESOURCE_PATH = "classpath:/tls/client-keystore.p12";
|
||||||
|
private static final String KEYSTORE_STOREPASS = "changeit";
|
||||||
|
private static final String KEYSTORE_KEYPASS = "changeit";
|
||||||
|
private static final String KEYSTORE_ALIAS = "client";
|
||||||
|
|
||||||
|
private static final String TRUSTSTORE_RESOURCE_PATH = "classpath:/tls/client-truststore.p12";
|
||||||
|
private static final String TRUSTSTORE_STOREPASS = "changeit";
|
||||||
|
private static final String TRUSTSTORE_ALIAS = "client";
|
||||||
|
|
||||||
|
private final TlsAuthentication myTlsAuthentication;
|
||||||
|
private final KeyStoreInfo myKeystoreInfo;
|
||||||
|
private final TrustStoreInfo myTrustStoreInfo;
|
||||||
|
private File myTempFile;
|
||||||
|
|
||||||
|
public TlsAuthenticationTestHelper(){
|
||||||
|
myKeystoreInfo = new KeyStoreInfo(KEYSTORE_RESOURCE_PATH, KEYSTORE_STOREPASS, KEYSTORE_KEYPASS, KEYSTORE_ALIAS);
|
||||||
|
myTrustStoreInfo = new TrustStoreInfo(TRUSTSTORE_RESOURCE_PATH, TRUSTSTORE_STOREPASS, TRUSTSTORE_ALIAS);
|
||||||
|
myTlsAuthentication = new TlsAuthentication(Optional.of(myKeystoreInfo), Optional.of(myTrustStoreInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterEach(ExtensionContext theExtensionContext) throws Exception {
|
||||||
|
if(myTempFile != null && myTempFile.exists()){
|
||||||
|
assertTrue(myTempFile.delete());
|
||||||
|
myTempFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] createBaseRequestGeneratingCommandArgs(String[] theBaseArgs, String theUrlFlag, boolean theAddTls, BaseRestServerHelper theRestServerHelper){
|
||||||
|
if(isBlank(theUrlFlag)){
|
||||||
|
return theBaseArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] retVal;
|
||||||
|
if(theAddTls){
|
||||||
|
int newSize = theBaseArgs.length + 4;
|
||||||
|
retVal = Arrays.copyOf(theBaseArgs, newSize);
|
||||||
|
|
||||||
|
retVal[newSize - 4] = theUrlFlag;
|
||||||
|
retVal[newSize - 3] = theRestServerHelper.getSecureBase(); // HTTPS
|
||||||
|
|
||||||
|
myTempFile = createTlsAuthenticationFile();
|
||||||
|
retVal[newSize - 2] = "--tls-auth";
|
||||||
|
retVal[newSize - 1] = myTempFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int newSize = theBaseArgs.length + 2;
|
||||||
|
retVal = Arrays.copyOf(theBaseArgs, newSize);
|
||||||
|
retVal[newSize - 2] = theUrlFlag;
|
||||||
|
retVal[newSize - 1] = theRestServerHelper.getBase(); // HTTP
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TlsAuthentication getTlsAuthentication(){
|
||||||
|
return myTlsAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File createTlsAuthenticationFile() {
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
ObjectNode keyStore = mapper.createObjectNode();
|
||||||
|
keyStore.put("filePath", KEYSTORE_RESOURCE_PATH);
|
||||||
|
keyStore.put("storePass", KEYSTORE_STOREPASS);
|
||||||
|
keyStore.put("keyPass", KEYSTORE_KEYPASS);
|
||||||
|
keyStore.put("alias", KEYSTORE_ALIAS);
|
||||||
|
|
||||||
|
ObjectNode trustStore = mapper.createObjectNode();
|
||||||
|
trustStore.put("filePath", TRUSTSTORE_RESOURCE_PATH);
|
||||||
|
trustStore.put("storePass", TRUSTSTORE_STOREPASS);
|
||||||
|
trustStore.put("alias", TRUSTSTORE_ALIAS);
|
||||||
|
|
||||||
|
ObjectNode json = mapper.createObjectNode();
|
||||||
|
json.set("keyStore", keyStore);
|
||||||
|
json.set("trustStore", trustStore);
|
||||||
|
|
||||||
|
File inputFile = File.createTempFile("smile-unit-test", ".json");
|
||||||
|
try (FileWriter inputFileWriter = new FileWriter(inputFile, StandardCharsets.UTF_8, false)) {
|
||||||
|
IOUtils.write(json.toString(), inputFileWriter);
|
||||||
|
}
|
||||||
|
return inputFile;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(Msg.code(2122)+"Failed to load test TLS authentication file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.1.0-PRE27-SNAPSHOT</version>
|
<version>6.1.0-PRE29-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue