Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
8427fc4547
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>hapi-fhir-standalone-overlay-example</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public class JaxRsConformanceProvider extends AbstractJaxRsConformanceProvider {
|
|||
private JaxRsPatientRestProvider provider;
|
||||
|
||||
public JaxRsConformanceProvider() {
|
||||
super("My Server Version", "My Server Description", "My Server Name");
|
||||
super("My Server Description", "My Server Name", "My Server Version");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -59,6 +59,13 @@
|
|||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<!-- Guava brings in a newer replacement for this dependency called com.google.code.findbugs:jsr305 -->
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId>
|
||||
|
@ -77,6 +84,10 @@
|
|||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
|
|
|
@ -1127,7 +1127,7 @@ public abstract class BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public BaseRuntimeChildDefinition getDef() {
|
||||
|
|
|
@ -1450,7 +1450,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
}
|
||||
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||
if (childDef == null) {
|
||||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, false, myParent, false);
|
||||
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName);
|
||||
|
|
|
@ -138,19 +138,6 @@ public class ParameterUtil {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
|
||||
* Section</a>
|
||||
*/
|
||||
public static String escapeAndUrlEncode(String theValue) {
|
||||
if (theValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String escaped = escape(theValue);
|
||||
return UrlUtil.escape(escaped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
|
||||
* Section</a>
|
||||
|
|
|
@ -47,6 +47,10 @@ public class InvalidRequestException extends BaseServerResponseException {
|
|||
public InvalidRequestException(String theMessage) {
|
||||
super(STATUS_CODE, theMessage);
|
||||
}
|
||||
|
||||
public InvalidRequestException(Throwable theCause) {
|
||||
super(STATUS_CODE, theCause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.net.PercentEscaper;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -35,6 +39,10 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
public class UrlUtil {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UrlUtil.class);
|
||||
|
||||
private static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*";
|
||||
private static final Escaper PARAMETER_ESCAPER = new PercentEscaper(URL_FORM_PARAMETER_OTHER_SAFE_CHARS, false);
|
||||
|
||||
|
||||
/**
|
||||
* Resolve a relative URL - THIS METHOD WILL NOT FAIL but will log a warning and return theEndpoint if the input is invalid.
|
||||
*/
|
||||
|
@ -88,19 +96,24 @@ public class UrlUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* URL encode a value
|
||||
* URL encode a value according to RFC 3986
|
||||
* <p>
|
||||
* This method is intended to be applied to an individual parameter
|
||||
* name or value. For example, if you are creating the URL
|
||||
* <code>http://example.com/fhir/Patient?key=føø</code>
|
||||
* it would be appropriate to pass the string "føø" to this method,
|
||||
* but not appropriate to pass the entire URL since characters
|
||||
* such as "/" and "?" would also be escaped.
|
||||
* </P>
|
||||
*/
|
||||
public static String escape(String theValue) {
|
||||
if (theValue == null) {
|
||||
public static String escapeUrlParam(String theUnescaped) {
|
||||
if (theUnescaped == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return URLEncoder.encode(theValue, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 not supported on this platform");
|
||||
}
|
||||
return PARAMETER_ESCAPER.escape(theUnescaped);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAbsolute(String theValue) {
|
||||
String value = theValue.toLowerCase();
|
||||
return value.startsWith("http://") || value.startsWith("https://");
|
||||
|
@ -147,7 +160,7 @@ public class UrlUtil {
|
|||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(escape("http://snomed.info/sct?fhir_vs=isa/126851005"));
|
||||
System.out.println(escapeUrlParam("http://snomed.info/sct?fhir_vs=isa/126851005"));
|
||||
}
|
||||
|
||||
public static Map<String, String[]> parseQueryString(String theQueryString) {
|
||||
|
@ -156,36 +169,20 @@ public class UrlUtil {
|
|||
return toQueryStringMap(map);
|
||||
}
|
||||
|
||||
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
|
||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
for (String next : theQueryString) {
|
||||
parseQueryString(next, map);
|
||||
}
|
||||
return toQueryStringMap(map);
|
||||
}
|
||||
|
||||
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
|
||||
HashMap<String, String[]> retVal = new HashMap<String, String[]>();
|
||||
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
|
||||
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static void parseQueryString(String theQueryString, HashMap<String, List<String>> map) {
|
||||
String query = theQueryString;
|
||||
if (query.startsWith("?")) {
|
||||
query = query.substring(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(query, "&");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String nextToken = tok.nextToken();
|
||||
if (isBlank(nextToken)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int equalsIndex = nextToken.indexOf('=');
|
||||
String nextValue;
|
||||
String nextKey;
|
||||
|
@ -196,21 +193,28 @@ public class UrlUtil {
|
|||
nextKey = nextToken.substring(0, equalsIndex);
|
||||
nextValue = nextToken.substring(equalsIndex + 1);
|
||||
}
|
||||
|
||||
|
||||
nextKey = unescape(nextKey);
|
||||
nextValue = unescape(nextValue);
|
||||
|
||||
|
||||
List<String> list = map.get(nextKey);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
list = new ArrayList<>();
|
||||
map.put(nextKey, list);
|
||||
}
|
||||
list.add(nextValue);
|
||||
}
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
/**
|
||||
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
|
||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
for (String next : theQueryString) {
|
||||
parseQueryString(next, map);
|
||||
}
|
||||
return toQueryStringMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a URL in one of the following forms:
|
||||
* <ul>
|
||||
* <li>[Resource Type]?[Search Params]
|
||||
|
@ -278,6 +282,16 @@ public class UrlUtil {
|
|||
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
|
||||
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
|
||||
HashMap<String, String[]> retVal = new HashMap<String, String[]>();
|
||||
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
|
||||
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static String unescape(String theString) {
|
||||
if (theString == null) {
|
||||
return null;
|
||||
|
@ -305,30 +319,30 @@ public class UrlUtil {
|
|||
return myParams;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public String getVersionId() {
|
||||
return myVersionId;
|
||||
}
|
||||
|
||||
public void setParams(String theParams) {
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(String theResourceId) {
|
||||
myResourceId = theResourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public String getVersionId() {
|
||||
return myVersionId;
|
||||
}
|
||||
|
||||
public void setVersionId(String theVersionId) {
|
||||
myVersionId = theVersionId;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,42 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class UrlUtilTest {
|
||||
|
||||
@Test
|
||||
public void testConstructAbsoluteUrl() {
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "baz"));
|
||||
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "baz/"));
|
||||
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "./baz/"));
|
||||
|
||||
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "../baz/"));
|
||||
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "/baz/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructRelativeUrl() {
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://boo/far/faz", "http://foo/bar/baz"));
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://foo/far/faz", "http://foo/bar/baz"));
|
||||
assertEquals("baz", UrlUtil.constructRelativeUrl("http://foo/bar/boo", "http://foo/bar/baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscape() {
|
||||
assertEquals("A%20B", UrlUtil.escapeUrlParam("A B"));
|
||||
assertEquals("A%2BB", UrlUtil.escapeUrlParam("A+B"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValid() {
|
||||
assertTrue(UrlUtil.isValid("http://foo"));
|
||||
assertTrue(UrlUtil.isValid("https://foo"));
|
||||
assertTrue(UrlUtil.isValid("HTTP://Foo"));
|
||||
assertTrue(UrlUtil.isValid("HTTPS://Foo"));
|
||||
|
||||
|
||||
assertFalse(UrlUtil.isValid("file://foo"));
|
||||
assertFalse(UrlUtil.isValid("://foo"));
|
||||
assertFalse(UrlUtil.isValid("http:/ss"));
|
||||
|
@ -24,7 +46,7 @@ public class UrlUtilTest {
|
|||
assertFalse(UrlUtil.isValid(""));
|
||||
assertFalse(UrlUtil.isValid(null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseUrl() {
|
||||
assertEquals("ConceptMap", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde").getResourceType());
|
||||
|
@ -36,25 +58,5 @@ public class UrlUtilTest {
|
|||
assertEquals("a=b", UrlUtil.parseUrl("ConceptMap/ussgfht-loincde?a=b").getParams());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructAbsoluteUrl() {
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl("http://foo/bar/","baz"));
|
||||
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","baz/"));
|
||||
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","./baz/"));
|
||||
|
||||
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","../baz/"));
|
||||
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","/baz/"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testConstructRelativeUrl() {
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://boo/far/faz", "http://foo/bar/baz"));
|
||||
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://foo/far/faz", "http://foo/bar/baz"));
|
||||
assertEquals("baz", UrlUtil.constructRelativeUrl("http://foo/bar/boo", "http://foo/bar/baz"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -20,13 +20,6 @@ package ca.uhn.fhir.rest.client.impl;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
|
@ -34,6 +27,12 @@ import ca.uhn.fhir.rest.client.api.Header;
|
|||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class BaseHttpClientInvocation {
|
||||
|
||||
|
@ -115,13 +114,9 @@ public abstract class BaseHttpClientInvocation {
|
|||
} else {
|
||||
theUrlBuilder.append('&');
|
||||
}
|
||||
try {
|
||||
theUrlBuilder.append(URLEncoder.encode(next.getKey(), "UTF-8"));
|
||||
theUrlBuilder.append('=');
|
||||
theUrlBuilder.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 not supported - This should not happen");
|
||||
}
|
||||
theUrlBuilder.append(UrlUtil.escapeUrlParam(next.getKey()));
|
||||
theUrlBuilder.append('=');
|
||||
theUrlBuilder.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -354,7 +354,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
case '?':
|
||||
case '$':
|
||||
case ':':
|
||||
b.append(UrlUtil.escape(Character.toString(nextChar)));
|
||||
b.append(UrlUtil.escapeUrlParam(Character.toString(nextChar)));
|
||||
break;
|
||||
default:
|
||||
b.append(nextChar);
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.rest.client.interceptor;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Client Framework
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.rest.client.api.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
|
|
@ -20,21 +20,18 @@ package ca.uhn.fhir.rest.client.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
@ -51,51 +48,40 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
|
|||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(FhirContext theContext, Map<String, List<String>> theParameters, List<String> theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = theParameters;
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(FhirContext theContext, String theUrlPath) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myParameters = new HashMap<>();
|
||||
myUrlPath = theUrlPath;
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(FhirContext theContext, String... theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
private boolean addQueryParameter(StringBuilder b, boolean first, String nextKey, String nextValue) {
|
||||
boolean retVal = first;
|
||||
if (retVal) {
|
||||
b.append('?');
|
||||
retVal = false;
|
||||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
b.append(UrlUtil.escapeUrlParam(nextKey));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
|
||||
public HttpGetClientInvocation(FhirContext theContext, List<String> theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
|
||||
public String getUrlPath() {
|
||||
return myUrlPath;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
|
||||
if (!myUrlPath.contains("://")) {
|
||||
b.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/") && !myUrlPath.startsWith("/")) {
|
||||
b.append('/');
|
||||
}
|
||||
}
|
||||
b.append(myUrlPath);
|
||||
|
||||
b.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/") && !myUrlPath.startsWith("/")) {
|
||||
b.append('/');
|
||||
}
|
||||
}
|
||||
b.append(myUrlPath);
|
||||
|
||||
boolean first = b.indexOf("?") == -1;
|
||||
for (Entry<String, List<String>> next : myParameters.entrySet()) {
|
||||
if (next.getValue() == null || next.getValue().isEmpty()) {
|
||||
|
@ -112,22 +98,12 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
|
|||
return super.createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.GET);
|
||||
}
|
||||
|
||||
private boolean addQueryParameter(StringBuilder b, boolean first, String nextKey, String nextValue) {
|
||||
boolean retVal = first;
|
||||
if (retVal) {
|
||||
b.append('?');
|
||||
retVal = false;
|
||||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
try {
|
||||
b.append(URLEncoder.encode(nextKey, "UTF-8"));
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ConfigurationException("Could not find UTF-8 encoding. This shouldn't happen.", e);
|
||||
}
|
||||
return retVal;
|
||||
public Map<String, List<String>> getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
|
||||
public String getUrlPath() {
|
||||
return myUrlPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -209,9 +209,9 @@ public class MethodUtil {
|
|||
for (String nextValue : nextEntry.getValue()) {
|
||||
b.append(haveQuestionMark ? '&' : '?');
|
||||
haveQuestionMark = true;
|
||||
b.append(UrlUtil.escape(nextEntry.getKey()));
|
||||
b.append(UrlUtil.escapeUrlParam(nextEntry.getKey()));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextValue));
|
||||
b.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
}
|
||||
}
|
||||
return b;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -26,42 +26,42 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2.1</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -51,11 +51,26 @@
|
|||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2.1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
|
|
|
@ -66,8 +66,11 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
|||
private RestulfulServerConfiguration serverConfiguration = new RestulfulServerConfiguration();
|
||||
|
||||
/** the conformance. It is created once during startup */
|
||||
private org.hl7.fhir.r4.model.CapabilityStatement myR4CapabilityStatement;
|
||||
private CapabilityStatement myDstu3CapabilityStatement;
|
||||
private org.hl7.fhir.dstu2016may.model.Conformance myDstu2_1Conformance;
|
||||
private ca.uhn.fhir.model.dstu2.resource.Conformance myDstu2Conformance;
|
||||
private org.hl7.fhir.instance.model.Conformance myDstu2Hl7OrgConformance;
|
||||
|
||||
/**
|
||||
* Constructor allowing the description, servername and server to be set
|
||||
|
@ -124,14 +127,26 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
|||
HardcodedServerAddressStrategy hardcodedServerAddressStrategy = new HardcodedServerAddressStrategy();
|
||||
hardcodedServerAddressStrategy.setValue(getBaseForServer());
|
||||
serverConfiguration.setServerAddressStrategy(hardcodedServerAddressStrategy);
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.R4)) {
|
||||
org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider serverCapabilityStatementProvider = new org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider(serverConfiguration);
|
||||
serverCapabilityStatementProvider.initializeOperations();
|
||||
myR4CapabilityStatement = serverCapabilityStatementProvider.getServerConformance(null);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
ServerCapabilityStatementProvider serverCapabilityStatementProvider = new ServerCapabilityStatementProvider(serverConfiguration);
|
||||
serverCapabilityStatementProvider.initializeOperations();
|
||||
myDstu3CapabilityStatement = serverCapabilityStatementProvider.getServerConformance(null);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_1)) {
|
||||
org.hl7.fhir.dstu2016may.hapi.rest.server.ServerConformanceProvider serverCapabilityStatementProvider = new org.hl7.fhir.dstu2016may.hapi.rest.server.ServerConformanceProvider(serverConfiguration);
|
||||
serverCapabilityStatementProvider.initializeOperations();
|
||||
myDstu2_1Conformance = serverCapabilityStatementProvider.getServerConformance(null);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||
ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider serverCapabilityStatementProvider = new ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider(serverConfiguration);
|
||||
serverCapabilityStatementProvider.initializeOperations();
|
||||
myDstu2Conformance = serverCapabilityStatementProvider.getServerConformance(null);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
org.hl7.fhir.instance.conf.ServerConformanceProvider serverCapabilityStatementProvider = new org.hl7.fhir.instance.conf.ServerConformanceProvider(serverConfiguration);
|
||||
serverCapabilityStatementProvider.initializeOperations();
|
||||
myDstu2Hl7OrgConformance = serverCapabilityStatementProvider.getServerConformance(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,12 +182,19 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
|||
response.addHeader(Constants.HEADER_CORS_ALLOW_ORIGIN, "*");
|
||||
|
||||
IBaseResource conformance = null;
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.R4)) {
|
||||
conformance = myR4CapabilityStatement;
|
||||
// return (Response) response.returnResponse(ParseAction.create(myDstu3CapabilityStatement), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
conformance = myDstu3CapabilityStatement;
|
||||
// return (Response) response.returnResponse(ParseAction.create(myDstu3CapabilityStatement), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_1)) {
|
||||
conformance = myDstu2_1Conformance;
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||
conformance = myDstu2Conformance;
|
||||
// return (Response) response.returnResponse(ParseAction.create(myDstu2CapabilityStatement), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
conformance = myDstu2Hl7OrgConformance;
|
||||
}
|
||||
|
||||
if (conformance != null) {
|
||||
|
@ -257,10 +279,16 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<IBaseResource> getResourceType() {
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.R4)) {
|
||||
return Class.class.cast(org.hl7.fhir.r4.model.CapabilityStatement.class);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
return Class.class.cast(CapabilityStatement.class);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_1)) {
|
||||
return Class.class.cast(org.hl7.fhir.dstu2016may.model.Conformance.class);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||
return Class.class.cast(ca.uhn.fhir.model.dstu2.resource.Conformance.class);
|
||||
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
return Class.class.cast(org.hl7.fhir.instance.model.Conformance.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ import java.util.Map.Entry;
|
|||
import javax.ws.rs.core.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.api.AddProfileTagEnum;
|
||||
|
@ -35,12 +33,9 @@ import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
|||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.server.*;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
|
||||
/**
|
||||
* This is the abstract superclass for all jaxrs providers. It contains some defaults implementing
|
||||
|
@ -57,11 +52,11 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
private final FhirContext CTX;
|
||||
/** the http headers */
|
||||
@Context
|
||||
private HttpHeaders theHeaders;
|
||||
private HttpHeaders myHeaders;
|
||||
|
||||
/** the uri info */
|
||||
@Context
|
||||
private UriInfo theUriInfo;
|
||||
private UriInfo myUriInfo;
|
||||
|
||||
/**
|
||||
* Default is DSTU2. Use {@link AbstractJaxRsProvider#AbstractJaxRsProvider(FhirContext)} to specify a DSTU3 context.
|
||||
|
@ -79,13 +74,6 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
CTX = ctx;
|
||||
}
|
||||
|
||||
private IBaseOperationOutcome createOutcome(final DataFormatException theException) {
|
||||
final IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getFhirContext());
|
||||
final String detailsValue = theException.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(theException);
|
||||
OperationOutcomeUtil.addIssue(getFhirContext(), oo, ERROR, detailsValue, null, PROCESSING);
|
||||
return oo;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEFAULT = AddProfileTagEnum.NEVER
|
||||
*/
|
||||
|
@ -142,7 +130,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
* @return the headers
|
||||
*/
|
||||
public HttpHeaders getHeaders() {
|
||||
return this.theHeaders;
|
||||
return this.myHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,7 +191,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
* @return the requestbuilder
|
||||
*/
|
||||
public Builder getRequest(final RequestTypeEnum requestType, final RestOperationTypeEnum restOperation, final String theResourceName) {
|
||||
return new JaxRsRequest.Builder(this, requestType, restOperation, theUriInfo.getRequestUri().toString(), theResourceName);
|
||||
return new JaxRsRequest.Builder(this, requestType, restOperation, myUriInfo.getRequestUri().toString(), theResourceName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,7 +212,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
* @return the uri info
|
||||
*/
|
||||
public UriInfo getUriInfo() {
|
||||
return this.theUriInfo;
|
||||
return this.myUriInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,9 +229,6 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
throws IOException {
|
||||
if (theException instanceof JaxRsResponseException) {
|
||||
return new JaxRsExceptionInterceptor().convertExceptionIntoResponse(theRequest, (JaxRsResponseException) theException);
|
||||
} else if (theException instanceof DataFormatException) {
|
||||
return new JaxRsExceptionInterceptor().convertExceptionIntoResponse(theRequest, new JaxRsResponseException(
|
||||
new InvalidRequestException(theException.getMessage(), createOutcome((DataFormatException) theException))));
|
||||
} else {
|
||||
return new JaxRsExceptionInterceptor().convertExceptionIntoResponse(theRequest,
|
||||
new JaxRsExceptionInterceptor().convertException(this, theException));
|
||||
|
@ -273,7 +258,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
* the headers to set
|
||||
*/
|
||||
public void setHeaders(final HttpHeaders headers) {
|
||||
this.theHeaders = headers;
|
||||
this.myHeaders = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,7 +268,7 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
* the uri info
|
||||
*/
|
||||
public void setUriInfo(final UriInfo uriInfo) {
|
||||
this.theUriInfo = uriInfo;
|
||||
this.myUriInfo = uriInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.*;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderDstu2Hl7Org;
|
||||
import org.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu2Hl7Org;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
public class AbstractJaxRsConformanceProviderDstu2Hl7OrgTest {
|
||||
|
||||
private static final String BASEURI = "http://basiuri";
|
||||
private static final String REQUESTURI = BASEURI + "/metadata";
|
||||
AbstractJaxRsConformanceProvider provider;
|
||||
private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers;
|
||||
private ContainerRequest headers;
|
||||
private MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// headers
|
||||
headers = new ContainerRequest(new URI(BASEURI), new URI(REQUESTURI), HttpMethod.GET, null,
|
||||
new MapPropertiesDelegate());
|
||||
// uri info
|
||||
queryParameters = new MultivaluedHashMap<String, String>();
|
||||
|
||||
|
||||
providers = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||
provider = createConformanceProvider(providers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformance() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderDstu2Hl7Org.class, new TestJaxRsDummyPatientProviderDstu2Hl7Org());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceUsingOptions() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderDstu2Hl7Org.class, new TestJaxRsDummyPatientProviderDstu2Hl7Org());
|
||||
Response response = createConformanceProvider(providers).conformanceUsingOptions();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceWithMethods() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderDstu2Hl7Org.class, new TestJaxRsMockPatientRestProviderDstu2Hl7Org());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
assertTrue(response.getEntity().toString().contains("\"type\": \"Patient\""));
|
||||
assertTrue(response.getEntity().toString().contains("someCustomOperation"));
|
||||
System.out.println(response);
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceInXml() throws Exception {
|
||||
queryParameters.put(Constants.PARAM_FORMAT, Arrays.asList(Constants.CT_XML));
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderDstu2Hl7Org.class, new TestJaxRsMockPatientRestProviderDstu2Hl7Org());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
System.out.println(response.getEntity());
|
||||
assertTrue(response.getEntity().toString().contains(" <type value=\"Patient\"/>"));
|
||||
assertTrue(response.getEntity().toString().contains("someCustomOperation"));
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
private AbstractJaxRsConformanceProvider createConformanceProvider(final ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers)
|
||||
throws Exception {
|
||||
AbstractJaxRsConformanceProvider result = new AbstractJaxRsConformanceProvider(FhirContext.forDstu2Hl7Org(), null, null, null) {
|
||||
@Override
|
||||
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
};
|
||||
// mocks
|
||||
UriInfo uriInfo = mock(UriInfo.class);
|
||||
when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
|
||||
when(uriInfo.getBaseUri()).thenReturn(new URI(BASEURI));
|
||||
when(uriInfo.getRequestUri()).thenReturn(new URI(BASEURI + "/foo"));
|
||||
result.setUriInfo(uriInfo);
|
||||
result.setHeaders(headers);
|
||||
result.setUpPostConstruct();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.*;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderDstu2_1;
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu2_1;
|
||||
import org.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
public class AbstractJaxRsConformanceProviderDstu2_1Test {
|
||||
|
||||
private static final String BASEURI = "http://basiuri";
|
||||
private static final String REQUESTURI = BASEURI + "/metadata";
|
||||
AbstractJaxRsConformanceProvider provider;
|
||||
private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers;
|
||||
private ContainerRequest headers;
|
||||
private MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// headers
|
||||
headers = new ContainerRequest(new URI(BASEURI), new URI(REQUESTURI), HttpMethod.GET, null,
|
||||
new MapPropertiesDelegate());
|
||||
// uri info
|
||||
queryParameters = new MultivaluedHashMap<String, String>();
|
||||
|
||||
|
||||
providers = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||
provider = createConformanceProvider(providers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformance() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderDstu2_1.class, new TestJaxRsDummyPatientProviderDstu2_1());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceUsingOptions() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderDstu2_1.class, new TestJaxRsDummyPatientProviderDstu2_1());
|
||||
Response response = createConformanceProvider(providers).conformanceUsingOptions();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceWithMethods() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderDstu2_1.class, new TestJaxRsMockPatientRestProviderDstu2_1());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
assertTrue(response.getEntity().toString().contains("\"type\": \"Patient\""));
|
||||
assertTrue(response.getEntity().toString().contains("\"someCustomOperation"));
|
||||
System.out.println(response);
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceInXml() throws Exception {
|
||||
queryParameters.put(Constants.PARAM_FORMAT, Arrays.asList(Constants.CT_XML));
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderDstu2_1.class, new TestJaxRsMockPatientRestProviderDstu2_1());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
System.out.println(response.getEntity());
|
||||
assertTrue(response.getEntity().toString().contains(" <type value=\"Patient\"/>"));
|
||||
assertTrue(response.getEntity().toString().contains("\"someCustomOperation"));
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
private AbstractJaxRsConformanceProvider createConformanceProvider(final ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers)
|
||||
throws Exception {
|
||||
AbstractJaxRsConformanceProvider result = new AbstractJaxRsConformanceProvider(FhirContext.forDstu2_1(), null, null, null) {
|
||||
@Override
|
||||
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
};
|
||||
// mocks
|
||||
UriInfo uriInfo = mock(UriInfo.class);
|
||||
when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
|
||||
when(uriInfo.getBaseUri()).thenReturn(new URI(BASEURI));
|
||||
when(uriInfo.getRequestUri()).thenReturn(new URI(BASEURI + "/foo"));
|
||||
result.setUriInfo(uriInfo);
|
||||
result.setHeaders(headers);
|
||||
result.setUpPostConstruct();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.*;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderR4;
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderR4;
|
||||
import org.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
public class AbstractJaxRsConformanceProviderR4Test {
|
||||
|
||||
private static final String BASEURI = "http://basiuri";
|
||||
private static final String REQUESTURI = BASEURI + "/metadata";
|
||||
AbstractJaxRsConformanceProvider provider;
|
||||
private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers;
|
||||
private ContainerRequest headers;
|
||||
private MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// headers
|
||||
headers = new ContainerRequest(new URI(BASEURI), new URI(REQUESTURI), HttpMethod.GET, null,
|
||||
new MapPropertiesDelegate());
|
||||
// uri info
|
||||
queryParameters = new MultivaluedHashMap<String, String>();
|
||||
|
||||
|
||||
providers = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||
provider = createConformanceProvider(providers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformance() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderR4.class, new TestJaxRsDummyPatientProviderR4());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceUsingOptions() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsDummyPatientProviderR4.class, new TestJaxRsDummyPatientProviderR4());
|
||||
Response response = createConformanceProvider(providers).conformanceUsingOptions();
|
||||
System.out.println(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceWithMethods() throws Exception {
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderR4.class, new TestJaxRsMockPatientRestProviderR4());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
assertTrue(response.getEntity().toString().contains("\"type\": \"Patient\""));
|
||||
assertTrue(response.getEntity().toString().contains("\"someCustomOperation"));
|
||||
System.out.println(response);
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConformanceInXml() throws Exception {
|
||||
queryParameters.put(Constants.PARAM_FORMAT, Arrays.asList(Constants.CT_XML));
|
||||
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||
providers.put(TestJaxRsMockPatientRestProviderR4.class, new TestJaxRsMockPatientRestProviderR4());
|
||||
Response response = createConformanceProvider(providers).conformance();
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||
System.out.println(response.getEntity());
|
||||
assertTrue(response.getEntity().toString().contains(" <type value=\"Patient\"/>"));
|
||||
assertTrue(response.getEntity().toString().contains("\"someCustomOperation"));
|
||||
System.out.println(response.getEntity());
|
||||
}
|
||||
|
||||
private AbstractJaxRsConformanceProvider createConformanceProvider(final ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers)
|
||||
throws Exception {
|
||||
AbstractJaxRsConformanceProvider result = new AbstractJaxRsConformanceProvider(FhirContext.forR4(), null, null, null) {
|
||||
@Override
|
||||
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
};
|
||||
// mocks
|
||||
UriInfo uriInfo = mock(UriInfo.class);
|
||||
when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
|
||||
when(uriInfo.getBaseUri()).thenReturn(new URI(BASEURI));
|
||||
when(uriInfo.getRequestUri()).thenReturn(new URI(BASEURI + "/foo"));
|
||||
result.setUriInfo(uriInfo);
|
||||
result.setHeaders(headers);
|
||||
result.setUpPostConstruct();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.ws.rs.core.*;
|
||||
|
||||
|
@ -41,8 +42,16 @@ public class AbstractJaxRsProviderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWithStackTrace() {
|
||||
assertFalse(provider.withStackTrace());
|
||||
public void testHandleExceptionDataFormatException() throws IOException, URISyntaxException {
|
||||
final DataFormatException theException = new DataFormatException();
|
||||
UriInfo uriInfo = mock(UriInfo.class);
|
||||
when(uriInfo.getRequestUri()).thenReturn(new URI("http://example.com"));
|
||||
when(uriInfo.getBaseUri()).thenReturn(new URI("http://example.com"));
|
||||
when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<String, String>());
|
||||
provider.setUriInfo(uriInfo);
|
||||
final Response result = provider.handleException(theRequest, theException);
|
||||
assertNotNull(result);
|
||||
assertEquals(Constants.STATUS_HTTP_400_BAD_REQUEST, result.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -54,14 +63,6 @@ public class AbstractJaxRsProviderTest {
|
|||
assertEquals(base.getStatusCode(), result.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExceptionDataFormatException() throws IOException {
|
||||
final DataFormatException theException = new DataFormatException();
|
||||
final Response result = provider.handleException(theRequest, theException);
|
||||
assertNotNull(result);
|
||||
assertEquals(Constants.STATUS_HTTP_400_BAD_REQUEST, result.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExceptionRuntimeException() throws IOException, URISyntaxException {
|
||||
final RuntimeException theException = new RuntimeException();
|
||||
|
@ -76,4 +77,9 @@ public class AbstractJaxRsProviderTest {
|
|||
assertNotNull(result);
|
||||
assertEquals(Constants.STATUS_HTTP_500_INTERNAL_ERROR, result.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithStackTrace() {
|
||||
assertFalse(provider.withStackTrace());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import org.hl7.fhir.instance.model.Patient;
|
||||
|
||||
/**
|
||||
* A dummy patient provider exposing no methods
|
||||
*/
|
||||
public class TestJaxRsDummyPatientProviderDstu2Hl7Org extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import org.hl7.fhir.dstu2016may.model.Patient;
|
||||
|
||||
/**
|
||||
* A dummy patient provider exposing no methods
|
||||
*/
|
||||
public class TestJaxRsDummyPatientProviderDstu2_1 extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
||||
/**
|
||||
* A dummy patient provider exposing no methods
|
||||
*/
|
||||
public class TestJaxRsDummyPatientProviderR4 extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.hl7.fhir.instance.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
|
||||
/**
|
||||
* A test server delegating each call to a mock
|
||||
*/
|
||||
@Path(TestJaxRsMockPatientRestProviderDstu2Hl7Org.PATH)
|
||||
@Stateless
|
||||
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_XML_NEW })
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public class TestJaxRsMockPatientRestProviderDstu2Hl7Org extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
static final String PATH = "/Patient";
|
||||
|
||||
public static final TestJaxRsMockPatientRestProviderDstu2Hl7Org mock = Mockito.mock(TestJaxRsMockPatientRestProviderDstu2Hl7Org.class);
|
||||
|
||||
public static final FifoMemoryPagingProvider PAGING_PROVIDER;
|
||||
|
||||
static
|
||||
{
|
||||
PAGING_PROVIDER = new FifoMemoryPagingProvider(10);
|
||||
PAGING_PROVIDER.setDefaultPageSize(10);
|
||||
PAGING_PROVIDER.setMaximumPageSize(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TestJaxRsMockPatientRestProviderDstu2Hl7Org() {
|
||||
super(FhirContext.forDstu2Hl7Org());
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name, @RequiredParam(name=Patient.SP_ADDRESS) StringAndListParam theAddressParts) {
|
||||
return mock.search(name, theAddressParts);
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient,@ConditionalUrlParam final String theConditional) throws Exception {
|
||||
return mock.update(theId, patient, theConditional);
|
||||
}
|
||||
|
||||
@Read
|
||||
public Patient find(@IdParam final IdType theId) {
|
||||
return mock.find(theId);
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient findHistory(@IdParam final IdType theId) {
|
||||
return mock.findHistory(theId);
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||
throws Exception {
|
||||
return mock.create(patient, theConditional);
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam final IdType theId, @ConditionalUrlParam final String theConditional) {
|
||||
return mock.delete(theId, theConditional);
|
||||
}
|
||||
|
||||
@Search(compartmentName = "Condition")
|
||||
public List<IBaseResource> searchCompartment(@IdParam IdType thePatientId) {
|
||||
return mock.searchCompartment(thePatientId);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingGet(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.GET, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingPost(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.POST, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@Operation(name = "someCustomOperation", idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "return", type = StringType.class) })
|
||||
public Parameters someCustomOperation(@IdParam IdType myId, @OperationParam(name = "dummy") StringType dummyInput) {
|
||||
return mock.someCustomOperation(myId, dummyInput);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validate(@ResourceParam final Patient resource) {
|
||||
MethodOutcome mO = new MethodOutcome();
|
||||
mO.setOperationOutcome(new OperationOutcome());
|
||||
return mO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return PAGING_PROVIDER;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.hl7.fhir.dstu2016may.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
|
||||
/**
|
||||
* A test server delegating each call to a mock
|
||||
*/
|
||||
@Path(TestJaxRsMockPatientRestProviderDstu2_1.PATH)
|
||||
@Stateless
|
||||
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_XML_NEW })
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public class TestJaxRsMockPatientRestProviderDstu2_1 extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
static final String PATH = "/Patient";
|
||||
|
||||
public static final TestJaxRsMockPatientRestProviderDstu2_1 mock = Mockito.mock(TestJaxRsMockPatientRestProviderDstu2_1.class);
|
||||
|
||||
public static final FifoMemoryPagingProvider PAGING_PROVIDER;
|
||||
|
||||
static
|
||||
{
|
||||
PAGING_PROVIDER = new FifoMemoryPagingProvider(10);
|
||||
PAGING_PROVIDER.setDefaultPageSize(10);
|
||||
PAGING_PROVIDER.setMaximumPageSize(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TestJaxRsMockPatientRestProviderDstu2_1() {
|
||||
super(FhirContext.forDstu2_1());
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name, @RequiredParam(name=Patient.SP_ADDRESS) StringAndListParam theAddressParts) {
|
||||
return mock.search(name, theAddressParts);
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient,@ConditionalUrlParam final String theConditional) throws Exception {
|
||||
return mock.update(theId, patient, theConditional);
|
||||
}
|
||||
|
||||
@Read
|
||||
public Patient find(@IdParam final IdType theId) {
|
||||
return mock.find(theId);
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient findHistory(@IdParam final IdType theId) {
|
||||
return mock.findHistory(theId);
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||
throws Exception {
|
||||
return mock.create(patient, theConditional);
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam final IdType theId, @ConditionalUrlParam final String theConditional) {
|
||||
return mock.delete(theId, theConditional);
|
||||
}
|
||||
|
||||
@Search(compartmentName = "Condition")
|
||||
public List<IBaseResource> searchCompartment(@IdParam IdType thePatientId) {
|
||||
return mock.searchCompartment(thePatientId);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingGet(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.GET, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingPost(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.POST, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@Operation(name = "someCustomOperation", idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "return", type = StringType.class) })
|
||||
public Parameters someCustomOperation(@IdParam IdType myId, @OperationParam(name = "dummy") StringType dummyInput) {
|
||||
return mock.someCustomOperation(myId, dummyInput);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validate(@ResourceParam final Patient resource) {
|
||||
MethodOutcome mO = new MethodOutcome();
|
||||
mO.setOperationOutcome(new OperationOutcome());
|
||||
return mO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return PAGING_PROVIDER;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package ca.uhn.fhir.jaxrs.server.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
|
||||
/**
|
||||
* A test server delegating each call to a mock
|
||||
*/
|
||||
@Path(TestJaxRsMockPatientRestProviderR4.PATH)
|
||||
@Stateless
|
||||
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_XML_NEW })
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public class TestJaxRsMockPatientRestProviderR4 extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
static final String PATH = "/Patient";
|
||||
|
||||
public static final TestJaxRsMockPatientRestProviderR4 mock = Mockito.mock(TestJaxRsMockPatientRestProviderR4.class);
|
||||
|
||||
public static final FifoMemoryPagingProvider PAGING_PROVIDER;
|
||||
|
||||
static
|
||||
{
|
||||
PAGING_PROVIDER = new FifoMemoryPagingProvider(10);
|
||||
PAGING_PROVIDER.setDefaultPageSize(10);
|
||||
PAGING_PROVIDER.setMaximumPageSize(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TestJaxRsMockPatientRestProviderR4() {
|
||||
super(FhirContext.forR4());
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name, @RequiredParam(name=Patient.SP_ADDRESS) StringAndListParam theAddressParts) {
|
||||
return mock.search(name, theAddressParts);
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient,@ConditionalUrlParam final String theConditional) throws Exception {
|
||||
return mock.update(theId, patient, theConditional);
|
||||
}
|
||||
|
||||
@Read
|
||||
public Patient find(@IdParam final IdType theId) {
|
||||
return mock.find(theId);
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient findHistory(@IdParam final IdType theId) {
|
||||
return mock.findHistory(theId);
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||
throws Exception {
|
||||
return mock.create(patient, theConditional);
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam final IdType theId, @ConditionalUrlParam final String theConditional) {
|
||||
return mock.delete(theId, theConditional);
|
||||
}
|
||||
|
||||
@Search(compartmentName = "Condition")
|
||||
public List<IBaseResource> searchCompartment(@IdParam IdType thePatientId) {
|
||||
return mock.searchCompartment(thePatientId);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingGet(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.GET, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/$someCustomOperation")
|
||||
public Response someCustomOperationUsingPost(@PathParam("id") String id, String resource) throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.POST, id, "$someCustomOperation",
|
||||
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
}
|
||||
|
||||
@Operation(name = "someCustomOperation", idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "return", type = StringType.class) })
|
||||
public Parameters someCustomOperation(@IdParam IdType myId, @OperationParam(name = "dummy") StringType dummyInput) {
|
||||
return mock.someCustomOperation(myId, dummyInput);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validate(@ResourceParam final Patient resource) {
|
||||
MethodOutcome mO = new MethodOutcome();
|
||||
mO.setOperationOutcome(new OperationOutcome());
|
||||
return mO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return PAGING_PROVIDER;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public class JaxRsConformanceProvider extends AbstractJaxRsConformanceProvider {
|
|||
* Standard Constructor
|
||||
*/
|
||||
public JaxRsConformanceProvider() {
|
||||
super(SERVER_VERSION, SERVER_DESCRIPTION, SERVER_NAME);
|
||||
super(SERVER_DESCRIPTION, SERVER_NAME, SERVER_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,7 +33,7 @@ public class JaxRsConformanceProviderDstu3 extends AbstractJaxRsConformanceProvi
|
|||
* Standard Constructor
|
||||
*/
|
||||
public JaxRsConformanceProviderDstu3() {
|
||||
super(FhirContext.forDstu3(), SERVER_VERSION, SERVER_DESCRIPTION, SERVER_NAME);
|
||||
super(FhirContext.forDstu3(), SERVER_DESCRIPTION, SERVER_NAME, SERVER_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
|
@ -229,14 +228,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||
partsChoices.add(nextChoicesList);
|
||||
|
||||
String key = UrlUtil.escape(nextCompositeOf.getName());
|
||||
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||
if (paramsListForCompositePart != null) {
|
||||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(getContext());
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escape(value);
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +245,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
for (ResourceLink nextLink : linksForCompositePart) {
|
||||
String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue();
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escape(value);
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
|
@ -2015,7 +2014,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
/*
|
||||
* The following block of code is used to strip out diacritical marks from latin script
|
||||
* and also convert to upper case. E.g. "jåmes" becomes "JAMES".
|
||||
* and also convert to upper case. E.g. "j?mes" becomes "JAMES".
|
||||
*
|
||||
* See http://www.unicode.org/charts/PDF/U0300.pdf for the logic
|
||||
* behind stripping 0300-036F
|
||||
|
|
|
@ -256,6 +256,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
deletedResources.add(entity);
|
||||
|
||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
// Notify interceptors
|
||||
|
@ -268,9 +269,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
// Perform delete
|
||||
Date updateTime = new Date();
|
||||
updateEntity(null, entity, updateTime, updateTime);
|
||||
resourceToDelete.setId(entity.getIdDt());
|
||||
|
||||
// Notify JPA interceptors
|
||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete);
|
||||
|
|
|
@ -60,7 +60,6 @@ import org.hibernate.ScrollMode;
|
|||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hl7.fhir.dstu3.model.BaseResource;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -175,7 +174,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
if (valueBuilder.length() > 0) {
|
||||
valueBuilder.append(',');
|
||||
}
|
||||
valueBuilder.append(UrlUtil.escape(next.getValueAsQueryToken(myContext)));
|
||||
valueBuilder.append(UrlUtil.escapeUrlParam(next.getValueAsQueryToken(myContext)));
|
||||
targetResourceType = next.getTargetResourceType();
|
||||
owningParameter = next.getOwningFieldName();
|
||||
parameterName = next.getParameterName();
|
||||
|
@ -185,7 +184,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
continue;
|
||||
}
|
||||
|
||||
String matchUrl = targetResourceType + '?' + UrlUtil.escape(parameterName) + '=' + valueBuilder.toString();
|
||||
String matchUrl = targetResourceType + '?' + UrlUtil.escapeUrlParam(parameterName) + '=' + valueBuilder.toString();
|
||||
RuntimeResourceDefinition targetResourceDefinition;
|
||||
try {
|
||||
targetResourceDefinition = myContext.getResourceDefinition(targetResourceType);
|
||||
|
@ -1272,13 +1271,13 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
List<List<String>> params = new ArrayList<>();
|
||||
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamNameToValues : theParams.entrySet()) {
|
||||
String nextParamName = nextParamNameToValues.getKey();
|
||||
nextParamName = UrlUtil.escape(nextParamName);
|
||||
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
|
||||
for (List<? extends IQueryParameterType> nextAnd : nextParamNameToValues.getValue()) {
|
||||
ArrayList<String> nextValueList = new ArrayList<>();
|
||||
params.add(nextValueList);
|
||||
for (IQueryParameterType nextOr : nextAnd) {
|
||||
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
||||
nextOrValue = UrlUtil.escape(nextOrValue);
|
||||
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
|
||||
nextValueList.add(nextParamName + "=" + nextOrValue);
|
||||
}
|
||||
}
|
||||
|
@ -2000,6 +1999,9 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
|
||||
private static List<Long> filterResourceIdsByLastUpdated(EntityManager theEntityManager, final DateRangeParam theLastUpdated, Collection<Long> thePids) {
|
||||
if (thePids.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
CriteriaBuilder builder = theEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
|
@ -24,7 +23,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
import java.util.*;
|
||||
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
@ -138,9 +136,9 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
|||
addUrlParamSeparator(b);
|
||||
b.append(paramName);
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextInclude.getParamType()));
|
||||
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamType()));
|
||||
b.append(':');
|
||||
b.append(UrlUtil.escape(nextInclude.getParamName()));
|
||||
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamName()));
|
||||
if (isNotBlank(nextInclude.getParamTargetType())) {
|
||||
b.append(':');
|
||||
b.append(nextInclude.getParamTargetType());
|
||||
|
@ -314,7 +312,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
|||
for (List<IQueryParameterType> nextValuesAnd : nextValuesAndsOut) {
|
||||
addUrlParamSeparator(b);
|
||||
IQueryParameterType firstValue = nextValuesAnd.get(0);
|
||||
b.append(UrlUtil.escape(nextKey));
|
||||
b.append(UrlUtil.escapeUrlParam(nextKey));
|
||||
|
||||
if (firstValue.getMissing() != null) {
|
||||
b.append(Constants.PARAMQUALIFIER_MISSING);
|
||||
|
@ -340,7 +338,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
|||
}
|
||||
String valueAsQueryToken = nextValueOr.getValueAsQueryToken(theCtx);
|
||||
// b.append(ParameterUtil.escapeAndUrlEncode(valueAsQueryToken));
|
||||
b.append(UrlUtil.escape(valueAsQueryToken));
|
||||
b.append(UrlUtil.escapeUrlParam(valueAsQueryToken));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -676,7 +676,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
String nextReplacementIdPart = nextReplacementId.getValueAsString();
|
||||
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
|
||||
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
|
||||
matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart);
|
||||
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -667,7 +667,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
String nextReplacementIdPart = nextReplacementId.getValueAsString();
|
||||
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
|
||||
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
|
||||
matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart);
|
||||
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.search;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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 org.apache.lucene.analysis.core.LowerCaseFilterFactory;
|
||||
import org.apache.lucene.analysis.core.StopFilterFactory;
|
||||
import org.apache.lucene.analysis.core.WhitespaceTokenizerFactory;
|
||||
|
|
|
@ -593,6 +593,9 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
shouldSync = true;
|
||||
}
|
||||
|
||||
// If no abort was requested, bail out
|
||||
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
|
||||
|
||||
if (shouldSync) {
|
||||
saveUnsynced(theResultIterator);
|
||||
}
|
||||
|
@ -605,10 +608,11 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if an abort got requested
|
||||
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
|
||||
|
||||
}
|
||||
|
||||
// If no abort was requested, bail out
|
||||
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
|
||||
|
||||
saveUnsynced(theResultIterator);
|
||||
}
|
||||
|
||||
|
|
|
@ -321,7 +321,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
cs.setUrl(theSystem);
|
||||
cs.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
|
||||
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
|
||||
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escapeUrlParam(theSystem), theRequestDetails);
|
||||
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
|
||||
if (createOutcome.getCreated() != Boolean.TRUE) {
|
||||
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);
|
||||
|
|
|
@ -325,7 +325,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal
|
|||
cs.setUrl(theSystem);
|
||||
cs.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
|
||||
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
|
||||
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escapeUrlParam(theSystem), theRequestDetails);
|
||||
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
|
||||
if (createOutcome.getCreated() != Boolean.TRUE) {
|
||||
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);
|
||||
|
|
|
@ -30,7 +30,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
public DataSource dataSource() {
|
||||
BasicDataSource retVal = new BasicDataSource();
|
||||
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDBDstu2;create=true");
|
||||
retVal.setUsername("");
|
||||
retVal.setPassword("");
|
||||
return retVal;
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
|
||||
};
|
||||
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDBDstu3;create=true");
|
||||
retVal.setMaxWaitMillis(10000);
|
||||
retVal.setUsername("");
|
||||
retVal.setPassword("");
|
||||
|
|
|
@ -85,7 +85,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
|
||||
};
|
||||
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
|
||||
retVal.setUrl("jdbc:derby:memory:myUnitTestDBR4;create=true");
|
||||
retVal.setMaxWaitMillis(10000);
|
||||
retVal.setUsername("");
|
||||
retVal.setPassword("");
|
||||
|
|
|
@ -1,38 +1,12 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hibernate.search.jpa.Search;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
|
||||
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
|
||||
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -41,6 +15,31 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hibernate.search.jpa.Search;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
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.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public abstract class BaseJpaTest {
|
||||
|
||||
|
@ -53,13 +52,23 @@ public abstract class BaseJpaTest {
|
|||
public void beforeCreateSrd() {
|
||||
mySrd = mock(ServletRequestDetails.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
when(mySrd.getRequestOperationCallback()).thenReturn(myRequestOperationCallback);
|
||||
myServerInterceptorList = new ArrayList<IServerInterceptor>();
|
||||
myServerInterceptorList = new ArrayList<>();
|
||||
when(mySrd.getServer().getInterceptors()).thenReturn(myServerInterceptorList);
|
||||
when(mySrd.getUserData()).thenReturn(new HashMap<Object, Object>());
|
||||
when(mySrd.getUserData()).thenReturn(new HashMap<>());
|
||||
}
|
||||
|
||||
protected abstract FhirContext getContext();
|
||||
|
||||
/**
|
||||
* Sleep until at least 1 ms has elapsed
|
||||
*/
|
||||
public void sleepUntilTimeChanges() throws InterruptedException {
|
||||
StopWatch sw = new StopWatch();
|
||||
while (sw.getMillis() == 0) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
protected org.hl7.fhir.dstu3.model.Bundle toBundle(IBundleProvider theSearch) {
|
||||
org.hl7.fhir.dstu3.model.Bundle bundle = new org.hl7.fhir.dstu3.model.Bundle();
|
||||
for (IBaseResource next : theSearch.getResources(0, theSearch.size())) {
|
||||
|
@ -76,11 +85,11 @@ public abstract class BaseJpaTest {
|
|||
return bundle;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
protected List toList(IBundleProvider theSearch) {
|
||||
return theSearch.getResources(0, theSearch.size());
|
||||
}
|
||||
|
||||
|
||||
protected List<String> toUnqualifiedIdValues(IBaseBundle theFound) {
|
||||
List<String> retVal = new ArrayList<String>();
|
||||
|
||||
|
@ -214,9 +223,9 @@ public abstract class BaseJpaTest {
|
|||
}
|
||||
|
||||
public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) {
|
||||
|
||||
|
||||
theSearchCoordinatorSvc.cancelAllActiveSearches();
|
||||
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(theTxManager);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
|
|
|
@ -461,7 +461,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
@ -2346,7 +2346,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSortByLastUpdated() {
|
||||
public void testSortByLastUpdated() throws InterruptedException {
|
||||
String methodName = "testSortByLastUpdated";
|
||||
|
||||
Patient p = new Patient();
|
||||
|
@ -2354,21 +2354,29 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
p.addName().addFamily(methodName);
|
||||
IIdType id1 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
sleepUntilTimeChanges();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system2").setValue(methodName);
|
||||
p.addName().addFamily(methodName);
|
||||
IIdType id2 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
sleepUntilTimeChanges();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system3").setValue(methodName);
|
||||
p.addName().addFamily(methodName);
|
||||
IIdType id3 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
sleepUntilTimeChanges();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system4").setValue(methodName);
|
||||
p.addName().addFamily(methodName);
|
||||
IIdType id4 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
sleepUntilTimeChanges();
|
||||
|
||||
SearchParameterMap pm;
|
||||
List<IIdType> actual;
|
||||
|
||||
|
|
|
@ -573,7 +573,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
|||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.test.util.AopTestUtils;
|
||||
|
@ -16,10 +19,11 @@ import org.springframework.transaction.TransactionStatus;
|
|||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoDstu3SearchPageExpiryTest.class);
|
||||
|
@ -104,14 +108,17 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
|
|||
// Search just got used so it shouldn't be deleted
|
||||
|
||||
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
|
||||
final AtomicLong search3timestamp = new AtomicLong();
|
||||
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
|
||||
assertNotNull(mySearchEntityDao.findByUuid(searchUuid3));
|
||||
Search search3 = mySearchEntityDao.findByUuid(searchUuid3);
|
||||
assertNotNull(search3);
|
||||
search3timestamp.set(search3.getCreated().getTime());
|
||||
}
|
||||
});
|
||||
|
||||
StaleSearchDeletingSvcImpl.setNowForUnitTests(start + 1400);
|
||||
StaleSearchDeletingSvcImpl.setNowForUnitTests(search3timestamp.get() + 1400);
|
||||
|
||||
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
|
||||
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
|
||||
|
@ -127,14 +134,14 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
});
|
||||
|
||||
StaleSearchDeletingSvcImpl.setNowForUnitTests(start + 2200);
|
||||
StaleSearchDeletingSvcImpl.setNowForUnitTests(search3timestamp.get() + 2200);
|
||||
|
||||
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
|
||||
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
|
||||
assertNull(mySearchEntityDao.findByUuid(searchUuid1));
|
||||
assertNull(mySearchEntityDao.findByUuid(searchUuid3));
|
||||
assertNull("Search 1 still exists", mySearchEntityDao.findByUuid(searchUuid1));
|
||||
assertNull("Search 3 still exists", mySearchEntityDao.findByUuid(searchUuid3));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -688,7 +688,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
|||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
|
|
@ -939,7 +939,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
|
|
@ -730,7 +730,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
|||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
|
|
@ -1018,7 +1018,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
|||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||
details = detailsCapt.getValue();
|
||||
assertNotNull(details.getId());
|
||||
assertNull(details.getId());
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import ca.uhn.fhir.model.dstu2.resource.*;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.*;
|
||||
import ca.uhn.fhir.model.primitive.*;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
|
@ -528,7 +527,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
pt.addName().addFamily("FOO");
|
||||
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdDt id2;
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.*;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
@ -41,92 +41,66 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
unregisterInterceptors();
|
||||
}
|
||||
|
||||
|
||||
private void unregisterInterceptors() {
|
||||
for (IServerInterceptor next : new ArrayList<IServerInterceptor>(ourRestServer.getInterceptors())) {
|
||||
if (next instanceof AuthorizationInterceptor) {
|
||||
ourRestServer.unregisterInterceptor(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See #503
|
||||
* See #667
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteIsBlocked() {
|
||||
|
||||
public void testBlockUpdatingPatientUserDoesnNotHaveAccessTo() throws IOException {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setActive(true);
|
||||
final IIdType pid1 = ourClient.create().resource(pt1).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setActive(false);
|
||||
final IIdType pid2 = ourClient.create().resource(pt2).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
.allow().write().allResources().inCompartment("Patient", pid1).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
IIdType id = ourClient.create().resource(patient).execute().getId();
|
||||
|
||||
try {
|
||||
ourClient.delete().resourceById(id.toUnqualifiedVersionless()).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
patient = ourClient.read().resource(Patient.class).withId(id.toUnqualifiedVersionless()).execute();
|
||||
assertEquals(id.getValue(), patient.getId());
|
||||
}
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid1));
|
||||
IIdType oid = ourClient.create().resource(obs).execute().getId().toUnqualified();
|
||||
|
||||
/**
|
||||
* See #503
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteIsAllowedForCompartment() {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
final IIdType id = ourClient.create().resource(patient).execute().getId();
|
||||
|
||||
Observation obsInCompartment = new Observation();
|
||||
obsInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
obsInCompartment.getSubject().setReferenceElement(id.toUnqualifiedVersionless());
|
||||
IIdType obsInCompartmentId = ourClient.create().resource(obsInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsNotInCompartment = new Observation();
|
||||
obsNotInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
IIdType obsNotInCompartmentId = ourClient.create().resource(obsNotInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
|
||||
unregisterInterceptors();
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().delete().resourcesOfType(Observation.class).inCompartment("Patient", id).andThen()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
.allow().write().allResources().inCompartment("Patient", pid2).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
ourClient.delete().resourceById(obsInCompartmentId.toUnqualifiedVersionless()).execute();
|
||||
|
||||
/*
|
||||
* Try to update to a new patient. The user has access to write to things in
|
||||
* pid2's compartment, so this would normally be ok, but in this case they are overwriting
|
||||
* a resource that is already in pid1's compartment, which shouldn't be allowed.
|
||||
*/
|
||||
obs = new Observation();
|
||||
obs.setId(oid);
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid2));
|
||||
|
||||
try {
|
||||
ourClient.delete().resourceById(obsNotInCompartmentId.toUnqualifiedVersionless()).execute();
|
||||
ourClient.update().resource(obs).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateConditional() {
|
||||
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
@ -135,15 +109,13 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("Rule 2").write().allResources().inCompartment("Patient", new IdDt("Patient/" + output1.getId().getIdPart())).andThen()
|
||||
.allow().updateConditional().allResources()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId(output1.getId().toUnqualifiedVersionless());
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
|
@ -151,7 +123,7 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
MethodOutcome output2 = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
assertEquals(output1.getId().getIdPart(), output2.getId().getIdPart());
|
||||
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
|
@ -176,62 +148,82 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
}
|
||||
|
||||
/**
|
||||
* See #667
|
||||
* See #503 #751
|
||||
*/
|
||||
@Test
|
||||
public void testBlockUpdatingPatientUserDoesnNotHaveAccessTo() throws IOException {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setActive(true);
|
||||
final IIdType pid1 = ourClient.create().resource(pt1).execute().getId().toUnqualifiedVersionless();
|
||||
public void testDeleteIsAllowedForCompartment() {
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setActive(false);
|
||||
final IIdType pid2 = ourClient.create().resource(pt2).execute().getId().toUnqualifiedVersionless();
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
final IIdType id = ourClient.create().resource(patient).execute().getId();
|
||||
|
||||
Observation obsInCompartment = new Observation();
|
||||
obsInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
obsInCompartment.getSubject().setReferenceElement(id.toUnqualifiedVersionless());
|
||||
IIdType obsInCompartmentId = ourClient.create().resource(obsInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
// create a 2nd observation to be deleted by url Observation?patient=id
|
||||
ourClient.create().resource(obsInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsNotInCompartment = new Observation();
|
||||
obsNotInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
IIdType obsNotInCompartmentId = ourClient.create().resource(obsNotInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().write().allResources().inCompartment("Patient", pid1).andThen()
|
||||
.allow().delete().resourcesOfType(Observation.class).inCompartment("Patient", id).andThen()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid1));
|
||||
IIdType oid = ourClient.create().resource(obs).execute().getId().toUnqualified();
|
||||
|
||||
|
||||
unregisterInterceptors();
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().write().allResources().inCompartment("Patient", pid2).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Try to update to a new patient. The user has access to write to things in
|
||||
* pid2's compartment, so this would normally be ok, but in this case they are overwriting
|
||||
* a resource that is already in pid1's compartment, which shouldn't be allowed.
|
||||
*/
|
||||
obs = new Observation();
|
||||
obs.setId(oid);
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid2));
|
||||
|
||||
ourClient.delete().resourceById(obsInCompartmentId.toUnqualifiedVersionless()).execute();
|
||||
ourClient.delete().resourceConditionalByUrl("Observation?patient=" + id.toUnqualifiedVersionless()).execute();
|
||||
|
||||
try {
|
||||
ourClient.update().resource(obs).execute();
|
||||
ourClient.delete().resourceById(obsNotInCompartmentId.toUnqualifiedVersionless()).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #503
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteIsBlocked() {
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
IIdType id = ourClient.create().resource(patient).execute().getId();
|
||||
|
||||
try {
|
||||
ourClient.delete().resourceById(id.toUnqualifiedVersionless()).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
patient = ourClient.read().resource(Patient.class).withId(id.toUnqualifiedVersionless()).execute();
|
||||
assertEquals(id.getValue(), patient.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteResourceConditional() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional";
|
||||
|
@ -280,7 +272,7 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
HttpDelete delete = new HttpDelete(ourServerBase + "/Patient?name=" + methodName);
|
||||
response = ourHttpClient.execute(delete);
|
||||
try {
|
||||
|
@ -299,4 +291,17 @@ public class AuthorizationInterceptorResourceProviderDstu3Test extends BaseResou
|
|||
|
||||
}
|
||||
|
||||
private void unregisterInterceptors() {
|
||||
for (IServerInterceptor next : new ArrayList<IServerInterceptor>(ourRestServer.getInterceptors())) {
|
||||
if (next instanceof AuthorizationInterceptor) {
|
||||
ourRestServer.unregisterInterceptor(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1639,7 +1639,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
myObservationDao.create(obs, mySrd);
|
||||
}
|
||||
|
||||
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escape("urn:system|FOO");
|
||||
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
|
||||
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
|
||||
assertThat(ids, contains(pid0.getValue()));
|
||||
}
|
||||
|
@ -2347,7 +2347,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
myPatientDao.create(p, mySrd);
|
||||
}
|
||||
|
||||
String uri = ourServerBase + "/Patient?name=" + URLEncoder.encode("Jernelöv", "UTF-8") + "&_count=5&_pretty=true";
|
||||
String uri = ourServerBase + "/Patient?name=" + UrlUtil.escapeUrlParam("Jernelöv") + "&_count=5&_pretty=true";
|
||||
ourLog.info("URI: {}", uri);
|
||||
HttpGet get = new HttpGet(uri);
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
||||
|
@ -3792,7 +3792,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
pt.addName().setFamily("FOO");
|
||||
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdType id2;
|
||||
|
|
|
@ -1,41 +1,37 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.*;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AuthorizationInterceptorResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
@ -43,45 +39,112 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
|
|||
unregisterInterceptors();
|
||||
}
|
||||
|
||||
|
||||
private void unregisterInterceptors() {
|
||||
for (IServerInterceptor next : new ArrayList<IServerInterceptor>(ourRestServer.getInterceptors())) {
|
||||
if (next instanceof AuthorizationInterceptor) {
|
||||
ourRestServer.unregisterInterceptor(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See #503
|
||||
* See #667
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteIsBlocked() {
|
||||
|
||||
public void testBlockUpdatingPatientUserDoesnNotHaveAccessTo() throws IOException {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setActive(true);
|
||||
final IIdType pid1 = myClient.create().resource(pt1).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setActive(false);
|
||||
final IIdType pid2 = myClient.create().resource(pt2).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
.allow().write().allResources().inCompartment("Patient", pid1).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
IIdType id = myClient.create().resource(patient).execute().getId();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid1));
|
||||
IIdType oid = myClient.create().resource(obs).execute().getId().toUnqualified();
|
||||
|
||||
|
||||
unregisterInterceptors();
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().write().allResources().inCompartment("Patient", pid2).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Try to update to a new patient. The user has access to write to things in
|
||||
* pid2's compartment, so this would normally be ok, but in this case they are overwriting
|
||||
* a resource that is already in pid1's compartment, which shouldn't be allowed.
|
||||
*/
|
||||
obs = new Observation();
|
||||
obs.setId(oid);
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid2));
|
||||
|
||||
try {
|
||||
myClient.delete().resourceById(id.toUnqualifiedVersionless()).execute();
|
||||
myClient.update().resource(obs).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
patient = myClient.read().resource(Patient.class).withId(id.toUnqualifiedVersionless()).execute();
|
||||
assertEquals(id.getValue(), patient.getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateConditional() {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
final MethodOutcome output1 = myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("Rule 2").write().allResources().inCompartment("Patient", new IdDt("Patient/" + output1.getId().getIdPart())).andThen()
|
||||
.allow().updateConditional().allResources()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId(output1.getId().toUnqualifiedVersionless());
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
MethodOutcome output2 = myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
assertEquals(output1.getId().getIdPart(), output2.getId().getIdPart());
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
try {
|
||||
myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|101").execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals("HTTP 403 Forbidden: Access denied by default policy (no applicable rules)", e.getMessage());
|
||||
}
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId("999");
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
try {
|
||||
myClient.update().resource(patient).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals("HTTP 403 Forbidden: Access denied by default policy (no applicable rules)", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,32 +202,32 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
|
|||
*/
|
||||
@Test
|
||||
public void testDeleteIsAllowedForCompartment() {
|
||||
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
final IIdType id = myClient.create().resource(patient).execute().getId();
|
||||
|
||||
|
||||
Observation obsInCompartment = new Observation();
|
||||
obsInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
obsInCompartment.getSubject().setReferenceElement(id.toUnqualifiedVersionless());
|
||||
IIdType obsInCompartmentId = myClient.create().resource(obsInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
|
||||
Observation obsNotInCompartment = new Observation();
|
||||
obsNotInCompartment.setStatus(ObservationStatus.FINAL);
|
||||
IIdType obsNotInCompartmentId = myClient.create().resource(obsNotInCompartment).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().delete().resourcesOfType(Observation.class).inCompartment("Patient", id).andThen()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
.allow().delete().resourcesOfType(Observation.class).inCompartment("Patient", id).andThen()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
myClient.delete().resourceById(obsInCompartmentId.toUnqualifiedVersionless()).execute();
|
||||
|
||||
try {
|
||||
|
@ -175,114 +238,38 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See #503
|
||||
*/
|
||||
@Test
|
||||
public void testCreateConditional() {
|
||||
|
||||
public void testDeleteIsBlocked() {
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.deny().delete().allResources().withAnyId().andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
final MethodOutcome output1 = myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
IIdType id = myClient.create().resource(patient).execute().getId();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("Rule 2").write().allResources().inCompartment("Patient", new IdDt("Patient/" + output1.getId().getIdPart())).andThen()
|
||||
.allow().updateConditional().allResources()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId(output1.getId().toUnqualifiedVersionless());
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
MethodOutcome output2 = myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute();
|
||||
|
||||
assertEquals(output1.getId().getIdPart(), output2.getId().getIdPart());
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
try {
|
||||
myClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|101").execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals("HTTP 403 Forbidden: Access denied by default policy (no applicable rules)", e.getMessage());
|
||||
}
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId("999");
|
||||
patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
|
||||
patient.addName().setFamily("Tester").addGiven("Raghad");
|
||||
try {
|
||||
myClient.update().resource(patient).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals("HTTP 403 Forbidden: Access denied by default policy (no applicable rules)", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #667
|
||||
*/
|
||||
@Test
|
||||
public void testBlockUpdatingPatientUserDoesnNotHaveAccessTo() throws IOException {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setActive(true);
|
||||
final IIdType pid1 = myClient.create().resource(pt1).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setActive(false);
|
||||
final IIdType pid2 = myClient.create().resource(pt2).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().write().allResources().inCompartment("Patient", pid1).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid1));
|
||||
IIdType oid = myClient.create().resource(obs).execute().getId().toUnqualified();
|
||||
|
||||
|
||||
unregisterInterceptors();
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow().write().allResources().inCompartment("Patient", pid2).andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Try to update to a new patient. The user has access to write to things in
|
||||
* pid2's compartment, so this would normally be ok, but in this case they are overwriting
|
||||
* a resource that is already in pid1's compartment, which shouldn't be allowed.
|
||||
*/
|
||||
obs = new Observation();
|
||||
obs.setId(oid);
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setSubject(new Reference(pid2));
|
||||
|
||||
try {
|
||||
myClient.update().resource(obs).execute();
|
||||
myClient.delete().resourceById(id.toUnqualifiedVersionless()).execute();
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
|
||||
patient = myClient.read().resource(Patient.class).withId(id.toUnqualifiedVersionless()).execute();
|
||||
assertEquals(id.getValue(), patient.getId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteResourceConditional() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional";
|
||||
|
@ -331,7 +318,7 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
|
|||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
HttpDelete delete = new HttpDelete(ourServerBase + "/Patient?name=" + methodName);
|
||||
response = ourHttpClient.execute(delete);
|
||||
try {
|
||||
|
@ -350,4 +337,144 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #762
|
||||
*/
|
||||
@Test
|
||||
public void testInstanceRuleOkForResourceWithNoId() {
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.deny().write().instance("Patient/123").andThen()
|
||||
.allowAll()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Create a transaction using linked IDs
|
||||
*/
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.setType(Bundle.BundleType.TRANSACTION);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
p.setId(IdType.newRandomUuid());
|
||||
request.addEntry().setResource(p).getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl(p.getId());
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getCode().setText("Some Observation");
|
||||
o.getSubject().setResource(p);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Bundle resp = myClient.transaction().withBundle(request).execute();
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #762
|
||||
*/
|
||||
@Test
|
||||
public void testInstanceRuleOkForResourceWithNoId2() {
|
||||
|
||||
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("transactions").transaction().withAnyOperation().andApplyNormalRules().andThen()
|
||||
.allow("write patient").write().resourcesOfType(Patient.class).withAnyId().andThen()
|
||||
.allow("write encounter").write().resourcesOfType(Encounter.class).withAnyId().andThen()
|
||||
.allow("write condition").write().resourcesOfType(Condition.class).withAnyId().andThen()
|
||||
.denyAll("deny all")
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Create a bundle that will be used as a transaction
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.TRANSACTION);
|
||||
|
||||
|
||||
|
||||
String encounterId = "123-123";
|
||||
String encounterSystem = "http://our.internal.code.system/encounter";
|
||||
Encounter encounter = new Encounter();
|
||||
|
||||
encounter.addIdentifier(new Identifier().setValue(encounterId)
|
||||
.setSystem(encounterSystem));
|
||||
|
||||
encounter.setStatus(Encounter.EncounterStatus.FINISHED);
|
||||
|
||||
Patient p = new Patient()
|
||||
.addIdentifier(new Identifier().setValue("321-321").setSystem("http://our.internal.code.system/patient"));
|
||||
p.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add patient to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Reference patientRef = new Reference(p.getId());
|
||||
|
||||
encounter.setSubject(patientRef);
|
||||
Condition condition = new Condition()
|
||||
.setCode(new CodeableConcept().addCoding(
|
||||
new Coding("http://hl7.org/fhir/icd-10", "S53.40", "FOREARM SPRAIN / STRAIN")))
|
||||
.setSubject(patientRef);
|
||||
|
||||
condition.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add condition to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setFullUrl(condition.getId())
|
||||
.setResource(condition)
|
||||
.getRequest()
|
||||
.setUrl("Condition")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Encounter.DiagnosisComponent dc = new Encounter.DiagnosisComponent();
|
||||
|
||||
dc.setCondition(new Reference(condition.getId()));
|
||||
encounter.addDiagnosis(dc);
|
||||
CodeableConcept reason = new CodeableConcept();
|
||||
reason.setText("SLIPPED ON FLOOR,PAIN L) ELBOW");
|
||||
encounter.addReason(reason);
|
||||
|
||||
// add encounter to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setResource(encounter)
|
||||
.getRequest()
|
||||
.setUrl("Encounter")
|
||||
.setIfNoneExist("identifier=" + encounterSystem + "|" + encounterId)
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
|
||||
Bundle resp = myClient.transaction().withBundle(bundle).execute();
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
}
|
||||
|
||||
private void unregisterInterceptors() {
|
||||
for (IServerInterceptor next : new ArrayList<IServerInterceptor>(ourRestServer.getInterceptors())) {
|
||||
if (next instanceof AuthorizationInterceptor) {
|
||||
ourRestServer.unregisterInterceptor(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class GraphQLProviderR4Test extends BaseResourceProviderR4Test {
|
|||
initTestPatients();
|
||||
|
||||
String query = "{name{family,given}}";
|
||||
HttpGet httpGet = new HttpGet(ourServerBase + "/Patient/" + myPatientId0.getIdPart() + "/$graphql?query=" + UrlUtil.escape(query));
|
||||
HttpGet httpGet = new HttpGet(ourServerBase + "/Patient/" + myPatientId0.getIdPart() + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(httpGet);
|
||||
try {
|
||||
|
@ -50,7 +50,7 @@ public class GraphQLProviderR4Test extends BaseResourceProviderR4Test {
|
|||
initTestPatients();
|
||||
|
||||
String query = "{PatientList(given:\"given\"){name{family,given}}}";
|
||||
HttpGet httpGet = new HttpGet(ourServerBase + "/$graphql?query=" + UrlUtil.escape(query));
|
||||
HttpGet httpGet = new HttpGet(ourServerBase + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(httpGet);
|
||||
try {
|
||||
|
|
|
@ -61,7 +61,6 @@ import java.math.BigDecimal;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -1647,7 +1646,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
myObservationDao.create(obs, mySrd);
|
||||
}
|
||||
|
||||
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escape("urn:system|FOO");
|
||||
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
|
||||
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
|
||||
assertThat(ids, contains(pid0.getValue()));
|
||||
}
|
||||
|
@ -2355,7 +2354,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
myPatientDao.create(p, mySrd);
|
||||
}
|
||||
|
||||
String uri = ourServerBase + "/Patient?name=" + URLEncoder.encode("Jernelöv", "UTF-8") + "&_count=5&_pretty=true";
|
||||
String uri = ourServerBase + "/Patient?name=" + UrlUtil.escapeUrlParam("Jernelöv") + "&_count=5&_pretty=true";
|
||||
ourLog.info("URI: {}", uri);
|
||||
HttpGet get = new HttpGet(uri);
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
||||
|
@ -2558,6 +2557,59 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* https://chat.fhir.org/#narrow/stream/implementers/topic/Internal.20error.2C.20when.20executing.20the.20following.20query.20on.20HAPI
|
||||
*/
|
||||
@Test
|
||||
public void testSearchByLastUpdatedGe() throws Exception {
|
||||
Patient p2 = new Patient();
|
||||
p2.setId("P2");
|
||||
p2.addName().setFamily("P2");
|
||||
myClient.update().resource(p2).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Practitioner pract = new Practitioner();
|
||||
pract.setId("PRAC");
|
||||
pract.addName().setFamily("PRACT");
|
||||
myClient.update().resource(pract).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Encounter enc = new Encounter();
|
||||
enc.setId("E2");
|
||||
enc.setStatus(EncounterStatus.ARRIVED);
|
||||
enc.setPeriod(new Period().setStart(new Date()).setEnd(new Date()));
|
||||
enc.getSubject().setReference("Patient/P2");
|
||||
enc.addParticipant().getIndividual().setReference("Practitioner/PRAC");
|
||||
myClient.update().resource(enc).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Encounter?patient=P2&date=ge2017-01-01&_include:recurse=Encounter:practitioner&_lastUpdated=ge2017-11-10");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
ourLog.info(output);
|
||||
List<String> ids = toUnqualifiedVersionlessIdValues(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
|
||||
ourLog.info(ids.toString());
|
||||
assertThat(ids, containsInAnyOrder("Practitioner/PRAC", "Encounter/E2"));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
get = new HttpGet(ourServerBase + "/Encounter?patient=P2&date=ge2017-01-01&_include:recurse=Encounter:practitioner&_lastUpdated=ge2099-11-10");
|
||||
response = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
ourLog.info(output);
|
||||
List<String> ids = toUnqualifiedVersionlessIdValues(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
|
||||
ourLog.info(ids.toString());
|
||||
assertThat(ids, empty());
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByReferenceIds() {
|
||||
Organization o1 = new Organization();
|
||||
|
@ -3219,7 +3271,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
// If this fails under load, try increasing the throttle above
|
||||
assertEquals(null, found.getTotalElement().getValue());
|
||||
assertEquals(1, found.getEntry().size());
|
||||
assertThat(sw.getMillis(), lessThan(1000L));
|
||||
assertThat(sw.getMillis(), lessThan(1500L));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -3885,7 +3937,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
pt.addName().setFamily("FOO");
|
||||
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdType id2;
|
||||
|
@ -4301,6 +4353,56 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAndEncodeExtensionWithValueWithExtension() throws IOException {
|
||||
String input = "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
" <extension url=\"https://purl.org/elab/fhir/network/StructureDefinition/1/BirthWeight\">\n" +
|
||||
" <valueDecimal>\n" +
|
||||
" <extension url=\"http://www.hl7.org/fhir/extension-data-absent-reason.html\">\n" +
|
||||
" <valueCoding>\n" +
|
||||
" <system value=\"http://hl7.org/fhir/ValueSet/birthweight\"/>\n" +
|
||||
" <code value=\"Underweight\"/>\n" +
|
||||
" <userSelected value=\"false\"/>\n" +
|
||||
" </valueCoding>\n" +
|
||||
" </extension>\n" +
|
||||
" </valueDecimal>\n" +
|
||||
" </extension>\n" +
|
||||
" <identifier>\n" +
|
||||
" <system value=\"https://purl.org/elab/fhir/network/StructureDefinition/1/EuroPrevallStudySubjects\"/>\n" +
|
||||
" <value value=\"1\"/>\n" +
|
||||
" </identifier>\n" +
|
||||
" <gender value=\"female\"/>\n" +
|
||||
"</Patient>";
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
post.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdType id;
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdType(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Patient/" + id.getIdPart() + "?_pretty=true");
|
||||
response = ourHttpClient.execute(get);
|
||||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
assertThat(resp, containsString("Underweight"));
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testValueSetExpandOperation() throws IOException {
|
||||
CodeSystem cs = myFhirCtx.newXmlParser().parseResource(CodeSystem.class, new InputStreamReader(ResourceProviderR4Test.class.getResourceAsStream("/extensional-case-3-cs.xml")));
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -80,13 +80,13 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
|||
b.append("&tid=").append(myAnalyticsTid);
|
||||
|
||||
b.append("&t=event");
|
||||
b.append("&an=").append(UrlUtil.escape(myHostname)).append('+').append(UrlUtil.escape(next.getApplicationName()));
|
||||
b.append("&an=").append(UrlUtil.escapeUrlParam(myHostname)).append('+').append(UrlUtil.escapeUrlParam(next.getApplicationName()));
|
||||
b.append("&ec=").append(next.getResourceName());
|
||||
b.append("&ea=").append(next.getRestOperation());
|
||||
|
||||
b.append("&cid=").append(next.getClientId());
|
||||
b.append("&uip=").append(UrlUtil.escape(next.getSourceIp()));
|
||||
b.append("&ua=").append(UrlUtil.escape(next.getUserAgent()));
|
||||
b.append("&uip=").append(UrlUtil.escapeUrlParam(next.getSourceIp()));
|
||||
b.append("&ua=").append(UrlUtil.escapeUrlParam(next.getUserAgent()));
|
||||
b.append("\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -19,34 +19,38 @@ package ca.uhn.fhir.rest.server;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.util.BinaryUtil;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IRestfulResponse;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.method.ElementsParameter;
|
||||
import ca.uhn.fhir.rest.server.method.SummaryEnumParameter;
|
||||
import ca.uhn.fhir.util.BinaryUtil;
|
||||
import ca.uhn.fhir.util.DateUtils;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public class RestfulServerUtils {
|
||||
static final Pattern ACCEPT_HEADER_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9+.*/-]+)\\s*(;\\s*([a-zA-Z]+)\\s*=\\s*([a-zA-Z0-9.]+)\\s*)?(,?)");
|
||||
|
@ -127,74 +131,70 @@ public class RestfulServerUtils {
|
|||
}
|
||||
|
||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
|
||||
BundleTypeEnum theBundleType) {
|
||||
try {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theServerBase);
|
||||
b.append('?');
|
||||
b.append(Constants.PARAM_PAGINGACTION);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(theSearchId, "UTF-8"));
|
||||
BundleTypeEnum theBundleType) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theServerBase);
|
||||
b.append('?');
|
||||
b.append(Constants.PARAM_PAGINGACTION);
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escapeUrlParam(theSearchId));
|
||||
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PAGINGOFFSET);
|
||||
b.append('=');
|
||||
b.append(theOffset);
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_COUNT);
|
||||
b.append('=');
|
||||
b.append(theCount);
|
||||
String[] strings = theRequestParameters.get(Constants.PARAM_FORMAT);
|
||||
if (strings != null && strings.length > 0) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PAGINGOFFSET);
|
||||
b.append(Constants.PARAM_FORMAT);
|
||||
b.append('=');
|
||||
b.append(theOffset);
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_COUNT);
|
||||
b.append('=');
|
||||
b.append(theCount);
|
||||
String[] strings = theRequestParameters.get(Constants.PARAM_FORMAT);
|
||||
if (strings != null && strings.length > 0) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_FORMAT);
|
||||
b.append('=');
|
||||
String format = strings[0];
|
||||
format = replace(format, " ", "+");
|
||||
b.append(UrlUtil.escape(format));
|
||||
}
|
||||
if (thePrettyPrint) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PRETTY);
|
||||
b.append('=');
|
||||
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
|
||||
}
|
||||
|
||||
if (theIncludes != null) {
|
||||
for (Include nextInclude : theIncludes) {
|
||||
if (isNotBlank(nextInclude.getValue())) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_INCLUDE);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theBundleType != null) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_BUNDLETYPE);
|
||||
b.append('=');
|
||||
b.append(theBundleType.getCode());
|
||||
}
|
||||
|
||||
String paramName = Constants.PARAM_ELEMENTS;
|
||||
String[] params = theRequestParameters.get(paramName);
|
||||
if (params != null) {
|
||||
for (String nextValue : params) {
|
||||
if (isNotBlank(nextValue)) {
|
||||
b.append('&');
|
||||
b.append(paramName);
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.toString();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 not supported", e);// should not happen
|
||||
String format = strings[0];
|
||||
format = replace(format, " ", "+");
|
||||
b.append(UrlUtil.escapeUrlParam(format));
|
||||
}
|
||||
if (thePrettyPrint) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PRETTY);
|
||||
b.append('=');
|
||||
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
|
||||
}
|
||||
|
||||
if (theIncludes != null) {
|
||||
for (Include nextInclude : theIncludes) {
|
||||
if (isNotBlank(nextInclude.getValue())) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_INCLUDE);
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escapeUrlParam(nextInclude.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theBundleType != null) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_BUNDLETYPE);
|
||||
b.append('=');
|
||||
b.append(theBundleType.getCode());
|
||||
}
|
||||
|
||||
String paramName = Constants.PARAM_ELEMENTS;
|
||||
String[] params = theRequestParameters.get(paramName);
|
||||
if (params != null) {
|
||||
for (String nextValue : params) {
|
||||
if (isNotBlank(nextValue)) {
|
||||
b.append('&');
|
||||
b.append(paramName);
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -392,15 +392,15 @@ public class RestfulServerUtils {
|
|||
try {
|
||||
NarrativeModeEnum narrativeMode = NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
|
||||
switch (narrativeMode) {
|
||||
case NORMAL:
|
||||
retVal = Collections.singleton(SummaryEnum.FALSE);
|
||||
break;
|
||||
case ONLY:
|
||||
retVal = Collections.singleton(SummaryEnum.TEXT);
|
||||
break;
|
||||
case SUPPRESS:
|
||||
retVal = Collections.singleton(SummaryEnum.DATA);
|
||||
break;
|
||||
case NORMAL:
|
||||
retVal = Collections.singleton(SummaryEnum.FALSE);
|
||||
break;
|
||||
case ONLY:
|
||||
retVal = Collections.singleton(SummaryEnum.TEXT);
|
||||
break;
|
||||
case SUPPRESS:
|
||||
retVal = Collections.singleton(SummaryEnum.DATA);
|
||||
break;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
ourLog.debug("Invalid {} parameter: {}", Constants.PARAM_NARRATIVE, narrative[0]);
|
||||
|
@ -461,13 +461,13 @@ public class RestfulServerUtils {
|
|||
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails).getEncoding();
|
||||
IParser parser;
|
||||
switch (responseEncoding) {
|
||||
case JSON:
|
||||
parser = theContext.newJsonParser();
|
||||
break;
|
||||
case XML:
|
||||
default:
|
||||
parser = theContext.newXmlParser();
|
||||
break;
|
||||
case JSON:
|
||||
parser = theContext.newJsonParser();
|
||||
break;
|
||||
case XML:
|
||||
default:
|
||||
parser = theContext.newXmlParser();
|
||||
break;
|
||||
}
|
||||
|
||||
configureResponseParser(theRequestDetails, parser);
|
||||
|
@ -581,13 +581,13 @@ public class RestfulServerUtils {
|
|||
}
|
||||
|
||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int stausCode, boolean theAddContentLocationHeader,
|
||||
boolean respondGzip, RequestDetails theRequestDetails) throws IOException {
|
||||
boolean respondGzip, RequestDetails theRequestDetails) throws IOException {
|
||||
return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, null, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null);
|
||||
}
|
||||
|
||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int theStausCode, String theStatusMessage,
|
||||
boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated)
|
||||
throws IOException {
|
||||
boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated)
|
||||
throws IOException {
|
||||
IRestfulResponse response = theRequestDetails.getResponse();
|
||||
|
||||
// Determine response encoding
|
||||
|
@ -706,7 +706,7 @@ public class RestfulServerUtils {
|
|||
try {
|
||||
return Integer.parseInt(retVal[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e });
|
||||
ourLog.debug("Failed to parse {} value '{}': {}", new Object[]{theParamName, retVal[0], e});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -752,7 +752,7 @@ public class RestfulServerUtils {
|
|||
if (theContentType.equals(EncodingEnum.JSON_PLAIN_STRING) || theContentType.equals(EncodingEnum.XML_PLAIN_STRING)) {
|
||||
FhirVersionEnum ctxtEnum = theCtx.getVersion().getVersion();
|
||||
myNonLegacy = ctxtEnum.isNewerThan(FhirVersionEnum.DSTU3)
|
||||
|| (ctxtEnum.isEquivalentTo(FhirVersionEnum.DSTU3) && !"1.4.0".equals(theCtx.getVersion().getVersion().getFhirVersionString()));
|
||||
|| (ctxtEnum.isEquivalentTo(FhirVersionEnum.DSTU3) && !"1.4.0".equals(theCtx.getVersion().getVersion().getFhirVersionString()));
|
||||
} else {
|
||||
myNonLegacy = EncodingEnum.isNonLegacy(theContentType);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
||||
|
@ -99,7 +101,10 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
|||
@Override
|
||||
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
|
||||
BaseServerResponseException retVal;
|
||||
if (!(theException instanceof BaseServerResponseException)) {
|
||||
if (theException instanceof DataFormatException) {
|
||||
// Wrapping the DataFormatException as an InvalidRequestException so that it gets sent back to the client as a 400 response.
|
||||
retVal = new InvalidRequestException(theException);
|
||||
} else if (!(theException instanceof BaseServerResponseException)) {
|
||||
retVal = new InternalErrorException(theException);
|
||||
} else {
|
||||
retVal = (BaseServerResponseException) theException;
|
||||
|
|
|
@ -41,6 +41,8 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
/**
|
||||
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish to use
|
||||
* {@link InterceptorAdapter} in order to not need to implement every method.
|
||||
|
@ -329,9 +331,9 @@ public interface IServerInterceptor {
|
|||
public static class ActionRequestDetails {
|
||||
private final FhirContext myContext;
|
||||
private final IIdType myId;
|
||||
private final String myResourceType;
|
||||
private RequestDetails myRequestDetails;
|
||||
private IBaseResource myResource;
|
||||
private final String myResourceType;
|
||||
|
||||
public ActionRequestDetails(RequestDetails theRequestDetails) {
|
||||
myId = theRequestDetails.getId();
|
||||
|
@ -346,7 +348,11 @@ public interface IServerInterceptor {
|
|||
}
|
||||
|
||||
public ActionRequestDetails(RequestDetails theRequestDetails, FhirContext theContext, String theResourceType, IIdType theId) {
|
||||
myId = theId;
|
||||
if (theId != null && isBlank(theId.getValue())) {
|
||||
myId = null;
|
||||
} else {
|
||||
myId = theId;
|
||||
}
|
||||
myResourceType = theResourceType;
|
||||
myContext = theContext;
|
||||
myRequestDetails = theRequestDetails;
|
||||
|
@ -409,6 +415,13 @@ public interface IServerInterceptor {
|
|||
return myResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be called by client code
|
||||
*/
|
||||
public void setResource(IBaseResource theObject) {
|
||||
myResource = theObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource type this request pertains to, or <code>null</code> if this request is not type specific
|
||||
* (e.g. server-history)
|
||||
|
@ -450,13 +463,6 @@ public interface IServerInterceptor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be called by client code
|
||||
*/
|
||||
public void setResource(IBaseResource theObject) {
|
||||
myResource = theObject;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.io.IOException;
|
|||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Date;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
@ -33,6 +32,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.text.StrLookup;
|
||||
|
@ -277,13 +277,9 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
try {
|
||||
b.append(URLEncoder.encode(next.getKey(), "UTF-8"));
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ca.uhn.fhir.context.ConfigurationException("UTF-8 not supported", e);
|
||||
}
|
||||
b.append(UrlUtil.escapeUrlParam(next.getKey()));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
|
|
|
@ -92,9 +92,9 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||
} else {
|
||||
rawB.append('&');
|
||||
}
|
||||
rawB.append(UrlUtil.escape(next));
|
||||
rawB.append(UrlUtil.escapeUrlParam(next));
|
||||
rawB.append('=');
|
||||
rawB.append(UrlUtil.escape(nextValue));
|
||||
rawB.append(UrlUtil.escapeUrlParam(nextValue));
|
||||
}
|
||||
}
|
||||
if (rawB.length() == 0) {
|
||||
|
|
|
@ -20,18 +20,6 @@ package ca.uhn.fhir.rest.server.interceptor.auth;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
|
@ -40,6 +28,21 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
/**
|
||||
* This class is a base class for interceptors which can be used to
|
||||
|
@ -66,9 +69,8 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theDefaultPolicy
|
||||
* The default policy if no rules apply (must not be null)
|
||||
*
|
||||
* @param theDefaultPolicy The default policy if no rules apply (must not be null)
|
||||
*/
|
||||
public AuthorizationInterceptor(PolicyEnum theDefaultPolicy) {
|
||||
this();
|
||||
|
@ -76,7 +78,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
}
|
||||
|
||||
private void applyRulesAndFailIfDeny(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId,
|
||||
IBaseResource theOutputResource) {
|
||||
IBaseResource theOutputResource) {
|
||||
Verdict decision = applyRulesAndReturnDecision(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource);
|
||||
|
||||
if (decision.getDecision() == PolicyEnum.ALLOW) {
|
||||
|
@ -88,7 +90,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
|
||||
@Override
|
||||
public Verdict applyRulesAndReturnDecision(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId,
|
||||
IBaseResource theOutputResource) {
|
||||
IBaseResource theOutputResource) {
|
||||
List<IAuthRule> rules = buildRuleList(theRequestDetails);
|
||||
ourLog.trace("Applying {} rules to render an auth decision for operation {}", rules.size(), theOperation);
|
||||
|
||||
|
@ -117,9 +119,8 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
* out who the current user is and then using a {@link RuleBuilder} to create
|
||||
* an appropriate rule chain.
|
||||
* </p>
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* The individual request currently being applied
|
||||
*
|
||||
* @param theRequestDetails The individual request currently being applied
|
||||
*/
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new ArrayList<IAuthRule>();
|
||||
|
@ -127,63 +128,63 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
|
||||
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation, IBaseResource theRequestResource) {
|
||||
switch (theOperation) {
|
||||
case ADD_TAGS:
|
||||
case DELETE_TAGS:
|
||||
case GET_TAGS:
|
||||
// These are DSTU1 operations and not relevant
|
||||
return OperationExamineDirection.NONE;
|
||||
case ADD_TAGS:
|
||||
case DELETE_TAGS:
|
||||
case GET_TAGS:
|
||||
// These are DSTU1 operations and not relevant
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
return OperationExamineDirection.BOTH;
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
return OperationExamineDirection.BOTH;
|
||||
|
||||
case METADATA:
|
||||
// Security does not apply to these operations
|
||||
return OperationExamineDirection.IN;
|
||||
case METADATA:
|
||||
// Security does not apply to these operations
|
||||
return OperationExamineDirection.IN;
|
||||
|
||||
case DELETE:
|
||||
// Delete is a special case
|
||||
return OperationExamineDirection.NONE;
|
||||
case DELETE:
|
||||
// Delete is a special case
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case CREATE:
|
||||
case UPDATE:
|
||||
case PATCH:
|
||||
// if (theRequestResource != null) {
|
||||
// if (theRequestResource.getIdElement() != null) {
|
||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return OperationExamineDirection.IN;
|
||||
case CREATE:
|
||||
case UPDATE:
|
||||
case PATCH:
|
||||
// if (theRequestResource != null) {
|
||||
// if (theRequestResource.getIdElement() != null) {
|
||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return OperationExamineDirection.IN;
|
||||
|
||||
case META:
|
||||
case META_ADD:
|
||||
case META_DELETE:
|
||||
// meta operations do not apply yet
|
||||
return OperationExamineDirection.NONE;
|
||||
case META:
|
||||
case META_ADD:
|
||||
case META_DELETE:
|
||||
// meta operations do not apply yet
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case GET_PAGE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case READ:
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case VREAD:
|
||||
return OperationExamineDirection.OUT;
|
||||
case GET_PAGE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case READ:
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case VREAD:
|
||||
return OperationExamineDirection.OUT;
|
||||
|
||||
case TRANSACTION:
|
||||
return OperationExamineDirection.BOTH;
|
||||
case TRANSACTION:
|
||||
return OperationExamineDirection.BOTH;
|
||||
|
||||
case VALIDATE:
|
||||
// Nothing yet
|
||||
return OperationExamineDirection.NONE;
|
||||
case VALIDATE:
|
||||
// Nothing yet
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
default:
|
||||
// Should not happen
|
||||
throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
|
||||
default:
|
||||
// Should not happen
|
||||
throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -195,6 +196,16 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
return myDefaultPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default policy if no rules have been found to apply. Default value for this setting is {@link PolicyEnum#DENY}
|
||||
*
|
||||
* @param theDefaultPolicy The policy (must not be <code>null</code>)
|
||||
*/
|
||||
public void setDefaultPolicy(PolicyEnum theDefaultPolicy) {
|
||||
Validate.notNull(theDefaultPolicy, "theDefaultPolicy must not be null");
|
||||
myDefaultPolicy = theDefaultPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an access control verdict of {@link PolicyEnum#DENY}.
|
||||
* <p>
|
||||
|
@ -221,17 +232,17 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
IIdType inputResourceId = null;
|
||||
|
||||
switch (determineOperationDirection(theOperation, theProcessedRequest.getResource())) {
|
||||
case IN:
|
||||
case BOTH:
|
||||
inputResource = theProcessedRequest.getResource();
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case OUT:
|
||||
// inputResource = null;
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case NONE:
|
||||
return;
|
||||
case IN:
|
||||
case BOTH:
|
||||
inputResource = theProcessedRequest.getResource();
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case OUT:
|
||||
// inputResource = null;
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
RequestDetails requestDetails = theProcessedRequest.getRequestDetails();
|
||||
|
@ -241,43 +252,39 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
|
||||
switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) {
|
||||
case IN:
|
||||
case NONE:
|
||||
return true;
|
||||
case BOTH:
|
||||
case OUT:
|
||||
break;
|
||||
case IN:
|
||||
case NONE:
|
||||
return true;
|
||||
case BOTH:
|
||||
case OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
FhirContext fhirContext = theRequestDetails.getServer().getFhirContext();
|
||||
List<IBaseResource> resources = Collections.emptyList();
|
||||
|
||||
switch (theRequestDetails.getRestOperationType()) {
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case TRANSACTION:
|
||||
case GET_PAGE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
case EXTENDED_OPERATION_INSTANCE: {
|
||||
if (theResponseObject != null) {
|
||||
if (theResponseObject instanceof IBaseBundle) {
|
||||
resources = toListOfResourcesAndExcludeContainer(theResponseObject, fhirContext);
|
||||
} else if (theResponseObject instanceof IBaseParameters) {
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case TRANSACTION:
|
||||
case GET_PAGE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
case EXTENDED_OPERATION_INSTANCE: {
|
||||
if (theResponseObject != null) {
|
||||
resources = toListOfResourcesAndExcludeContainer(theResponseObject, fhirContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (theResponseObject != null) {
|
||||
resources = Collections.singletonList(theResponseObject);
|
||||
default: {
|
||||
if (theResponseObject != null) {
|
||||
resources = Collections.singletonList(theResponseObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (IBaseResource nextResponse : resources) {
|
||||
|
@ -296,7 +303,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
@CoverageIgnore
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws AuthenticationException {
|
||||
throws AuthenticationException {
|
||||
throw failForDstu1();
|
||||
}
|
||||
|
||||
|
@ -318,33 +325,38 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
|||
handleUserOperation(theRequest, theNewResource, RestOperationTypeEnum.UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default policy if no rules have been found to apply. Default value for this setting is {@link PolicyEnum#DENY}
|
||||
*
|
||||
* @param theDefaultPolicy
|
||||
* The policy (must not be <code>null</code>)
|
||||
*/
|
||||
public void setDefaultPolicy(PolicyEnum theDefaultPolicy) {
|
||||
Validate.notNull(theDefaultPolicy, "theDefaultPolicy must not be null");
|
||||
myDefaultPolicy = theDefaultPolicy;
|
||||
}
|
||||
|
||||
private List<IBaseResource> toListOfResourcesAndExcludeContainer(IBaseResource theResponseObject, FhirContext fhirContext) {
|
||||
List<IBaseResource> resources;
|
||||
resources = fhirContext.newTerser().getAllPopulatedChildElementsOfType(theResponseObject, IBaseResource.class);
|
||||
|
||||
// Exclude the container
|
||||
if (resources.size() > 0 && resources.get(0) == theResponseObject) {
|
||||
resources = resources.subList(1, resources.size());
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
private static UnsupportedOperationException failForDstu1() {
|
||||
return new UnsupportedOperationException("Use of this interceptor on DSTU1 servers is not supportd");
|
||||
}
|
||||
|
||||
static List<IBaseResource> toListOfResourcesAndExcludeContainer(IBaseResource theResponseObject, FhirContext fhirContext) {
|
||||
if (theResponseObject == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<IBaseResource> retVal;
|
||||
|
||||
boolean isContainer = false;
|
||||
if (theResponseObject instanceof IBaseBundle) {
|
||||
isContainer = true;
|
||||
} else if (theResponseObject instanceof IBaseParameters) {
|
||||
isContainer = true;
|
||||
}
|
||||
|
||||
if (!isContainer) {
|
||||
return Collections.singletonList(theResponseObject);
|
||||
}
|
||||
|
||||
retVal = fhirContext.newTerser().getAllPopulatedChildElementsOfType(theResponseObject, IBaseResource.class);
|
||||
|
||||
// Exclude the container
|
||||
if (retVal.size() > 0 && retVal.get(0) == theResponseObject) {
|
||||
retVal = retVal.subList(1, retVal.size());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private enum OperationExamineDirection {
|
||||
BOTH,
|
||||
IN,
|
||||
|
|
|
@ -165,13 +165,15 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
|
|||
}
|
||||
return verdict;
|
||||
} else if (theOutputResource != null) {
|
||||
List<BundleEntryParts> inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource);
|
||||
|
||||
List<IBaseResource> outputResources = AuthorizationInterceptor.toListOfResourcesAndExcludeContainer(theOutputResource, theRequestDetails.getFhirContext());
|
||||
|
||||
Verdict verdict = null;
|
||||
for (BundleEntryParts nextPart : inputResources) {
|
||||
if (nextPart.getResource() == null) {
|
||||
for (IBaseResource nextResource : outputResources) {
|
||||
if (nextResource == null) {
|
||||
continue;
|
||||
}
|
||||
Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextPart.getResource());
|
||||
Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextResource);
|
||||
if (newVerdict == null) {
|
||||
continue;
|
||||
} else if (verdict == null) {
|
||||
|
@ -225,7 +227,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
if (appliesToResourceId != null) {
|
||||
if (appliesToResourceId != null && appliesToResourceId.hasResourceType()) {
|
||||
Class<? extends IBaseResource> type = theRequestDetails.getServer().getFhirContext().getResourceDefinition(appliesToResourceId.getResourceType()).getImplementingClass();
|
||||
if (myAppliesToTypes.contains(type) == false) {
|
||||
return null;
|
||||
|
|
|
@ -186,9 +186,9 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
b.append(UrlUtil.escape(nextParamName));
|
||||
b.append(UrlUtil.escapeUrlParam(nextParamName));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextParamValue));
|
||||
b.append(UrlUtil.escapeUrlParam(nextParamValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,118 +1,119 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-autoconfigure</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- Compile dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional dependencies -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-client-okhttp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2.1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-autoconfigure</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- Compile dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional dependencies -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-client-okhttp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2.1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,287 +1,308 @@
|
|||
package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
||||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
|
||||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaProvider;
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
|
||||
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.apache.http.client.HttpClient;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ResourceCondition;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR.
|
||||
*
|
||||
* @author Mathieu Ouellet
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
public class FhirAutoConfiguration {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
public FhirAutoConfiguration(FhirProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FhirContext fhirContext() {
|
||||
FhirContext fhirContext = new FhirContext(properties.getVersion());
|
||||
return fhirContext;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(AbstractJaxRsProvider.class)
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
@ConfigurationProperties("hapi.fhir.rest")
|
||||
@SuppressWarnings("serial")
|
||||
static class FhirRestfulServerConfiguration extends RestfulServer {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
private final FhirContext fhirContext;
|
||||
|
||||
private final List<IResourceProvider> resourceProviders;
|
||||
|
||||
private final IPagingProvider pagingProvider;
|
||||
|
||||
private final List<IServerInterceptor> interceptors;
|
||||
|
||||
private final List<FhirRestfulServerCustomizer> customizers;
|
||||
|
||||
public FhirRestfulServerConfiguration(
|
||||
FhirProperties properties,
|
||||
FhirContext fhirContext,
|
||||
ObjectProvider<List<IResourceProvider>> resourceProviders,
|
||||
ObjectProvider<IPagingProvider> pagingProvider,
|
||||
ObjectProvider<List<IServerInterceptor>> interceptors,
|
||||
ObjectProvider<List<FhirRestfulServerCustomizer>> customizers) {
|
||||
this.properties = properties;
|
||||
this.fhirContext = fhirContext;
|
||||
this.resourceProviders = resourceProviders.getIfAvailable();
|
||||
this.pagingProvider = pagingProvider.getIfAvailable();
|
||||
this.interceptors = interceptors.getIfAvailable();
|
||||
this.customizers = customizers.getIfAvailable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean fhirServerRegistrationBean() {
|
||||
ServletRegistrationBean registration = new ServletRegistrationBean(this, this.properties.getServer().getPath());
|
||||
registration.setLoadOnStartup(1);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
|
||||
setFhirContext(this.fhirContext);
|
||||
setResourceProviders(this.resourceProviders);
|
||||
setPagingProvider(this.pagingProvider);
|
||||
setInterceptors(this.interceptors);
|
||||
|
||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(this.properties.getServer().getPath()));
|
||||
|
||||
customize();
|
||||
}
|
||||
|
||||
private void customize() {
|
||||
if (this.customizers != null) {
|
||||
AnnotationAwareOrderComparator.sort(this.customizers);
|
||||
for (FhirRestfulServerCustomizer customizer : this.customizers) {
|
||||
customizer.customize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(BaseJpaProvider.class)
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
static class FhirJpaServerConfiguration {
|
||||
|
||||
@Configuration
|
||||
@EntityScan("ca.uhn.fhir.jpa.entity")
|
||||
@EnableJpaRepositories(basePackages = "ca.uhn.fhir.jpa.dao.data")
|
||||
static class FhirJpaDaoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.jpa")
|
||||
public DaoConfig fhirDaoConfig() {
|
||||
DaoConfig fhirDaoConfig = new DaoConfig();
|
||||
return fhirDaoConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnBean({ DaoConfig.class, RestfulServer.class })
|
||||
@SuppressWarnings("rawtypes")
|
||||
static class RestfulServerCustomizer implements FhirRestfulServerCustomizer {
|
||||
|
||||
private final BaseJpaSystemProvider systemProviders;
|
||||
|
||||
public RestfulServerCustomizer(ObjectProvider<BaseJpaSystemProvider> systemProviders) {
|
||||
this.systemProviders = systemProviders.getIfAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(RestfulServer server) {
|
||||
server.setPlainProviders(systemProviders);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU3")
|
||||
static class Dstu3 extends BaseJavaConfigDstu3 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU2")
|
||||
static class Dstu2 extends BaseJavaConfigDstu2 {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Conditional(FhirValidationConfiguration.SchemaAvailableCondition.class)
|
||||
@ConditionalOnProperty(name = "hapi.fhir.validation.enabled", matchIfMissing = true)
|
||||
static class FhirValidationConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RequestValidatingInterceptor requestValidatingInterceptor() {
|
||||
return new RequestValidatingInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(name = "hapi.fhir.validation.request-only", havingValue = "false")
|
||||
public ResponseValidatingInterceptor responseValidatingInterceptor() {
|
||||
return new ResponseValidatingInterceptor();
|
||||
}
|
||||
|
||||
static class SchemaAvailableCondition extends ResourceCondition {
|
||||
|
||||
SchemaAvailableCondition() {
|
||||
super("ValidationSchema",
|
||||
"hapi.fhir.validation",
|
||||
"schema-location",
|
||||
"classpath:/org/hl7/fhir/instance/model/schema",
|
||||
"classpath:/org/hl7/fhir/dstu2016may/model/schema",
|
||||
"classpath:/org/hl7/fhir/dstu3/model/schema");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty("hapi.fhir.server.url")
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
static class FhirRestfulClientConfiguration {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
private final List<IClientInterceptor> clientInterceptors;
|
||||
|
||||
public FhirRestfulClientConfiguration(FhirProperties properties, ObjectProvider<List<IClientInterceptor>> clientInterceptors) {
|
||||
this.properties = properties;
|
||||
this.clientInterceptors = clientInterceptors.getIfAvailable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(IRestfulClientFactory.class)
|
||||
public IGenericClient fhirClient(final IRestfulClientFactory clientFactory) {
|
||||
IGenericClient fhirClient = clientFactory.newGenericClient(this.properties.getServer().getUrl());
|
||||
if (!CollectionUtils.isEmpty(this.clientInterceptors)) {
|
||||
for (IClientInterceptor interceptor : this.clientInterceptors) {
|
||||
fhirClient.registerInterceptor(interceptor);
|
||||
}
|
||||
}
|
||||
return fhirClient;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HttpClient.class)
|
||||
@ConditionalOnMissingClass("okhttp3.OkHttpClient")
|
||||
static class Apache {
|
||||
|
||||
private final FhirContext context;
|
||||
|
||||
public Apache(FhirContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.rest.client.apache")
|
||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||
ApacheRestfulClientFactory restfulClientFactory = new ApacheRestfulClientFactory(this.context);
|
||||
return restfulClientFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
static class OkHttp {
|
||||
|
||||
private final FhirContext context;
|
||||
|
||||
public OkHttp(FhirContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.rest.client.okhttp")
|
||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||
OkHttpRestfulClientFactory restfulClientFactory = new OkHttpRestfulClientFactory(this.context);
|
||||
return restfulClientFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-autoconfigure
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
||||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
|
||||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaProvider;
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
|
||||
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.apache.http.client.HttpClient;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ResourceCondition;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR.
|
||||
*
|
||||
* @author Mathieu Ouellet
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
public class FhirAutoConfiguration {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
public FhirAutoConfiguration(FhirProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FhirContext fhirContext() {
|
||||
FhirContext fhirContext = new FhirContext(properties.getVersion());
|
||||
return fhirContext;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(AbstractJaxRsProvider.class)
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
@ConfigurationProperties("hapi.fhir.rest")
|
||||
@SuppressWarnings("serial")
|
||||
static class FhirRestfulServerConfiguration extends RestfulServer {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
private final FhirContext fhirContext;
|
||||
|
||||
private final List<IResourceProvider> resourceProviders;
|
||||
|
||||
private final IPagingProvider pagingProvider;
|
||||
|
||||
private final List<IServerInterceptor> interceptors;
|
||||
|
||||
private final List<FhirRestfulServerCustomizer> customizers;
|
||||
|
||||
public FhirRestfulServerConfiguration(
|
||||
FhirProperties properties,
|
||||
FhirContext fhirContext,
|
||||
ObjectProvider<List<IResourceProvider>> resourceProviders,
|
||||
ObjectProvider<IPagingProvider> pagingProvider,
|
||||
ObjectProvider<List<IServerInterceptor>> interceptors,
|
||||
ObjectProvider<List<FhirRestfulServerCustomizer>> customizers) {
|
||||
this.properties = properties;
|
||||
this.fhirContext = fhirContext;
|
||||
this.resourceProviders = resourceProviders.getIfAvailable();
|
||||
this.pagingProvider = pagingProvider.getIfAvailable();
|
||||
this.interceptors = interceptors.getIfAvailable();
|
||||
this.customizers = customizers.getIfAvailable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean fhirServerRegistrationBean() {
|
||||
ServletRegistrationBean registration = new ServletRegistrationBean(this, this.properties.getServer().getPath());
|
||||
registration.setLoadOnStartup(1);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
|
||||
setFhirContext(this.fhirContext);
|
||||
setResourceProviders(this.resourceProviders);
|
||||
setPagingProvider(this.pagingProvider);
|
||||
setInterceptors(this.interceptors);
|
||||
|
||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(this.properties.getServer().getPath()));
|
||||
|
||||
customize();
|
||||
}
|
||||
|
||||
private void customize() {
|
||||
if (this.customizers != null) {
|
||||
AnnotationAwareOrderComparator.sort(this.customizers);
|
||||
for (FhirRestfulServerCustomizer customizer : this.customizers) {
|
||||
customizer.customize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(BaseJpaProvider.class)
|
||||
@ConditionalOnBean(DataSource.class)
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
static class FhirJpaServerConfiguration {
|
||||
|
||||
@Configuration
|
||||
@EntityScan("ca.uhn.fhir.jpa.entity")
|
||||
@EnableJpaRepositories(basePackages = "ca.uhn.fhir.jpa.dao.data")
|
||||
static class FhirJpaDaoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.jpa")
|
||||
public DaoConfig fhirDaoConfig() {
|
||||
DaoConfig fhirDaoConfig = new DaoConfig();
|
||||
return fhirDaoConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnBean({ DaoConfig.class, RestfulServer.class })
|
||||
@SuppressWarnings("rawtypes")
|
||||
static class RestfulServerCustomizer implements FhirRestfulServerCustomizer {
|
||||
|
||||
private final BaseJpaSystemProvider systemProviders;
|
||||
|
||||
public RestfulServerCustomizer(ObjectProvider<BaseJpaSystemProvider> systemProviders) {
|
||||
this.systemProviders = systemProviders.getIfAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(RestfulServer server) {
|
||||
server.setPlainProviders(systemProviders);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU3")
|
||||
static class Dstu3 extends BaseJavaConfigDstu3 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU2")
|
||||
static class Dstu2 extends BaseJavaConfigDstu2 {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Conditional(FhirValidationConfiguration.SchemaAvailableCondition.class)
|
||||
@ConditionalOnProperty(name = "hapi.fhir.validation.enabled", matchIfMissing = true)
|
||||
static class FhirValidationConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RequestValidatingInterceptor requestValidatingInterceptor() {
|
||||
return new RequestValidatingInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(name = "hapi.fhir.validation.request-only", havingValue = "false")
|
||||
public ResponseValidatingInterceptor responseValidatingInterceptor() {
|
||||
return new ResponseValidatingInterceptor();
|
||||
}
|
||||
|
||||
static class SchemaAvailableCondition extends ResourceCondition {
|
||||
|
||||
SchemaAvailableCondition() {
|
||||
super("ValidationSchema",
|
||||
"hapi.fhir.validation",
|
||||
"schema-location",
|
||||
"classpath:/org/hl7/fhir/instance/model/schema",
|
||||
"classpath:/org/hl7/fhir/dstu2016may/model/schema",
|
||||
"classpath:/org/hl7/fhir/dstu3/model/schema");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty("hapi.fhir.server.url")
|
||||
@EnableConfigurationProperties(FhirProperties.class)
|
||||
static class FhirRestfulClientConfiguration {
|
||||
|
||||
private final FhirProperties properties;
|
||||
|
||||
private final List<IClientInterceptor> clientInterceptors;
|
||||
|
||||
public FhirRestfulClientConfiguration(FhirProperties properties, ObjectProvider<List<IClientInterceptor>> clientInterceptors) {
|
||||
this.properties = properties;
|
||||
this.clientInterceptors = clientInterceptors.getIfAvailable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(IRestfulClientFactory.class)
|
||||
public IGenericClient fhirClient(final IRestfulClientFactory clientFactory) {
|
||||
IGenericClient fhirClient = clientFactory.newGenericClient(this.properties.getServer().getUrl());
|
||||
if (!CollectionUtils.isEmpty(this.clientInterceptors)) {
|
||||
for (IClientInterceptor interceptor : this.clientInterceptors) {
|
||||
fhirClient.registerInterceptor(interceptor);
|
||||
}
|
||||
}
|
||||
return fhirClient;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HttpClient.class)
|
||||
@ConditionalOnMissingClass("okhttp3.OkHttpClient")
|
||||
static class Apache {
|
||||
|
||||
private final FhirContext context;
|
||||
|
||||
public Apache(FhirContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.rest.client.apache")
|
||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||
ApacheRestfulClientFactory restfulClientFactory = new ApacheRestfulClientFactory(this.context);
|
||||
return restfulClientFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(OkHttpClient.class)
|
||||
static class OkHttp {
|
||||
|
||||
private final FhirContext context;
|
||||
|
||||
public OkHttp(FhirContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties("hapi.fhir.rest.client.okhttp")
|
||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||
OkHttpRestfulClientFactory restfulClientFactory = new OkHttpRestfulClientFactory(this.context);
|
||||
return restfulClientFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,85 +1,106 @@
|
|||
package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "hapi.fhir")
|
||||
public class FhirProperties {
|
||||
|
||||
private FhirVersionEnum version = FhirVersionEnum.DSTU2;
|
||||
|
||||
private Server server = new Server();
|
||||
|
||||
private Validation validation = new Validation();
|
||||
|
||||
public FhirVersionEnum getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(FhirVersionEnum version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Server getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void setServer(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public Validation getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
public void setValidation(Validation validation) {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
|
||||
private String url;
|
||||
|
||||
private String path = "/fhir/*";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Validation {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private boolean requestOnly = true;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isRequestOnly() {
|
||||
return requestOnly;
|
||||
}
|
||||
|
||||
public void setRequestOnly(boolean requestOnly) {
|
||||
this.requestOnly = requestOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-autoconfigure
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.FhirVersionEnum;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "hapi.fhir")
|
||||
public class FhirProperties {
|
||||
|
||||
private FhirVersionEnum version = FhirVersionEnum.DSTU2;
|
||||
|
||||
private Server server = new Server();
|
||||
|
||||
private Validation validation = new Validation();
|
||||
|
||||
public FhirVersionEnum getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(FhirVersionEnum version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Server getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void setServer(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public Validation getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
public void setValidation(Validation validation) {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
|
||||
private String url;
|
||||
|
||||
private String path = "/fhir/*";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Validation {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private boolean requestOnly = true;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isRequestOnly() {
|
||||
return requestOnly;
|
||||
}
|
||||
|
||||
public void setRequestOnly(boolean requestOnly) {
|
||||
this.requestOnly = requestOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-autoconfigure
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.rest.server.RestfulServer;
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package sample.fhir.client;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-sample-client-apache
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package sample.fhir.client;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-sample-client-okhttp
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||
|
|
|
@ -1,67 +1,85 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jersey</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-starter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- Optional -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jersey</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-starter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- Optional -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package sample.fhir.server.jersey;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-sample-server-jersey
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.rest.server.interceptor.LoggingInterceptor;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package sample.fhir.server.jersey.provider;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* hapi-fhir-spring-boot-sample-server-jersey
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* 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.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-server-jpa</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-starter</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-autoconfigure</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>3.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-starter</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-autoconfigure</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue