From 4042a3a3532e83bebf7e61737e3fdf617b8e4734 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 22 Nov 2017 18:17:35 -0500 Subject: [PATCH] Prevent accidental deletion of deeply nested resources in JPA server --- .../java/ca/uhn/fhir/parser/BaseParser.java | 2 +- .../java/ca/uhn/fhir/parser/JsonParser.java | 2 +- .../provider/r4/ResourceProviderR4Test.java | 50 +++++++++++++++++++ .../ca/uhn/fhir/parser/JsonParserR4Test.java | 46 +++++++++++++++++ .../ca/uhn/fhir/parser/XmlParserR4Test.java | 30 +++++++++++ src/changes/changes.xml | 4 ++ 6 files changed, 132 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java index 9dfcdb7c7da..da8f83f9957 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java @@ -1115,7 +1115,7 @@ public abstract class BaseParser implements IParser { } } - return true; + return false; } public BaseRuntimeChildDefinition getDef() { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index f759cefa6cd..de7286a98dd 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -1434,7 +1434,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); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index 5c6981cccb5..0f0a5920ff2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -4301,6 +4301,56 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } } + @Test + public void testParseAndEncodeExtensionWithValueWithExtension() throws IOException { + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + 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"))); diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java index 93fe167ff77..64f379f9160 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java @@ -2,6 +2,7 @@ package ca.uhn.fhir.parser; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.util.TestUtil; +import com.google.common.collect.Sets; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Patient; import org.junit.AfterClass; @@ -110,6 +111,51 @@ public class JsonParserR4Test { return b; } + + @Test + public void testParseAndEncodeExtensionWithValueWithExtension() { + String input = "{\n" + + " \"resourceType\": \"Patient\",\n" + + " \"extension\": [\n" + + " {\n" + + " \"url\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/BirthWeight\",\n" + + " \"_valueDecimal\": {\n" + + " \"extension\": [\n" + + " {\n" + + " \"url\": \"http://www.hl7.org/fhir/extension-data-absent-reason.html\",\n" + + " \"valueCoding\": {\n" + + " \"system\": \"http://hl7.org/fhir/ValueSet/birthweight\",\n" + + " \"code\": \"Underweight\",\n" + + " \"userSelected\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/EuroPrevallStudySubjects\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " ],\n" + + " \"gender\": \"female\"\n" + + "}"; + + IParser jsonParser = ourCtx.newJsonParser(); + IParser xmlParser = ourCtx.newXmlParser(); + jsonParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + xmlParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + + Patient parsed = jsonParser.parseResource(Patient.class, input); + + ourLog.info(jsonParser.setPrettyPrint(true).encodeResourceToString(parsed)); + assertThat(xmlParser.encodeResourceToString(parsed), containsString("Underweight")); + assertThat(jsonParser.encodeResourceToString(parsed), containsString("Underweight")); + + } + + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java index 2d16f0e9c56..5be2e8e7977 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java @@ -110,6 +110,36 @@ public class XmlParserR4Test { return b; } + @Test + public void testParseAndEncodeExtensionWithValueWithExtension() { + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, input); + + ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed)); + assertThat(ourCtx.newXmlParser().encodeResourceToString(parsed), containsString("Underweight")); + assertThat(ourCtx.newJsonParser().encodeResourceToString(parsed), containsString("Underweight")); + + } + + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 21cee568c1f..51dc07483f1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -212,6 +212,10 @@ client requests. Thanks to Clayton Bodendein for the pull request! + + An issue was fixed in JPA server where extensions on primitives which + are nestedt several layers deep are lost when resources are retrieved +