working on binary resources

This commit is contained in:
jamesagnew 2014-05-28 07:30:40 -04:00
parent 0ad18c0b77
commit adde115c53
12 changed files with 568 additions and 98 deletions

View File

@ -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")
@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;
}
}

View File

@ -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());
}
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();
}

View File

@ -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;
@ -346,7 +347,7 @@ class ParserState<T> {
}
IdDt id = myEntry.getId();
if(id!=null && id.isEmpty()==false) {
if (id != null && id.isEmpty() == false) {
myEntry.getResource().setId(id);
}
@ -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,8 +1133,12 @@ class ParserState<T> {
myEntry.setResource(myInstance);
}
if ("Binary".equals(def.getName())) {
push(new BinaryResourceState(this, (Binary) myInstance));
} else {
push(new ElementCompositeState(this, def, myInstance));
}
}
public Map<String, IResource> getContainedResources() {
return myContainedResources;

View File

@ -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());
}
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();
}

View File

@ -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

View File

@ -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) {

View File

@ -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>();

View File

@ -343,16 +343,24 @@ public class RestfulServer extends HttpServlet {
findResourceMethods(theProvider, clazz);
}
private void findResourceMethods(Object theProvider, Class<?> clazz) {
for (Method m : clazz.getDeclaredMethods()) {
if (!Modifier.isPublic(m.getModifiers())) {
ourLog.debug("Ignoring non-public method: {}", m);
} else {
if (!Modifier.isStatic(m.getModifiers())) {
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
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) {
if (foundMethodBinding == null) {
continue;
}
count++;
if (!Modifier.isPublic(m.getModifiers())) {
throw new ConfigurationException("Method '" + m.getName() + "' is not public, FHIR RESTful methods must be public");
} else {
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());
String resourceName = foundMethodBinding.getResourceName();
ResourceBinding resourceBinding;
@ -371,11 +379,12 @@ public class RestfulServer extends HttpServlet {
resourceBinding.addMethod(foundMethodBinding);
ourLog.debug(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
} else {
ourLog.debug(" * Method: {}#{} is not 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());
}
}
@ -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()) {

View File

@ -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() {

View File

@ -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());

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}