Clean up resource parameter handling
This commit is contained in:
parent
8f27462db7
commit
064f113133
|
@ -85,10 +85,12 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
myContext = theFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConnectionRequestTimeout() {
|
||||
return myConnectionRequestTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConnectTimeout() {
|
||||
return myConnectTimeout;
|
||||
}
|
||||
|
@ -274,6 +276,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
myHttpClient = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
|
||||
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
|
||||
|
|
|
@ -98,6 +98,51 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
myParameters = MethodUtil.getResourceParameters(theContext, theMethod, theProvider, getResourceOperationType());
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingResponse(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode) {
|
||||
EncodingEnum encoding = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (encoding == null) {
|
||||
NonFhirResponseException ex = NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
|
||||
populateException(ex, theResponseReader);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
return parser;
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingServerRequest(Request theRequest) {
|
||||
String contentTypeHeader = theRequest.getServletRequest().getHeader("content-type");
|
||||
EncodingEnum encoding;
|
||||
if (isBlank(contentTypeHeader)) {
|
||||
encoding = EncodingEnum.XML;
|
||||
} else {
|
||||
int semicolon = contentTypeHeader.indexOf(';');
|
||||
if (semicolon != -1) {
|
||||
contentTypeHeader = contentTypeHeader.substring(0, semicolon);
|
||||
}
|
||||
encoding = EncodingEnum.forContentType(contentTypeHeader);
|
||||
}
|
||||
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("Request contins non-FHIR conent-type header value: " + contentTypeHeader);
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
return parser;
|
||||
}
|
||||
|
||||
protected Object[] createParametersForServerRequest(Request theRequest, byte[] theRequestContents) {
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
IParameter param = getParameters().get(i);
|
||||
if (param == null) {
|
||||
continue;
|
||||
}
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, theRequestContents, this);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public List<Class<?>> getAllowableParamAnnotations() {
|
||||
return null;
|
||||
}
|
||||
|
@ -128,6 +173,10 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return myParameters;
|
||||
}
|
||||
|
||||
public Object getProvider() {
|
||||
return myProvider;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Set<Include> getRequestIncludesFromParams(Object[] params) {
|
||||
if (params == null || params.length == 0)
|
||||
|
@ -163,16 +212,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return null;
|
||||
}
|
||||
|
||||
public Object getProvider() {
|
||||
return myProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the resource this method handles, or <code>null</code> if this method is not resource
|
||||
* specific
|
||||
*/
|
||||
public abstract String getResourceName();
|
||||
|
||||
public abstract RestfulOperationTypeEnum getResourceOperationType();
|
||||
|
||||
/**
|
||||
* Returns the value of {@link #getResourceOperationType()} or {@link #getSystemOperationType()} or {@link #getOtherOperationType()}
|
||||
*/
|
||||
|
@ -192,8 +239,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return null;
|
||||
}
|
||||
|
||||
public abstract RestfulOperationTypeEnum getResourceOperationType();
|
||||
|
||||
public abstract RestfulOperationSystemEnum getSystemOperationType();
|
||||
|
||||
public abstract boolean incomingServerRequestMatchesMethod(Request theRequest);
|
||||
|
@ -202,56 +247,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
|
||||
public abstract void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException;
|
||||
|
||||
/** For unit tests only */
|
||||
public void setParameters(List<IParameter> theParameters) {
|
||||
myParameters = theParameters;
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingResponse(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode) {
|
||||
EncodingEnum encoding = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (encoding == null) {
|
||||
NonFhirResponseException ex = NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
|
||||
populateException(ex, theResponseReader);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
return parser;
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingServerRequest(Request theRequest) {
|
||||
String contentTypeHeader = theRequest.getServletRequest().getHeader("content-type");
|
||||
EncodingEnum encoding;
|
||||
if (isBlank(contentTypeHeader)) {
|
||||
encoding = EncodingEnum.XML;
|
||||
} else {
|
||||
int semicolon = contentTypeHeader.indexOf(';');
|
||||
if (semicolon != -1) {
|
||||
contentTypeHeader = contentTypeHeader.substring(0, semicolon);
|
||||
}
|
||||
encoding = EncodingEnum.forContentType(contentTypeHeader);
|
||||
}
|
||||
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("Request contins non-FHIR conent-type header value: " + contentTypeHeader);
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
return parser;
|
||||
}
|
||||
|
||||
protected Object[] createParametersForServerRequest(Request theRequest, IBaseResource theResource) {
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
IParameter param = getParameters().get(i);
|
||||
if (param == null) {
|
||||
continue;
|
||||
}
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, theResource);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
protected Object invokeServerMethod(Object[] theMethodParams) {
|
||||
try {
|
||||
Method method = getMethod();
|
||||
|
@ -267,6 +262,11 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
}
|
||||
|
||||
protected byte[] loadRequestContents(Request theRequest) throws IOException {
|
||||
byte[] requestContents = IOUtils.toByteArray(theRequest.getServletRequest().getInputStream());
|
||||
return requestContents;
|
||||
}
|
||||
|
||||
protected BaseServerResponseException processNon2xxResponseAndReturnExceptionToThrow(int theStatusCode, String theResponseMimeType, Reader theResponseReader) {
|
||||
BaseServerResponseException ex;
|
||||
switch (theStatusCode) {
|
||||
|
@ -300,6 +300,11 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return ex;
|
||||
}
|
||||
|
||||
/** For unit tests only */
|
||||
public void setParameters(List<IParameter> theParameters) {
|
||||
myParameters = theParameters;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static BaseMethodBinding<?> bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
Read read = theMethod.getAnnotation(Read.class);
|
||||
|
@ -470,6 +475,52 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
// return sm;
|
||||
}
|
||||
|
||||
private static void populateException(BaseServerResponseException theEx, Reader theResponseReader) {
|
||||
try {
|
||||
String responseText = IOUtils.toString(theResponseReader);
|
||||
theEx.setResponseBody(responseText);
|
||||
} catch (IOException e) {
|
||||
ourLog.debug("Failed to read response", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toLogString(Class<?> theType) {
|
||||
if (theType == null) {
|
||||
return null;
|
||||
}
|
||||
return theType.getCanonicalName();
|
||||
}
|
||||
|
||||
protected static IBundleProvider toResourceList(Object response) throws InternalErrorException {
|
||||
if (response == null) {
|
||||
return BundleProviders.newEmptyList();
|
||||
} else if (response instanceof IBundleProvider) {
|
||||
return (IBundleProvider) response;
|
||||
} else if (response instanceof IResource) {
|
||||
return BundleProviders.newList((IResource) response);
|
||||
} else if (response instanceof Collection) {
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
for (Object next : ((Collection<?>) response)) {
|
||||
retVal.add((IBaseResource) next);
|
||||
}
|
||||
return BundleProviders.newList(retVal);
|
||||
} else {
|
||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean verifyIsValidResourceReturnType(Class<?> theReturnType) {
|
||||
if (theReturnType == null) {
|
||||
return false;
|
||||
}
|
||||
if (!IBaseResource.class.isAssignableFrom(theReturnType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// boolean retVal = Modifier.isAbstract(theReturnType.getModifiers()) == false;
|
||||
// return retVal;
|
||||
}
|
||||
|
||||
public static boolean verifyMethodHasZeroOrOneOperationAnnotation(Method theNextMethod, Object... theAnnotations) {
|
||||
Object obj1 = null;
|
||||
for (Object object : theAnnotations) {
|
||||
|
@ -493,50 +544,4 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void populateException(BaseServerResponseException theEx, Reader theResponseReader) {
|
||||
try {
|
||||
String responseText = IOUtils.toString(theResponseReader);
|
||||
theEx.setResponseBody(responseText);
|
||||
} catch (IOException e) {
|
||||
ourLog.debug("Failed to read response", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toLogString(Class<?> theType) {
|
||||
if (theType == null) {
|
||||
return null;
|
||||
}
|
||||
return theType.getCanonicalName();
|
||||
}
|
||||
|
||||
private static boolean verifyIsValidResourceReturnType(Class<?> theReturnType) {
|
||||
if (theReturnType == null) {
|
||||
return false;
|
||||
}
|
||||
if (!IBaseResource.class.isAssignableFrom(theReturnType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// boolean retVal = Modifier.isAbstract(theReturnType.getModifiers()) == false;
|
||||
// return retVal;
|
||||
}
|
||||
|
||||
protected static IBundleProvider toResourceList(Object response) throws InternalErrorException {
|
||||
if (response == null) {
|
||||
return BundleProviders.newEmptyList();
|
||||
} else if (response instanceof IBundleProvider) {
|
||||
return (IBundleProvider) response;
|
||||
} else if (response instanceof IResource) {
|
||||
return BundleProviders.newList((IResource) response);
|
||||
} else if (response instanceof Collection) {
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
for (Object next : ((Collection<?>) response)) {
|
||||
retVal.add((IBaseResource) next);
|
||||
}
|
||||
return BundleProviders.newList(retVal);
|
||||
} else {
|
||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,30 +20,21 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
|
@ -56,7 +47,6 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||
|
@ -149,24 +139,14 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
IBaseResource resource;
|
||||
if (requestContainsResource()) {
|
||||
resource = parseIncomingServerResource(theRequest);
|
||||
if (theServer.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
TagList tagList = new TagList();
|
||||
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
|
||||
String nextTagComplete = enumeration.nextElement();
|
||||
MethodUtil.parseTagValue(tagList, nextTagComplete);
|
||||
}
|
||||
if (tagList.isEmpty() == false) {
|
||||
((IResource)resource).getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resource = null;
|
||||
}
|
||||
byte[] requestContents = loadRequestContents(theRequest);
|
||||
// if (requestContainsResource()) {
|
||||
// requestContents = parseIncomingServerResource(theRequest);
|
||||
// } else {
|
||||
// requestContents = null;
|
||||
// }
|
||||
|
||||
Object[] params = createParametersForServerRequest(theRequest, resource);
|
||||
Object[] params = createParametersForServerRequest(theRequest, requestContents);
|
||||
addParametersForServerRequest(theRequest, params);
|
||||
|
||||
HttpServletResponse servletResponse = theRequest.getServletResponse();
|
||||
|
@ -274,73 +254,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
return myReturnVoid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IOException
|
||||
*/
|
||||
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
|
||||
|
||||
Reader requestReader;
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncodingNoDefault(theRequest);
|
||||
if (encoding == null) {
|
||||
String ctValue = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
if (ctValue != null) {
|
||||
if (ctValue.startsWith("application/x-www-form-urlencoded")) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "invalidContentTypeInRequest", ctValue, getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
if (isBlank(ctValue)) {
|
||||
/*
|
||||
* If the client didn't send a content type, try to guess
|
||||
*/
|
||||
requestReader = theRequest.getServletRequest().getReader();
|
||||
String body = IOUtils.toString(requestReader);
|
||||
encoding = MethodUtil.detectEncodingNoDefault(body);
|
||||
if (encoding == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "noContentTypeInRequest", getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
} else {
|
||||
requestReader = new StringReader(body);
|
||||
}
|
||||
} else {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "invalidContentTypeInRequest", ctValue, getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
} else {
|
||||
requestReader = theRequest.getServletRequest().getReader();
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
|
||||
Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType();
|
||||
IBaseResource retVal;
|
||||
if (wantedResourceType != null) {
|
||||
retVal = parser.parseResource(wantedResourceType, requestReader);
|
||||
} else {
|
||||
retVal = parser.parseResource(requestReader);
|
||||
}
|
||||
|
||||
retVal.setId(theRequest.getId());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract Set<RequestTypeEnum> provideAllowableRequestTypes();
|
||||
|
||||
/**
|
||||
* Subclasses may override if the incoming request should not contain a resource
|
||||
*/
|
||||
protected boolean requestContainsResource() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override to provide a specific resource type that this method wants as a parameter
|
||||
*/
|
||||
protected Class<? extends IBaseResource> requestContainsResourceType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, Request theRequest)
|
||||
throws IOException {
|
||||
theResponse.setStatus(theE.getStatusCode());
|
||||
|
|
|
@ -20,12 +20,9 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
|
@ -34,14 +31,12 @@ import ca.uhn.fhir.model.api.IResource;
|
|||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private int myResourceParameterIndex;
|
||||
private String myResourceName;
|
||||
private boolean myBinary;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
private Integer myIdParamIndex;
|
||||
|
||||
|
@ -64,10 +59,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
|||
providerResourceType = ((IResourceProvider) theProvider).getResourceType();
|
||||
}
|
||||
|
||||
if (IBaseBinary.class.isAssignableFrom(providerResourceType)) {
|
||||
myBinary = true;
|
||||
}
|
||||
|
||||
myResourceType = resourceParameter.getResourceType();
|
||||
if (Modifier.isAbstract(myResourceType.getModifiers())) {
|
||||
myResourceType = providerResourceType;
|
||||
|
@ -88,27 +79,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends IBaseResource> requestContainsResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
|
||||
if (myBinary) {
|
||||
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
byte[] contents = IOUtils.toByteArray(theRequest.getServletRequest().getInputStream());
|
||||
|
||||
IBaseBinary binary = (IBaseBinary) getContext().getResourceDefinition("Binary").newInstance();
|
||||
binary.setContentType(ct);
|
||||
binary.setContent(contents);
|
||||
|
||||
return binary;
|
||||
} else {
|
||||
return super.parseIncomingServerResource(theRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
if (myIdParamIndex != null) {
|
||||
|
|
|
@ -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.Reader;
|
||||
|
@ -37,20 +37,18 @@ import java.util.Set;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
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.api.Include;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
@ -244,14 +242,14 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
Object requestObject = parseRequestObject(theRequest);
|
||||
byte[] requestContents = loadRequestContents(theRequest);
|
||||
|
||||
// Method params
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
IParameter param = getParameters().get(i);
|
||||
if (param != null) {
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, requestObject);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, requestContents, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,18 +390,6 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @throws IOException
|
||||
* Subclasses may throw this in the event of an IO exception
|
||||
*/
|
||||
protected Object parseRequestObject(Request theRequest) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setResourceName(String theResourceName) {
|
||||
myResourceName = theResourceName;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class ConditionalParamBinder implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
if (myOperationType == RestfulOperationTypeEnum.CREATE) {
|
||||
String retVal = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_EXIST);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class CountParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||
if (sinceParams != null) {
|
||||
if (sinceParams.length > 0) {
|
||||
|
|
|
@ -20,13 +20,10 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
|
@ -56,18 +53,6 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
|
|||
return Collections.singleton(RequestTypeEnum.POST);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
|
||||
IBaseResource retVal = super.parseIncomingServerResource(theRequest);
|
||||
|
||||
if (theRequest.getId() != null && theRequest.getId().hasIdPart()) {
|
||||
retVal.setId(theRequest.getId());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {
|
||||
FhirContext context = getContext();
|
||||
|
|
|
@ -81,11 +81,6 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestContainsResource() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowVoidReturnType() {
|
||||
return true;
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DynamicSearchParameter implements IParameter {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
SearchParameterMap retVal = new SearchParameterMap();
|
||||
|
||||
for (String next : theRequest.getParameters().keySet()) {
|
||||
|
|
|
@ -45,9 +45,10 @@ public interface IParameter {
|
|||
* The incoming request object
|
||||
* @param theRequestContents
|
||||
* The parsed contents of the incoming request. E.g. if the request was an HTTP POST with a resource in the body, this argument would contain the parsed {@link IResource} instance.
|
||||
* @param theMethodBinding TODO
|
||||
* @return Returns the argument object as it will be passed to the {@link IResourceProvider} method.
|
||||
*/
|
||||
Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException;
|
||||
Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
|
@ -25,10 +24,10 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
@ -76,6 +75,7 @@ import ca.uhn.fhir.rest.param.ReferenceAndListParam;
|
|||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TransactionParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||
|
@ -411,7 +411,7 @@ public class MethodUtil {
|
|||
if (!IResource.class.isAssignableFrom(parameterType)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName() + " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
||||
}
|
||||
param = new ResourceParameter((Class<? extends IResource>) parameterType);
|
||||
param = new ResourceParameter((Class<? extends IResource>) parameterType, theProvider);
|
||||
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
||||
param = new NullParameter();
|
||||
} else if (nextAnnotation instanceof ServerBase) {
|
||||
|
@ -423,12 +423,12 @@ public class MethodUtil {
|
|||
} else if (nextAnnotation instanceof Sort) {
|
||||
param = new SortParameter();
|
||||
} else if (nextAnnotation instanceof TransactionParam) {
|
||||
param = new TransactionParamBinder(theContext);
|
||||
param = new TransactionParameter(theContext);
|
||||
} else if (nextAnnotation instanceof ConditionalUrlParam) {
|
||||
param = new ConditionalParamBinder(theRestfulOperationTypeEnum);
|
||||
} else if (nextAnnotation instanceof OperationParam) {
|
||||
Operation op = theMethod.getAnnotation(Operation.class);
|
||||
param = new OperationParamBinder(op.name(), (OperationParam) nextAnnotation);
|
||||
param = new OperationParameter(op.name(), (OperationParam) nextAnnotation);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class NarrativeModeParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String val = theRequest.getServletRequest().getParameter(Constants.PARAM_NARRATIVE);
|
||||
if (val != null) {
|
||||
try {
|
||||
|
|
|
@ -39,7 +39,7 @@ class NullParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
// nothing
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,8 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
@ -46,13 +43,10 @@ import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
|||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
|
@ -196,20 +190,6 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseRequestObject(Request theRequest) throws IOException {
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
BufferedReader requestReader = theRequest.getServletRequest().getReader();
|
||||
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<? extends IBaseResource> wantedResourceType = getContext().getResourceDefinition("Parameters").getImplementingClass();
|
||||
return parser.parseResource(wantedResourceType, requestReader);
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theOperationName, IBaseParameters theInput,
|
||||
boolean theUseHttpGet) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
|
|
@ -44,11 +44,14 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
|||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
|
||||
class OperationParamBinder implements IParameter {
|
||||
class OperationParameter implements IParameter {
|
||||
|
||||
private final String myName;
|
||||
private Class<?> myParameterType;
|
||||
|
@ -56,7 +59,7 @@ class OperationParamBinder implements IParameter {
|
|||
private Class<? extends Collection> myInnerCollectionType;
|
||||
private final String myOperationName;
|
||||
|
||||
OperationParamBinder(String theOperationName, OperationParam theAnnotation) {
|
||||
OperationParameter(String theOperationName, OperationParam theAnnotation) {
|
||||
myOperationName = theOperationName;
|
||||
myName = theAnnotation.name();
|
||||
}
|
||||
|
@ -109,7 +112,7 @@ class OperationParamBinder implements IParameter {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
List<Object> matchingParamValues = new ArrayList<Object>();
|
||||
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
|
@ -125,16 +128,21 @@ class OperationParamBinder implements IParameter {
|
|||
}
|
||||
} else {
|
||||
HapiLocalizer localizer = theRequest.getServer().getFhirContext().getLocalizer();
|
||||
String msg = localizer.getMessage(OperationParamBinder.class, "urlParamNotPrimitive", myOperationName, myName);
|
||||
String msg = localizer.getMessage(OperationParameter.class, "urlParamNotPrimitive", myOperationName, myName);
|
||||
throw new MethodNotAllowedException(msg, RequestTypeEnum.POST);
|
||||
}
|
||||
}
|
||||
} else if (theRequestContents == null) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
IBaseResource requestContents = (IBaseResource) theRequestContents;
|
||||
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<? extends IBaseResource> wantedResourceType = theMethodBinding.getContext().getResourceDefinition("Parameters").getImplementingClass();
|
||||
IBaseResource requestContents = ResourceParameter.loadResourceFromRequest(theRequest, theRequestContents, theMethodBinding, wantedResourceType);
|
||||
|
||||
RuntimeResourceDefinition def = ctx.getResourceDefinition(requestContents);
|
||||
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
|
@ -43,7 +43,7 @@ class ServerBaseParamBinder implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getFhirServerBase();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class ServletRequestParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getServletRequest();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class ServletResponseParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getServletResponse();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class SinceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||
if (sinceParams != null) {
|
||||
if (sinceParams.length > 0) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class SortParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT)) {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_ASC)) {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_DESC)) {
|
||||
|
|
|
@ -20,9 +20,8 @@ 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.lang.reflect.Method;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
@ -44,7 +43,8 @@ import ca.uhn.fhir.rest.annotation.Transaction;
|
|||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.TransactionParamBinder.ParamStyle;
|
||||
import ca.uhn.fhir.rest.param.TransactionParameter;
|
||||
import ca.uhn.fhir.rest.param.TransactionParameter.ParamStyle;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -60,13 +60,13 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
myTransactionParamIndex = -1;
|
||||
int index = 0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof TransactionParamBinder) {
|
||||
if (next instanceof TransactionParameter) {
|
||||
if (myTransactionParamIndex != -1) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " has multiple parameters annotated with the @" + TransactionParam.class + " annotation, exactly one is required for @" + Transaction.class
|
||||
+ " methods");
|
||||
}
|
||||
myTransactionParamIndex = index;
|
||||
myTransactionParamStyle = ((TransactionParamBinder) next).getParamStyle();
|
||||
myTransactionParamStyle = ((TransactionParameter) next).getParamStyle();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
@ -182,11 +182,6 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseRequestObject(Request theRequest) throws IOException {
|
||||
return null; // This is parsed in TransactionParamBinder
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createTransactionInvocation(Bundle theBundle, FhirContext theContext) {
|
||||
return new HttpPostClientInvocation(theContext, theBundle);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
|
@ -129,7 +130,7 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
List<QualifiedParamList> paramList = new ArrayList<QualifiedParamList>();
|
||||
String name = getName();
|
||||
|
|
|
@ -20,26 +20,69 @@ package ca.uhn.fhir.rest.param;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class ResourceParameter implements IParameter {
|
||||
|
||||
private Class<? extends IResource> myResourceType;
|
||||
private boolean myBinary;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
|
||||
public ResourceParameter(Class<? extends IResource> theParameterType) {
|
||||
public ResourceParameter(Class<? extends IResource> theParameterType, Object theProvider) {
|
||||
myResourceType = theParameterType;
|
||||
myBinary = IBaseBinary.class.isAssignableFrom(theParameterType);
|
||||
|
||||
Class<? extends IBaseResource> providerResourceType = null;
|
||||
if (theProvider instanceof IResourceProvider) {
|
||||
providerResourceType = ((IResourceProvider) theProvider).getResourceType();
|
||||
}
|
||||
|
||||
if (Modifier.isAbstract(myResourceType.getModifiers()) && providerResourceType != null) {
|
||||
myResourceType = providerResourceType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// ignore for now
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,18 +92,110 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
IResource resource = (IResource) theRequestContents;
|
||||
return resource;
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
if (myBinary) {
|
||||
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
IBaseBinary binary = (IBaseBinary) ctx.getResourceDefinition("Binary").newInstance();
|
||||
binary.setContentType(ct);
|
||||
binary.setContent(theRequestContents);
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return myResourceType;
|
||||
IBaseResource retVal = loadResourceFromRequest(theRequest, theRequestContents, theMethodBinding, myResourceType);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// ignore for now
|
||||
public static IBaseResource loadResourceFromRequest(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
|
||||
final Charset charset = determineRequestCharset(theRequest);
|
||||
Reader requestReader = createRequestReader(theRequestContents, charset);
|
||||
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncodingNoDefault(theRequest);
|
||||
if (encoding == null) {
|
||||
String ctValue = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
if (ctValue != null) {
|
||||
if (ctValue.startsWith("application/x-www-form-urlencoded")) {
|
||||
String msg = theRequest.getServer().getFhirContext().getLocalizer().getMessage(ResourceParameter.class, "invalidContentTypeInRequest", ctValue, theMethodBinding.getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
if (isBlank(ctValue)) {
|
||||
/*
|
||||
* If the client didn't send a content type, try to guess
|
||||
*/
|
||||
String body;
|
||||
try {
|
||||
body = IOUtils.toString(requestReader);
|
||||
} catch (IOException e) {
|
||||
// This shouldn't happen since we're reading from a byte array..
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
encoding = MethodUtil.detectEncodingNoDefault(body);
|
||||
if (encoding == null) {
|
||||
String msg = ctx.getLocalizer().getMessage(ResourceParameter.class, "noContentTypeInRequest", theMethodBinding.getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
} else {
|
||||
requestReader = new InputStreamReader(new ByteArrayInputStream(theRequestContents), charset);
|
||||
}
|
||||
} else {
|
||||
String msg = ctx.getLocalizer().getMessage(ResourceParameter.class, "invalidContentTypeInRequest", ctValue, theMethodBinding.getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(ctx);
|
||||
|
||||
IBaseResource retVal;
|
||||
if (theResourceType != null) {
|
||||
retVal = parser.parseResource(theResourceType, requestReader);
|
||||
} else {
|
||||
retVal = parser.parseResource(requestReader);
|
||||
}
|
||||
|
||||
if (theRequest.getId() != null && theRequest.getId().hasIdPart()) {
|
||||
retVal.setId(theRequest.getId());
|
||||
}
|
||||
|
||||
if (theRequest.getServer().getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
TagList tagList = new TagList();
|
||||
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
|
||||
String nextTagComplete = enumeration.nextElement();
|
||||
MethodUtil.parseTagValue(tagList, nextTagComplete);
|
||||
}
|
||||
if (tagList.isEmpty() == false) {
|
||||
((IResource)retVal).getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static Reader createRequestReader(byte[] theRequestContents, Charset charset) {
|
||||
Reader requestReader = new InputStreamReader(new ByteArrayInputStream(theRequestContents), charset);
|
||||
return requestReader;
|
||||
}
|
||||
|
||||
static Reader createRequestReader(Request theRequest, byte[] theRequestContents) {
|
||||
return createRequestReader(theRequestContents, determineRequestCharset(theRequest));
|
||||
}
|
||||
|
||||
static Charset determineRequestCharset(Request theRequest) {
|
||||
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
||||
Charset charset = null;
|
||||
if (isNotBlank(ct)) {
|
||||
ContentType parsedCt = ContentType.parse(ct);
|
||||
charset = parsedCt.getCharset();
|
||||
}
|
||||
if (charset == null) {
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
return charset;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -20,8 +20,7 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
@ -39,18 +38,21 @@ import ca.uhn.fhir.model.api.BundleEntry;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
class TransactionParamBinder implements IParameter {
|
||||
public class TransactionParameter implements IParameter {
|
||||
|
||||
private FhirContext myContext;
|
||||
private ParamStyle myParamStyle;
|
||||
private Class<? extends IBaseResource> myResourceBundleType;
|
||||
|
||||
public TransactionParamBinder(FhirContext theContext) {
|
||||
public TransactionParameter(FhirContext theContext) {
|
||||
myContext = theContext;
|
||||
}
|
||||
|
||||
|
@ -96,19 +98,14 @@ class TransactionParamBinder implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
// TODO: don't use a default encoding, just fail!
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
|
||||
IParser parser = encoding.newParser(myContext);
|
||||
|
||||
BufferedReader reader;
|
||||
try {
|
||||
reader = theRequest.getServletRequest().getReader();
|
||||
} catch (IOException e) {
|
||||
throw new InternalErrorException("Failed to read incoming payload", e);
|
||||
}
|
||||
Reader reader = ResourceParameter.createRequestReader(theRequest, theRequestContents);
|
||||
|
||||
switch (myParamStyle) {
|
||||
case DSTU1_BUNDLE: {
|
||||
|
@ -137,7 +134,7 @@ class TransactionParamBinder implements IParameter {
|
|||
return myParamStyle;
|
||||
}
|
||||
|
||||
enum ParamStyle {
|
||||
public enum ParamStyle {
|
||||
/** Old style bundle (defined in hapi-fhir-base) */
|
||||
DSTU1_BUNDLE,
|
||||
/** New style bundle (defined in hapi-fhir-structures-* as a resource definition itself */
|
|
@ -13,11 +13,9 @@ ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable
|
|||
ca.uhn.fhir.rest.client.RestfulClientFactory.failedToRetrieveConformance=Failed to retrieve the server's metadata statement during client initialization. URL used was: {0}
|
||||
ca.uhn.fhir.rest.client.RestfulClientFactory.wrongVersionInConformance=The server at base URL "{0}" returned a conformance statement indicating that it supports FHIR version "{1}" which corresponds to {2}, but this client is configured to use {3} (via the FhirContext).
|
||||
|
||||
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBinding.noContentTypeInRequest=No Content-Type header was provided in the request. This is required for "{0}" operation
|
||||
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBinding.invalidContentTypeInRequest=Incorrect Content-Type header value of "{0}" was provided in the request. A FHIR Content-Type is required for "{1}" operation
|
||||
|
||||
ca.uhn.fhir.rest.method.OperationMethodBinding.methodNotSupported=HTTP Method {0} is not allowed for this operation. Allowed method(s): {1}
|
||||
ca.uhn.fhir.rest.method.OperationParamBinder.urlParamNotPrimitive=Can not invoke operation {0} using HTTP GET because parameter {1} is not a primitive datatype
|
||||
ca.uhn.fhir.rest.method.OperationParameter.urlParamNotPrimitive=Can not invoke operation {0} using HTTP GET because parameter {1} is not a primitive datatype
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid {2} parameter value: "{0}". Valid values are: {1}
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.orIncludeInRequest='OR' query parameters (values containing ',') are not supported in _include parameters
|
||||
|
||||
|
@ -25,6 +23,9 @@ ca.uhn.fhir.rest.method.SearchMethodBinding.invalidSpecialParamName=Method [{0}]
|
|||
ca.uhn.fhir.rest.method.SearchMethodBinding.idWithoutCompartment=Method [{0}] in provider [{1}] has an @IdParam parameter. This is only allowable for compartment search (e.g. @Search(compartment="foo") )
|
||||
ca.uhn.fhir.rest.method.SearchMethodBinding.idNullForCompartmentSearch=ID parameter can not be null or empty for compartment search
|
||||
|
||||
ca.uhn.fhir.rest.param.ResourceParameter.invalidContentTypeInRequest=Incorrect Content-Type header value of "{0}" was provided in the request. A FHIR Content-Type is required for "{1}" operation
|
||||
ca.uhn.fhir.rest.param.ResourceParameter.noContentTypeInRequest=No Content-Type header was provided in the request. This is required for "{0}" operation
|
||||
|
||||
ca.uhn.fhir.parser.ParserState.wrongResourceTypeFound=Incorrect resource type found, expected "{0}" but found "{1}"
|
||||
|
||||
ca.uhn.fhir.rest.server.RestfulServer.getPagesNonHttpGet=Requests for _getpages must use HTTP GET
|
||||
|
|
|
@ -128,3 +128,4 @@ local.properties
|
|||
.texlipse
|
||||
|
||||
/target/
|
||||
/target/
|
||||
|
|
|
@ -27,7 +27,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class ClientServerValidationTestDstu {
|
||||
|
@ -70,7 +70,7 @@ public class ClientServerValidationTestDstu {
|
|||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
// don't load the conformance until the first time the client is actually used
|
||||
|
@ -98,11 +98,11 @@ public class ClientServerValidationTestDstu {
|
|||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
try {
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/1"));
|
||||
fail();
|
||||
} catch (FhirClientConnectionException e) {
|
||||
} catch (FhirClientInappropriateForServerException e) {
|
||||
assertThat(e.toString(), containsString("The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.4.0\" which corresponds to DSTU2, but this client is configured to use DSTU1 (via the FhirContext)"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class BaseDateTimeDtTest {
|
|||
*/
|
||||
ourDefaultLocale = Locale.getDefault();
|
||||
|
||||
Locale[] available = Locale.getAvailableLocales();
|
||||
Locale[] available = { Locale.CANADA, Locale.GERMANY, Locale.TAIWAN };
|
||||
Locale newLocale = available[(int) (Math.random() * available.length)];
|
||||
Locale.setDefault(newLocale);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ca.uhn.fhir.validation;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
|
@ -15,7 +14,6 @@ import org.hl7.fhir.instance.model.StructureDefinition;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.utils.WorkerContext;
|
||||
import org.hl7.fhir.instance.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
|
@ -28,7 +26,6 @@ public class InstanceValidator {
|
|||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(InstanceValidator.class);
|
||||
|
||||
private FhirContext myCtx;
|
||||
|
||||
private DocumentBuilderFactory myDocBuilderFactory;
|
||||
|
||||
InstanceValidator(FhirContext theContext) {
|
||||
|
|
Loading…
Reference in New Issue