working on binary resources
This commit is contained in:
parent
0ad18c0b77
commit
adde115c53
|
@ -20,38 +20,64 @@ package ca.uhn.fhir.model.dstu.resource;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.model.api.BaseResource;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.primitive.Base64BinaryDt;
|
||||
|
||||
@ResourceDef(name="Binary", profile="http://hl7.org/fhir/profiles/Binary", id="binary")
|
||||
public class Binary extends BaseResource implements IResource {
|
||||
@ResourceDef(name = "Binary", profile = "http://hl7.org/fhir/profiles/Binary", id = "binary")
|
||||
public class Binary extends BaseResource implements IResource {
|
||||
|
||||
// TODO: implement binary
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
private Base64BinaryDt myContent = new Base64BinaryDt();
|
||||
private String myContentType;
|
||||
|
||||
@Override
|
||||
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
|
||||
return null;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainedDt getContained() {
|
||||
return null;
|
||||
public byte[] getContent() {
|
||||
return myContent.getValue();
|
||||
}
|
||||
|
||||
public String getContentAsBase64() {
|
||||
return myContent.getValueAsString();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return myContentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not call - throws {@link UnsupportedOperationException}
|
||||
*/
|
||||
@Override
|
||||
public NarrativeDt getText() {
|
||||
throw new IllegalStateException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return (myContent.isEmpty()) && StringUtils.isBlank(myContentType);
|
||||
}
|
||||
|
||||
public void setContent(byte[] theContent) {
|
||||
myContent.setValue(theContent);
|
||||
}
|
||||
|
||||
public void setContentAsBase64(String theContent) {
|
||||
myContent.setValueAsString(theContent);
|
||||
}
|
||||
|
||||
public void setContentType(String theContentType) {
|
||||
myContentType = theContentType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ import ca.uhn.fhir.model.api.annotation.Child;
|
|||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -477,10 +478,14 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theEventWriter.write("id", theResource.getId().getValue());
|
||||
}
|
||||
|
||||
extractAndWriteExtensionsAsDirectChild(theResource, theEventWriter, resDef, theResDef, theResource);
|
||||
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef);
|
||||
|
||||
if (theResource instanceof Binary) {
|
||||
Binary bin = (Binary) theResource;
|
||||
theEventWriter.write("contentType", bin.getContentType());
|
||||
theEventWriter.write("content",bin.getContentAsBase64());
|
||||
} else {
|
||||
extractAndWriteExtensionsAsDirectChild(theResource, theEventWriter, resDef, theResDef, theResource);
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ import ca.uhn.fhir.model.api.Tag;
|
|||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
|
@ -267,14 +268,14 @@ class ParserState<T> {
|
|||
} else {
|
||||
id = entry.getId();
|
||||
}
|
||||
|
||||
|
||||
IResource resource = entry.getResource();
|
||||
if (resource == null && id != null && isNotBlank(id.getResourceType())) {
|
||||
resource = myContext.getResourceDefinition(id.getResourceType()).newInstance();
|
||||
resource.setId(id);
|
||||
entry.setResource(resource);
|
||||
}
|
||||
|
||||
|
||||
if (resource != null) {
|
||||
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.DELETED_AT, entry.getDeletedAt());
|
||||
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, id);
|
||||
|
@ -346,10 +347,10 @@ class ParserState<T> {
|
|||
}
|
||||
|
||||
IdDt id = myEntry.getId();
|
||||
if(id!=null && id.isEmpty()==false) {
|
||||
if (id != null && id.isEmpty() == false) {
|
||||
myEntry.getResource().setId(id);
|
||||
}
|
||||
|
||||
|
||||
Map<ResourceMetadataKeyEnum, Object> metadata = myEntry.getResource().getResourceMetadata();
|
||||
if (myEntry.getPublished().isEmpty() == false) {
|
||||
metadata.put(ResourceMetadataKeyEnum.PUBLISHED, myEntry.getPublished());
|
||||
|
@ -459,6 +460,77 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
private class BinaryResourceState extends BaseState {
|
||||
|
||||
private static final int SUBSTATE_CT = 1;
|
||||
private static final int SUBSTATE_CONTENT = 2;
|
||||
private Binary myInstance;
|
||||
private String myData;
|
||||
private int mySubState = 0;
|
||||
|
||||
public BinaryResourceState(PreResourceState thePreResourceState, Binary theInstance) {
|
||||
super(thePreResourceState);
|
||||
myInstance = theInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
if ("contentType".equals(theName)) {
|
||||
myInstance.setContentType(theValue);
|
||||
} else if (myJsonMode && "value".equals(theName)) {
|
||||
string(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
if (mySubState == SUBSTATE_CT) {
|
||||
myInstance.setContentType(myData);
|
||||
mySubState = 0;
|
||||
myData=null;
|
||||
return;
|
||||
} else if (mySubState == SUBSTATE_CONTENT) {
|
||||
myInstance.setContentAsBase64(myData);
|
||||
mySubState = 0;
|
||||
myData=null;
|
||||
return;
|
||||
} else {
|
||||
if (!myJsonMode) {
|
||||
myInstance.setContentAsBase64(myData);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if (myJsonMode && "contentType".equals(theLocalPart) && mySubState == 0) {
|
||||
mySubState = SUBSTATE_CT;
|
||||
} else if (myJsonMode && "content".equals(theLocalPart) && mySubState == 0) {
|
||||
mySubState = SUBSTATE_CONTENT;
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected nested element in atom tag: " + theLocalPart);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void string(String theData) {
|
||||
if (myData == null) {
|
||||
myData = theData;
|
||||
} else {
|
||||
// this shouldn't generally happen so it's ok that it's
|
||||
// inefficient
|
||||
myData = myData + theData;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IElement getCurrentElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class AtomPrimitiveState extends BaseState {
|
||||
|
||||
private String myData;
|
||||
|
@ -1061,7 +1133,11 @@ class ParserState<T> {
|
|||
myEntry.setResource(myInstance);
|
||||
}
|
||||
|
||||
push(new ElementCompositeState(this, def, myInstance));
|
||||
if ("Binary".equals(def.getName())) {
|
||||
push(new BinaryResourceState(this, (Binary) myInstance));
|
||||
} else {
|
||||
push(new ElementCompositeState(this, def, myInstance));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, IResource> getContainedResources() {
|
||||
|
|
|
@ -70,6 +70,7 @@ import ca.uhn.fhir.model.api.TagList;
|
|||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
@ -551,7 +552,13 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeAttribute("id", theResource.getId().getValue());
|
||||
}
|
||||
|
||||
encodeCompositeElementToStreamWriter(resDef, theResource, theResource, theEventWriter, resDef, theIncludedResource);
|
||||
if (theResource instanceof Binary) {
|
||||
Binary bin = (Binary) theResource;
|
||||
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
||||
theEventWriter.writeCharacters(bin.getContentAsBase64());
|
||||
} else {
|
||||
encodeCompositeElementToStreamWriter(resDef, theResource, theResource, theEventWriter, resDef, theIncludedResource);
|
||||
}
|
||||
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
|
|
@ -112,11 +112,9 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
IResource resource;
|
||||
if (requestContainsResource()) {
|
||||
resource = parser.parseResource(theRequest.getInputReader());
|
||||
resource = parseIncomingServerResource(theRequest);
|
||||
TagList tagList = new TagList();
|
||||
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
|
||||
String nextTagComplete = enumeration.nextElement();
|
||||
|
@ -138,10 +136,12 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
response = (MethodOutcome) invokeServerMethod(params);
|
||||
} catch (InternalErrorException e) {
|
||||
ourLog.error("Internal error during method invocation", e);
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
|
||||
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
|
||||
return;
|
||||
} catch (BaseServerResponseException e) {
|
||||
ourLog.info("Exception during method invocation: " + e.getMessage());
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
|
||||
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
|
||||
return;
|
||||
}
|
||||
|
@ -172,8 +172,10 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
theServer.addHeadersToResponse(theResponse);
|
||||
|
||||
if (response != null && response.getOperationOutcome() != null) {
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
|
||||
theResponse.setContentType(encoding.getResourceContentType());
|
||||
Writer writer = theResponse.getWriter();
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
parser.setPrettyPrint(RestfulServer.prettyPrintResponse(theRequest));
|
||||
try {
|
||||
parser.encodeResourceToWriter(response.getOperationOutcome(), writer);
|
||||
|
@ -189,6 +191,14 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
// getMethod().in
|
||||
}
|
||||
|
||||
private IResource parseIncomingServerResource(Request theRequest) {
|
||||
IResource resource;
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
resource = parser.parseResource(theRequest.getInputReader());
|
||||
return resource;
|
||||
}
|
||||
|
||||
/*
|
||||
* @Override public void invokeServer(RestfulServer theServer, Request
|
||||
* theRequest, HttpServletResponse theResponse) throws
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -35,6 +35,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -50,8 +51,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
|||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
|
@ -289,6 +289,24 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
||||
if (theResource instanceof Binary) {
|
||||
Binary bin = (Binary) theResource;
|
||||
if (isNotBlank(bin.getContentType())) {
|
||||
theHttpResponse.setContentType(bin.getContentType());
|
||||
}else {
|
||||
theHttpResponse.setContentType(Constants.CT_OCTET_STREAM);
|
||||
}
|
||||
if (bin.getContent()==null || bin.getContent().length==0) {
|
||||
return;
|
||||
}
|
||||
theHttpResponse.setContentLength(bin.getContent().length);
|
||||
ServletOutputStream oos = theHttpResponse.getOutputStream();
|
||||
oos.write(bin.getContent());
|
||||
oos.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else if (theNarrativeMode == NarrativeModeEnum.ONLY) {
|
||||
|
|
|
@ -28,54 +28,55 @@ import java.util.Set;
|
|||
|
||||
public class Constants {
|
||||
|
||||
public static final String CHARSET_UTF_8 = "UTF-8";
|
||||
public static final String CT_ATOM_XML = "application/atom+xml";
|
||||
public static final String CT_FHIR_JSON = "application/json+fhir";
|
||||
public static final String CT_FHIR_XML = "application/xml+fhir";
|
||||
public static final String PARAM_FORMAT = "_format";
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String CT_ATOM_XML = "application/atom+xml";
|
||||
public static final Set<String> FORMAT_VAL_XML;
|
||||
public static final String CT_HTML = "text/html";
|
||||
public static final String CT_JSON = "application/json";
|
||||
public static final String CT_OCTET_STREAM = "application/octet-stream";
|
||||
public static final String CT_TEXT = "text/plain";
|
||||
public static final String CT_XML = "application/xml";
|
||||
public static final String FORMAT_JSON = "json";
|
||||
public static final Set<String> FORMAT_VAL_JSON;
|
||||
public static final Map<String, EncodingEnum> FORMAT_VAL_TO_ENCODING;
|
||||
public static final String CT_XML = "application/xml";
|
||||
public static final String CT_JSON = "application/json";
|
||||
public static final String CT_HTML = "text/html";
|
||||
public static final String PARAM_NARRATIVE = "_narrative";
|
||||
public static final String PARAM_HISTORY = "_history";
|
||||
public static final String PARAM_PRETTY = "_pretty";
|
||||
public static final String PARAM_QUERY = "_query";
|
||||
public static final int STATUS_HTTP_201_CREATED = 201;
|
||||
public static final String CT_TEXT = "text/plain";
|
||||
public static final int STATUS_HTTP_200_OK = 200;
|
||||
public static final int STATUS_HTTP_422_UNPROCESSABLE_ENTITY = 422;
|
||||
public static final int STATUS_HTTP_404_NOT_FOUND = 404;
|
||||
public static final int STATUS_HTTP_400_BAD_REQUEST = 400;
|
||||
public static final int STATUS_HTTP_405_METHOD_NOT_ALLOWED = 405;
|
||||
public static final int STATUS_HTTP_409_CONFLICT = 409;
|
||||
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
||||
public static final Set<String> FORMAT_VAL_XML;
|
||||
public static final String FORMAT_XML = "xml";
|
||||
public static final String HEADER_ACCEPT = "Accept";
|
||||
public static final String HEADER_CATEGORY = "Category";
|
||||
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
|
||||
public static final int STATUS_HTTP_204_NO_CONTENT = 204;
|
||||
public static final String PARAM_COUNT = "_count";
|
||||
public static final String PARAM_SINCE = "_since";
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String HEADER_LAST_MODIFIED = "Last-Modified";
|
||||
public static final String HEADER_LAST_MODIFIED_LOWERCASE = HEADER_LAST_MODIFIED.toLowerCase();
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
public static final int STATUS_HTTP_401_CLIENT_UNAUTHORIZED = 401;
|
||||
public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
|
||||
public static final String OPENSEARCH_NS_OLDER = "http://purl.org/atompub/tombstones/1.0";
|
||||
public static final String PARAM_COUNT = "_count";
|
||||
public static final String PARAM_DELETE = "_delete";
|
||||
public static final String PARAM_FORMAT = "_format";
|
||||
public static final String PARAM_HISTORY = "_history";
|
||||
public static final String PARAM_INCLUDE = "_include";
|
||||
public static final String PARAM_NARRATIVE = "_narrative";
|
||||
public static final String PARAM_PRETTY = "_pretty";
|
||||
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
|
||||
public static final String PARAM_QUERY = "_query";
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String PARAM_SINCE = "_since";
|
||||
public static final String PARAM_SORT = "_sort";
|
||||
public static final String PARAM_SORT_ASC = "_sort:asc";
|
||||
public static final String PARAM_SORT_DESC = "_sort:desc";
|
||||
public static final String HEADER_CATEGORY = "Category";
|
||||
public static final String OPENSEARCH_NS_OLDER = "http://purl.org/atompub/tombstones/1.0";
|
||||
public static final String PARAM_TAGS = "_tags";
|
||||
public static final String CHARSET_UTF_8 = "UTF-8";
|
||||
public static final String PARAM_DELETE = "_delete";
|
||||
public static final String FORMAT_XML = "xml";
|
||||
public static final String FORMAT_JSON = "json";
|
||||
public static final String PARAM_INCLUDE = "_include";
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
|
||||
public static final String HEADER_ACCEPT = "Accept";
|
||||
public static final int STATUS_HTTP_200_OK = 200;
|
||||
public static final int STATUS_HTTP_201_CREATED = 201;
|
||||
public static final int STATUS_HTTP_204_NO_CONTENT = 204;
|
||||
public static final int STATUS_HTTP_400_BAD_REQUEST = 400;
|
||||
public static final int STATUS_HTTP_401_CLIENT_UNAUTHORIZED = 401;
|
||||
public static final int STATUS_HTTP_404_NOT_FOUND = 404;
|
||||
public static final int STATUS_HTTP_405_METHOD_NOT_ALLOWED = 405;
|
||||
public static final int STATUS_HTTP_409_CONFLICT = 409;
|
||||
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
||||
public static final int STATUS_HTTP_422_UNPROCESSABLE_ENTITY = 422;
|
||||
public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -343,40 +343,49 @@ public class RestfulServer extends HttpServlet {
|
|||
findResourceMethods(theProvider, clazz);
|
||||
}
|
||||
|
||||
private void findResourceMethods(Object theProvider, Class<?> clazz) {
|
||||
private void findResourceMethods(Object theProvider, Class<?> clazz) throws ConfigurationException {
|
||||
int count = 0;
|
||||
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, myFhirContext, theProvider);
|
||||
if (foundMethodBinding == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (!Modifier.isPublic(m.getModifiers())) {
|
||||
ourLog.debug("Ignoring non-public method: {}", m);
|
||||
throw new ConfigurationException("Method '" + m.getName() + "' is not public, FHIR RESTful methods must be public");
|
||||
} else {
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
throw new ConfigurationException("Method '" + m.getName() + "' is static, FHIR RESTful methods must not be static");
|
||||
} else {
|
||||
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||
|
||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, myFhirContext, theProvider);
|
||||
if (foundMethodBinding != null) {
|
||||
|
||||
String resourceName = foundMethodBinding.getResourceName();
|
||||
ResourceBinding resourceBinding;
|
||||
if (resourceName == null) {
|
||||
resourceBinding = myNullResourceBinding;
|
||||
} else {
|
||||
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(resourceName);
|
||||
if (myResourceNameToProvider.containsKey(definition.getName())) {
|
||||
resourceBinding = myResourceNameToProvider.get(definition.getName());
|
||||
} else {
|
||||
resourceBinding = new ResourceBinding();
|
||||
resourceBinding.setResourceName(resourceName);
|
||||
myResourceNameToProvider.put(resourceName, resourceBinding);
|
||||
}
|
||||
}
|
||||
|
||||
resourceBinding.addMethod(foundMethodBinding);
|
||||
ourLog.debug(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
||||
String resourceName = foundMethodBinding.getResourceName();
|
||||
ResourceBinding resourceBinding;
|
||||
if (resourceName == null) {
|
||||
resourceBinding = myNullResourceBinding;
|
||||
} else {
|
||||
ourLog.debug(" * Method: {}#{} is not a handler", theProvider.getClass(), m.getName());
|
||||
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(resourceName);
|
||||
if (myResourceNameToProvider.containsKey(definition.getName())) {
|
||||
resourceBinding = myResourceNameToProvider.get(definition.getName());
|
||||
} else {
|
||||
resourceBinding = new ResourceBinding();
|
||||
resourceBinding.setResourceName(resourceName);
|
||||
myResourceNameToProvider.put(resourceName, resourceBinding);
|
||||
}
|
||||
}
|
||||
|
||||
resourceBinding.addMethod(foundMethodBinding);
|
||||
ourLog.debug(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
throw new ConfigurationException("Did not find any annotated RESTful methods on provider class " + theProvider.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private void findSystemMethods(Object theSystemProvider) {
|
||||
|
@ -472,8 +481,8 @@ public class RestfulServer extends HttpServlet {
|
|||
String servletContextPath = "";
|
||||
if (theRequest.getServletContext() != null) {
|
||||
servletContextPath = StringUtils.defaultString(theRequest.getServletContext().getContextPath());
|
||||
// } else {
|
||||
//servletContextPath = servletPath;
|
||||
// } else {
|
||||
// servletContextPath = servletPath;
|
||||
}
|
||||
|
||||
if (ourLog.isTraceEnabled()) {
|
||||
|
|
|
@ -39,6 +39,7 @@ import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
|
@ -69,6 +70,28 @@ public class JsonParserTest {
|
|||
assertEquals("{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://foo#bar\"}]}", str);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeBinaryResource() {
|
||||
|
||||
Binary patient = new Binary();
|
||||
patient.setContentType("foo");
|
||||
patient.setContent(new byte[] {1,2,3,4});
|
||||
|
||||
String val = ourCtx.newJsonParser().encodeResourceToString(patient);
|
||||
assertEquals("{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}",val);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseBinaryResource() {
|
||||
|
||||
Binary val = ourCtx.newJsonParser().parseResource(Binary.class, "{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}");
|
||||
assertEquals("foo", val.getContentType());
|
||||
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagList() {
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -43,6 +39,7 @@ import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
|
@ -81,6 +78,28 @@ public class XmlParserTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeBinaryResource() {
|
||||
|
||||
Binary patient = new Binary();
|
||||
patient.setContentType("foo");
|
||||
patient.setContent(new byte[] {1,2,3,4});
|
||||
|
||||
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseBinaryResource() {
|
||||
|
||||
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
|
||||
assertEquals("foo", val.getContentType());
|
||||
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagList() {
|
||||
|
||||
|
@ -92,7 +111,7 @@ public class XmlParserTest {
|
|||
"</taglist>";
|
||||
//@formatter:on
|
||||
|
||||
TagList tagList = new FhirContext().newXmlParser().parseTagList(tagListStr);
|
||||
TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr);
|
||||
assertEquals(3, tagList.size());
|
||||
assertEquals("term0", tagList.get(0).getTerm());
|
||||
assertEquals("label0", tagList.get(0).getLabel());
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ch.qos.logback.core.util.ContentTypeUtil;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class BinaryTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx = new FhirContext();
|
||||
private static Binary ourLast;
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BinaryTest.class);
|
||||
|
||||
private static int ourPort;
|
||||
|
||||
private static Server ourServer;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourLast=null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals("foo", status.getFirstHeader("content-type").getValue());
|
||||
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
Binary res = new Binary();
|
||||
res.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
res.setContentType("text/plain");
|
||||
String stringContent = ourCtx.newJsonParser().encodeResourceToString(res);
|
||||
|
||||
HttpPost http = new HttpPost("http://localhost:" + ourPort + "/Binary");
|
||||
http.setEntity(new StringEntity(stringContent, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(http);
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertEquals("text/plain", ourLast.getContentType());
|
||||
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, ourLast.getContent());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary?");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals(Constants.CT_ATOM_XML + "; charset=UTF-8", status.getFirstHeader("content-type").getValue());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
Binary bin = (Binary) bundle.getEntries().get(0).getResource();
|
||||
|
||||
assertEquals("text/plain", bin.getContentType());
|
||||
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, bin.getContent());
|
||||
}
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
ResourceProvider patientProvider = new ResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class ResourceProvider implements IResourceProvider {
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam Binary theBinary) {
|
||||
ourLast = theBinary;
|
||||
return new MethodOutcome(new IdDt("1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Binary.class;
|
||||
}
|
||||
|
||||
@Read
|
||||
public Binary read(@IdParam IdDt theId) {
|
||||
Binary retVal = new Binary();
|
||||
retVal.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
retVal.setContentType(theId.getUnqualifiedId());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Search
|
||||
public List<Binary> search() {
|
||||
Binary retVal = new Binary();
|
||||
retVal.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
retVal.setContentType("text/plain");
|
||||
return Collections.singletonList(retVal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
public class ResourceProviderWithNoMethodsTest {
|
||||
|
||||
private Server ourServer;
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoAnnotatedMethods() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(port);
|
||||
|
||||
ResourceProvider patientProvider = new ResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
|
||||
try {
|
||||
ourServer.start();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertEquals(e.getCause().getClass(), ConfigurationException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonPublicMethod() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(port);
|
||||
|
||||
NonPublicMethodProvider patientProvider = new NonPublicMethodProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
|
||||
try {
|
||||
ourServer.start();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertEquals(e.getCause().getClass(), ConfigurationException.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ResourceProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Binary.class;
|
||||
}
|
||||
|
||||
public Binary read(@IdParam IdDt theId) {
|
||||
Binary retVal = new Binary();
|
||||
retVal.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
retVal.setContentType(theId.getUnqualifiedId());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class NonPublicMethodProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Binary.class;
|
||||
}
|
||||
|
||||
@Read
|
||||
protected Binary read(@IdParam IdDt theId) {
|
||||
Binary retVal = new Binary();
|
||||
retVal.setContent(new byte[] { 1, 2, 3, 4 });
|
||||
retVal.setContentType(theId.getUnqualifiedId());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue