Merging cleanup from local branch with commit from #153

This commit is contained in:
James Agnew 2015-04-20 15:28:20 -04:00
parent dfbfed2d35
commit 4f1d2a3c75
8 changed files with 273 additions and 180 deletions

View File

@ -147,7 +147,7 @@
<include>javax.xml.stream:stax-api</include> <include>javax.xml.stream:stax-api</include>
<include>javax.servlet:javax.servlet-api</include> <include>javax.servlet:javax.servlet-api</include>
<include>org.codehaus.woodstox:stax2-api</include> <include>org.codehaus.woodstox:stax2-api</include>
<include>org.slf4j:slf4j*</include> <!-- <include>org.slf4j:slf4j*</include> -->
<include>org.apache.commons:*</include> <include>org.apache.commons:*</include>
<include>org.apache.httpcomponents:*</include> <include>org.apache.httpcomponents:*</include>
<include>org.glassfish:javax.json</include> <include>org.glassfish:javax.json</include>

View File

@ -49,14 +49,13 @@ import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonGeneratorFactory; import javax.json.stream.JsonGeneratorFactory;
import javax.json.stream.JsonParsingException; import javax.json.stream.JsonParsingException;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.primitive.*;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.IBase; import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource; import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType; import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype; import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype; import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
@ -89,19 +88,25 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt; import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt; import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt; import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseBinary; import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DecimalDt; import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt; import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.model.primitive.XhtmlDt; import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
/**
* This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use {@link FhirContext#newJsonParser()} to get an instance.
*/
public class JsonParser extends BaseParser implements IParser { public class JsonParser extends BaseParser implements IParser {
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1; private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1;
@ -298,9 +303,9 @@ public class JsonParser extends BaseParser implements IParser {
// IResource nextResource = nextEntry.getResource(); // IResource nextResource = nextEntry.getResource();
} }
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) { if (nextEntry.getTransactionMethod().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
theEventWriter.writeStartObject("transaction"); theEventWriter.writeStartObject("transaction");
writeOptionalTagWithTextNode(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue()); writeOptionalTagWithTextNode(theEventWriter, "method", nextEntry.getTransactionMethod().getValue());
writeOptionalTagWithTextNode(theEventWriter, "url", nextEntry.getLinkSearch().getValue()); writeOptionalTagWithTextNode(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
theEventWriter.writeEnd(); theEventWriter.writeEnd();
} }
@ -343,7 +348,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue,
BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theIsSubElementWithinResource) throws IOException { BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theContainedResource) throws IOException {
switch (theChildDef.getChildType()) { switch (theChildDef.getChildType()) {
case PRIMITIVE_DATATYPE: { case PRIMITIVE_DATATYPE: {
@ -391,7 +396,7 @@ public class JsonParser extends BaseParser implements IParser {
if (theNextValue instanceof ExtensionDt) { if (theNextValue instanceof ExtensionDt) {
theWriter.write("url", ((ExtensionDt) theNextValue).getUrlAsString()); theWriter.write("url", ((ExtensionDt) theNextValue).getUrlAsString());
} }
encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theWriter, childCompositeDef, theIsSubElementWithinResource); encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theWriter, childCompositeDef, theContainedResource);
theWriter.writeEnd(); theWriter.writeEnd();
break; break;
} }
@ -452,7 +457,7 @@ public class JsonParser extends BaseParser implements IParser {
case RESOURCE: case RESOURCE:
IBaseResource resource = (IBaseResource) theNextValue; IBaseResource resource = (IBaseResource) theNextValue;
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource); RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, true); encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, false);
break; break;
case UNDECL_EXT: case UNDECL_EXT:
default: default:
@ -462,7 +467,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException { List<? extends BaseRuntimeChildDefinition> theChildren, boolean theContainedResource) throws IOException {
for (BaseRuntimeChildDefinition nextChild : theChildren) { for (BaseRuntimeChildDefinition nextChild : theChildren) {
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) { if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
continue; continue;
@ -478,7 +483,7 @@ public class JsonParser extends BaseParser implements IParser {
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild; RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
String childName = nextChild.getChildNameByDatatype(child.getDatatype()); String childName = nextChild.getChildNameByDatatype(child.getDatatype());
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName); BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource);
continue; continue;
} }
} }
@ -499,7 +504,7 @@ public class JsonParser extends BaseParser implements IParser {
for (IBase nextValue : values) { for (IBase nextValue : values) {
if (nextValue == null || nextValue.isEmpty()) { if (nextValue == null || nextValue.isEmpty()) {
if (nextValue instanceof BaseContainedDt) { if (nextValue instanceof BaseContainedDt) {
if (theIsSubElementWithinResource || getContainedResources().isEmpty()) { if (theContainedResource || getContainedResources().isEmpty()) {
continue; continue;
} }
} else { } else {
@ -515,7 +520,7 @@ public class JsonParser extends BaseParser implements IParser {
} }
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE; boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && theIsSubElementWithinResource) { if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && theContainedResource) {
continue; continue;
} }
@ -537,15 +542,15 @@ public class JsonParser extends BaseParser implements IParser {
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) { if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
theEventWriter.writeStartArray(childName); theEventWriter.writeStartArray(childName);
inArray = true; inArray = true;
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource);
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIsSubElementWithinResource) { } else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
// suppress narratives from contained resources // suppress narratives from contained resources
} else { } else {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theContainedResource);
} }
currentChildName = childName; currentChildName = childName;
} else { } else {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource);
} }
if (primitive) { if (primitive) {
@ -620,19 +625,19 @@ public class JsonParser extends BaseParser implements IParser {
} }
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException { BaseRuntimeElementCompositeDefinition<?> resDef, boolean theContainedResource) throws IOException, DataFormatException {
extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null); extractAndWriteExtensionsAsDirectChild(theNextValue, theEventWriter, resDef, theResDef, theResource, null);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource); encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getExtensions(), theContainedResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theIsSubElementWithinResource); encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, resDef.getChildren(), theContainedResource);
} }
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theContainedResource)
boolean theIsSubElementWithinResource) throws IOException { throws IOException {
String resourceId = null; String resourceId = null;
if (theResource instanceof IResource) { if (theResource instanceof IResource) {
IResource res = (IResource) theResource; IResource res = (IResource) theResource;
if (StringUtils.isNotBlank(res.getId().getIdPart())) { if (StringUtils.isNotBlank(res.getId().getIdPart())) {
if (theIsSubElementWithinResource) { if (theContainedResource) {
resourceId = res.getId().getIdPart(); resourceId = res.getId().getIdPart();
} else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { } else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
resourceId = res.getId().getIdPart(); resourceId = res.getId().getIdPart();
@ -640,17 +645,17 @@ public class JsonParser extends BaseParser implements IParser {
} }
} else if (theResource instanceof IAnyResource) { } else if (theResource instanceof IAnyResource) {
IAnyResource res = (IAnyResource) theResource; IAnyResource res = (IAnyResource) theResource;
if (theIsSubElementWithinResource && StringUtils.isNotBlank(res.getId())) { if (theContainedResource && StringUtils.isNotBlank(res.getId())) {
resourceId = res.getId(); resourceId = res.getId();
} }
} }
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theIsSubElementWithinResource, resourceId); encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);
} }
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
boolean theIsSubElementWithinResource, String theResourceId) throws IOException { boolean theContainedResource, String theResourceId) throws IOException {
if (!theIsSubElementWithinResource) { if (!theContainedResource) {
super.containResourcesForEncoding(theResource); super.containResourcesForEncoding(theResource);
} }
@ -670,54 +675,65 @@ public class JsonParser extends BaseParser implements IParser {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) { if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) {
IResource resource = (IResource) theResource; IResource resource = (IResource) theResource;
// Object securityLabelRawObj = // Object securityLabelRawObj =
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
if (!ElementUtil.isEmpty(resource.getId().getVersionIdPart(), ResourceMetadataKeyEnum.UPDATED.get(resource)) List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|| (securityLabels != null && !securityLabels.isEmpty())) { List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(resource);
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
IdDt resourceId = resource.getId();
String versionIdPart = resourceId.getVersionIdPart();
if (isBlank(versionIdPart)) {
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
}
if (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, profiles) == false) {
theEventWriter.writeStartObject("meta"); theEventWriter.writeStartObject("meta");
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart()); writeOptionalTagWithTextNode(theEventWriter, "versionId", versionIdPart);
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource)); writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", updated);
if (securityLabels != null) { if (profiles != null && profiles.isEmpty() == false) {
if (!securityLabels.isEmpty()) { theEventWriter.writeStartArray("profile");
for (IdDt profile : profiles) {
if (profile != null && isNotBlank(profile.getValue())) {
theEventWriter.write(profile.getValue());
}
}
theEventWriter.writeEnd();
}
if (securityLabels.isEmpty() == false) {
theEventWriter.writeStartArray("security"); theEventWriter.writeStartArray("security");
for (BaseCodingDt securityLabel : securityLabels) { for (BaseCodingDt securityLabel : securityLabels) {
theEventWriter.writeStartObject(); theEventWriter.writeStartObject();
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
UriDt system = securityLabel.getSystemElement(); encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
if (system != null && !system.isEmpty()) theEventWriter.writeEnd();
writeOptionalTagWithTextNode(theEventWriter, "system", system.getValueAsString());
CodeDt code = securityLabel.getCodeElement();
if (code != null && !code.isEmpty())
writeOptionalTagWithTextNode(theEventWriter, "code", code.getValueAsString());
StringDt display = securityLabel.getDisplayElement();
if (display != null && !display.isEmpty())
writeOptionalTagWithTextNode(theEventWriter, "display", display.getValueAsString());
/*todo: handle version
StringDt version = securityLabel.getVersion();
if (version != null && ! version.isEmpty())
writeOptionalTagWithTextNode(theEventWriter, "version", version.getValueAsString());
*/
theEventWriter.writeEnd(); //end the individual security label
} }
theEventWriter.writeEnd(); //end security labels array theEventWriter.writeEnd();
} }
if (tags != null && tags.isEmpty() == false) {
theEventWriter.writeStartArray("tag");
for (Tag tag : tags) {
theEventWriter.writeStartObject();
writeOptionalTagWithTextNode(theEventWriter, "system", tag.getScheme());
writeOptionalTagWithTextNode(theEventWriter, "code", tag.getTerm());
writeOptionalTagWithTextNode(theEventWriter, "display", tag.getLabel());
theEventWriter.writeEnd();
}
theEventWriter.writeEnd();
} }
theEventWriter.writeEnd(); // end meta theEventWriter.writeEnd(); // end meta
} }
} }
if (theResource instanceof BaseBinary) { if (theResource instanceof IBaseBinary) {
BaseBinary bin = (BaseBinary) theResource; IBaseBinary bin = (IBaseBinary) theResource;
theEventWriter.write("contentType", bin.getContentType()); theEventWriter.write("contentType", bin.getContentType());
theEventWriter.write("content", bin.getContentAsBase64()); theEventWriter.write("content", bin.getContentAsBase64());
} else { } else {
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource); encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
} }
theEventWriter.writeEnd(); theEventWriter.writeEnd();
@ -1128,30 +1144,30 @@ public class JsonParser extends BaseParser implements IParser {
} }
} }
private void parseExtensionInDstu2Style(boolean theModifier, ParserState<?> theState, String theParentExtensionUrl, String theExtensionUrl, JsonArray theValues) { // private void parseExtensionInDstu2Style(boolean theModifier, ParserState<?> theState, String theParentExtensionUrl, String theExtensionUrl, JsonArray theValues) {
String extUrl = UrlUtil.constructAbsoluteUrl(theParentExtensionUrl, theExtensionUrl); // String extUrl = UrlUtil.constructAbsoluteUrl(theParentExtensionUrl, theExtensionUrl);
theState.enteringNewElementExtension(null, extUrl, theModifier); // theState.enteringNewElementExtension(null, extUrl, theModifier);
//
for (int extIdx = 0; extIdx < theValues.size(); extIdx++) { // for (int extIdx = 0; extIdx < theValues.size(); extIdx++) {
JsonObject nextExt = theValues.getJsonObject(extIdx); // JsonObject nextExt = theValues.getJsonObject(extIdx);
for (String nextKey : nextExt.keySet()) { // for (String nextKey : nextExt.keySet()) {
// if (nextKey.startsWith("value") && nextKey.length() > 5 && // // if (nextKey.startsWith("value") && nextKey.length() > 5 &&
// myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(nextKey) != null) { // // myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(nextKey) != null) {
JsonValue jsonVal = nextExt.get(nextKey); // JsonValue jsonVal = nextExt.get(nextKey);
if (jsonVal.getValueType() == ValueType.ARRAY) { // if (jsonVal.getValueType() == ValueType.ARRAY) {
/* // /*
* Extension children which are arrays are sub-extensions. Any other value type should be treated as a value. // * Extension children which are arrays are sub-extensions. Any other value type should be treated as a value.
*/ // */
JsonArray arrayValue = (JsonArray) jsonVal; // JsonArray arrayValue = (JsonArray) jsonVal;
parseExtensionInDstu2Style(theModifier, theState, extUrl, nextKey, arrayValue); // parseExtensionInDstu2Style(theModifier, theState, extUrl, nextKey, arrayValue);
} else { // } else {
parseChildren(theState, nextKey, jsonVal, null, null); // parseChildren(theState, nextKey, jsonVal, null, null);
} // }
} // }
} // }
//
theState.endingElement(); // theState.endingElement();
} // }
@Override @Override
public <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) { public <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) {

View File

@ -20,17 +20,17 @@ package ca.uhn.fhir.parser;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.FactoryConfigurationError;
@ -46,13 +46,12 @@ import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.primitive.*;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.IBase; import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource; import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType; import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension; import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
@ -73,20 +72,22 @@ import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions; import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt; import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt; import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt; import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseBinary; 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.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.rest.method.BaseMethodBinding; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper; import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
import ca.uhn.fhir.util.PrettyPrintWriterWrapper; import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
import ca.uhn.fhir.util.XmlUtil; import ca.uhn.fhir.util.XmlUtil;
@ -245,12 +246,12 @@ public class XmlParser extends BaseParser implements IParser {
writeTagWithTextNode(eventWriter, "title", theBundle.getTitle()); writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId()); writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());
writeAtomLink(eventWriter, "self", theBundle.getLinkSelf()); writeAtomLink(eventWriter, Constants.LINK_SELF, theBundle.getLinkSelf());
writeAtomLink(eventWriter, "first", theBundle.getLinkFirst()); writeAtomLink(eventWriter, Constants.LINK_FIRST, theBundle.getLinkFirst());
writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious()); writeAtomLink(eventWriter, Constants.LINK_PREVIOUS, theBundle.getLinkPrevious());
writeAtomLink(eventWriter, "next", theBundle.getLinkNext()); writeAtomLink(eventWriter, Constants.LINK_NEXT, theBundle.getLinkNext());
writeAtomLink(eventWriter, "last", theBundle.getLinkLast()); writeAtomLink(eventWriter, Constants.LINK_LAST, theBundle.getLinkLast());
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase()); writeAtomLink(eventWriter, Constants.LINK_FHIR_BASE, theBundle.getLinkBase());
if (theBundle.getTotalResults().getValue() != null) { if (theBundle.getTotalResults().getValue() != null) {
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS); eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
@ -412,9 +413,9 @@ public class XmlParser extends BaseParser implements IParser {
// IResource nextResource = nextEntry.getResource(); // IResource nextResource = nextEntry.getResource();
} }
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) { if (nextEntry.getTransactionMethod().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
theEventWriter.writeStartElement("transaction"); theEventWriter.writeStartElement("transaction");
writeOptionalTagWithValue(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue()); writeOptionalTagWithValue(theEventWriter, "method", nextEntry.getTransactionMethod().getValue());
writeOptionalTagWithValue(theEventWriter, "url", nextEntry.getLinkSearch().getValue()); writeOptionalTagWithValue(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} }
@ -733,69 +734,56 @@ public class XmlParser extends BaseParser implements IParser {
// HL7.org Structures // HL7.org Structures
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource); encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
} else { } else {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
// DSTU2+ // DSTU2+
IResource resource = (IResource) theResource; IResource resource = (IResource) theResource;
writeOptionalTagWithValue(theEventWriter, "id", theResourceId); writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED); InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
//Object securityLabelRawObj = resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
IdDt resourceId = resource.getId(); IdDt resourceId = resource.getId();
if (resourceId != null && isNotBlank(resourceId.getVersionIdPart())
|| (updated != null && !updated.isEmpty())
|| (securityLabels != null && !securityLabels.isEmpty())) {
theEventWriter.writeStartElement("meta");
String versionIdPart = resourceId.getVersionIdPart(); String versionIdPart = resourceId.getVersionIdPart();
if (isBlank(versionIdPart)) { if (isBlank(versionIdPart)) {
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource); versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
} }
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(resource);
if (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, profiles) == false) {
theEventWriter.writeStartElement("meta");
writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart); writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
if (updated != null) { if (updated != null) {
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString()); writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
} }
if (securityLabels != null) { for (IdDt profile : profiles) {
theEventWriter.writeStartElement("profile");
if (!securityLabels.isEmpty()) { theEventWriter.writeAttribute("value", profile.getValue());
theEventWriter.writeEndElement();
}
for (BaseCodingDt securityLabel : securityLabels) { for (BaseCodingDt securityLabel : securityLabels) {
theEventWriter.writeStartElement("security"); theEventWriter.writeStartElement("security");
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
UriDt system = securityLabel.getSystemElement(); encodeCompositeElementChildrenToStreamWriter(resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
if (system != null && !system.isEmpty())
writeOptionalTagWithValue(theEventWriter, "system", system.getValueAsString());
CodeDt code = securityLabel.getCodeElement();
if (code != null && !code.isEmpty())
writeOptionalTagWithValue(theEventWriter, "code", code.getValueAsString());
StringDt display = securityLabel.getDisplayElement();
if (display != null && !display.isEmpty())
writeOptionalTagWithValue(theEventWriter, "display", display.getValueAsString());
/*todo: handle version
StringDt version = securityLabel.getVersion();
if (version != null && ! version.isEmpty())
writeOptionalTagWithValue(theEventWriter, "version", version.getValueAsString());
*/
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} }
if (tags != null) {
for (Tag tag : tags) {
theEventWriter.writeStartElement("tag");
writeOptionalTagWithValue(theEventWriter, "system", tag.getScheme());
writeOptionalTagWithValue(theEventWriter, "code", tag.getTerm());
writeOptionalTagWithValue(theEventWriter, "display", tag.getLabel());
theEventWriter.writeEndElement();
} }
} }
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} }
if (theResource instanceof BaseBinary) { if (theResource instanceof IBaseBinary) {
BaseBinary bin = (BaseBinary) theResource; IBaseBinary bin = (IBaseBinary) theResource;
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType()); writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64()); writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
} else { } else {
@ -809,8 +797,8 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeAttribute("id", theResourceId); theEventWriter.writeAttribute("id", theResourceId);
} }
if (theResource instanceof BaseBinary) { if (theResource instanceof IBaseBinary) {
BaseBinary bin = (BaseBinary) theResource; IBaseBinary bin = (IBaseBinary) theResource;
if (bin.getContentType() != null) { if (bin.getContentType() != null) {
theEventWriter.writeAttribute("contentType", bin.getContentType()); theEventWriter.writeAttribute("contentType", bin.getContentType());
} }

View File

@ -30,10 +30,19 @@ import org.apache.commons.lang3.StringUtils;
*/ */
public class IncomingRequestAddressStrategy implements IServerAddressStrategy { public class IncomingRequestAddressStrategy implements IServerAddressStrategy {
private String myServletPath;
@Override @Override
public String determineServerBase(ServletContext theServletContext, HttpServletRequest theRequest) { public String determineServerBase(ServletContext theServletContext, HttpServletRequest theRequest) {
String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI()); String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI());
String servletPath = StringUtils.defaultString(theRequest.getServletPath());
String servletPath;
if (myServletPath != null) {
servletPath = myServletPath;
} else {
servletPath = StringUtils.defaultString(theRequest.getServletPath());
}
StringBuffer requestUrl = theRequest.getRequestURL(); StringBuffer requestUrl = theRequest.getRequestURL();
String servletContextPath = ""; String servletContextPath = "";
if (theServletContext != null) { if (theServletContext != null) {
@ -48,7 +57,9 @@ public class IncomingRequestAddressStrategy implements IServerAddressStrategy {
} }
int startOfPath = requestUrl.indexOf("//"); int startOfPath = requestUrl.indexOf("//");
if (startOfPath != -1 && (startOfPath + 2) < requestUrl.length()) { int requestUrlLength = requestUrl.length();
if (startOfPath != -1 && (startOfPath + 2) < requestUrlLength) {
startOfPath = requestUrl.indexOf("/", startOfPath + 2); startOfPath = requestUrl.indexOf("/", startOfPath + 2);
} }
if (startOfPath == -1) { if (startOfPath == -1) {
@ -56,9 +67,9 @@ public class IncomingRequestAddressStrategy implements IServerAddressStrategy {
} }
int contextIndex; int contextIndex;
if (servletPath.length() == 0) { if (servletPath.length() == 0 || servletPath.equals("/")) {
if (requestPath.length() == 0) { if (requestPath.length() == 0) {
contextIndex = requestUrl.length(); contextIndex = requestUrlLength;
} else { } else {
contextIndex = requestUrl.indexOf(requestPath, startOfPath); contextIndex = requestUrl.indexOf(requestPath, startOfPath);
} }
@ -68,8 +79,30 @@ public class IncomingRequestAddressStrategy implements IServerAddressStrategy {
String fhirServerBase; String fhirServerBase;
int length = contextIndex + servletPath.length(); int length = contextIndex + servletPath.length();
if (length > requestUrlLength) {
length = requestUrlLength;
}
fhirServerBase = requestUrl.substring(0, length); fhirServerBase = requestUrl.substring(0, length);
return fhirServerBase; return fhirServerBase;
} }
/**
* If set to a non-null value (default is <code>null</code>), this address strategy assumes that the FHIR endpoint is deployed to the given servlet path within the context. This is useful in some
* deployments where it isn't obvious to the servlet which part of the path is actually the root path to reach the servlet.
* <p>
* Example values could be:
* <ul>
* <li>null</li>
* <li>/</li>
* <li>/base</li>
* </ul>
* </p>
* <p>
* <b>Wildcards are not supported!</b>
* </p>
*/
public void setServletPath(String theServletPath) {
myServletPath = theServletPath;
}
} }

View File

@ -7,18 +7,16 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.ContextLoaderListener;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.server.ETagSupportEnum; import ca.uhn.fhir.rest.server.ETagSupportEnum;
import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.EncodingEnum;
@ -26,7 +24,7 @@ import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
public class TestRestfulServer extends RestfulServer { public class TestRestfulServer extends RestfulServer {
@ -165,18 +163,12 @@ public class TestRestfulServer extends RestfulServer {
setPagingProvider(new FifoMemoryPagingProvider(10)); setPagingProvider(new FifoMemoryPagingProvider(10));
/* /*
* Do some fancy logging to create a nice access log that has details * Load interceptors for the server from Spring (these are defined in hapi-fhir-server-config.xml
* about each incoming request.
*/ */
List<IServerInterceptor> interceptorBeans = myAppCtx.getBean("myServerInterceptors", List.class); List<IServerInterceptor> interceptorBeans = myAppCtx.getBean("myServerInterceptors", List.class);
for (IServerInterceptor interceptor : interceptorBeans) for (IServerInterceptor interceptor : interceptorBeans) {
this.registerInterceptor(interceptor); this.registerInterceptor(interceptor);
}
/*LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
loggingInterceptor.setLoggerName("fhirtest.access");
loggingInterceptor.setMessageFormat("Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]");
this.registerInterceptor(loggingInterceptor);
*/
} }

View File

@ -24,6 +24,11 @@
<util:list id="myServerInterceptors"> <util:list id="myServerInterceptors">
<ref bean="myLoggingInterceptor"/> <ref bean="myLoggingInterceptor"/>
</util:list> </util:list>
<!--
Do some fancy logging to create a nice access log that has details
about each incoming request.
-->
<bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor"> <bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor">
<property name="loggerName" value="fhirtest.access"/> <property name="loggerName" value="fhirtest.access"/>
<property name="messageFormat" <property name="messageFormat"

View File

@ -1,7 +1,8 @@
package ca.uhn.fhir.rest.server; package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -24,8 +25,6 @@ import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.server.ServerBaseTest.DummyProvider;
import ca.uhn.fhir.util.RandomServerPortProvider; import ca.uhn.fhir.util.RandomServerPortProvider;
public class IncomingRequestAddressStrategyTest { public class IncomingRequestAddressStrategyTest {
@ -99,9 +98,33 @@ public class IncomingRequestAddressStrategyTest {
startServer(port, contextPath, servletPath); startServer(port, contextPath, servletPath);
httpGet("http://localhost:" + port + "/ctx");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/Patient?_pretty=true");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/Patient/123/_history/222");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
httpGet("http://localhost:" + port); httpGet("http://localhost:" + port);
assertEquals(null, ourLastBase); assertEquals(null, ourLastBase);
}
@Test
public void testUnderJettyWithContextPathServletRootContextOnly() throws Exception {
int port = RandomServerPortProvider.findFreePort();
String contextPath = "/ctx";
String servletPath = "/";
startServer(port, contextPath, servletPath);
ourStrategy.setServletPath("");
httpGet("http://localhost:" + port + "/ctx"); httpGet("http://localhost:" + port + "/ctx");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase); assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
@ -113,6 +136,37 @@ public class IncomingRequestAddressStrategyTest {
httpGet("http://localhost:" + port + "/ctx/Patient/123/_history/222"); httpGet("http://localhost:" + port + "/ctx/Patient/123/_history/222");
assertEquals("http://localhost:" + port + "/ctx/", ourLastBase); assertEquals("http://localhost:" + port + "/ctx/", ourLastBase);
httpGet("http://localhost:" + port);
assertEquals(null, ourLastBase);
}
@Test
public void testUnderJettyWithContextPathServletRoot2() throws Exception {
int port = RandomServerPortProvider.findFreePort();
String contextPath = "/ctx";
String servletPath = "/foo/bar/*"; // not /* but still this should work
startServer(port, contextPath, servletPath);
httpGet("http://localhost:" + port + "/ctx/foo/bar/Patient?_pretty=true");
assertEquals("http://localhost:" + port + "/ctx/foo/bar", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/foo/bar");
assertEquals("http://localhost:" + port + "/ctx/foo/bar", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/foo/bar/");
assertEquals("http://localhost:" + port + "/ctx/foo/bar", ourLastBase);
httpGet("http://localhost:" + port + "/ctx/foo/bar/Patient/123/_history/222");
assertEquals("http://localhost:" + port + "/ctx/foo/bar", ourLastBase);
httpGet("http://localhost:" + port);
assertEquals(null, ourLastBase);
} }
@Test @Test
@ -168,6 +222,9 @@ public class IncomingRequestAddressStrategyTest {
@Override @Override
protected void doGet(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException { protected void doGet(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
// ourLog.info("Ctx: {}", theReq.)
ourLastBase = ourStrategy.determineServerBase(getServletContext(), theReq); ourLastBase = ourStrategy.determineServerBase(getServletContext(), theReq);
theResp.setContentType("text/plain"); theResp.setContentType("text/plain");
theResp.getWriter().append("Success"); theResp.getWriter().append("Success");

View File

@ -49,7 +49,9 @@ public class HomeRequest {
} }
if (retVal.contains("${serverBase}")) { if (retVal.contains("${serverBase}")) {
String base = new IncomingRequestAddressStrategy().determineServerBase(theRequest.getServletContext(), theRequest); IncomingRequestAddressStrategy strategy = new IncomingRequestAddressStrategy();
strategy.setServletPath("");
String base = strategy.determineServerBase(theRequest.getServletContext(), theRequest);
if (base.endsWith("/")) { if (base.endsWith("/")) {
base = base.substring(0, base.length() - 1); base = base.substring(0, base.length() - 1);
} }