package ca.uhn.fhir.jaxrs.server.util;
/*
* #%L
* HAPI FHIR JAX-RS Server
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.model.IdType;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.param.ResourceParameter;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IRestfulResponse;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.UrlUtil;
/**
* The JaxRsRequest is a jax-rs specific implementation of the RequestDetails.
*
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
*/
public class JaxRsRequest extends RequestDetails {
/**
* An implementation of the builder pattern for the JaxRsRequest
*/
public static class Builder {
private String myResource;
private AbstractJaxRsProvider myServer;
private RequestTypeEnum myRequestType;
private RestOperationTypeEnum myRestOperation;
private String myId;
private String myVersion;
private String myCompartment;
private String myRequestUrl;
private final String myResourceName;
/**
* Utility Constructor
* @param theServer the server
* @param theRequestType the request type
* @param theRestOperation the rest operation
* @param theRequestUrl
*/
public Builder(AbstractJaxRsProvider theServer, RequestTypeEnum theRequestType,
RestOperationTypeEnum theRestOperation, String theRequestUrl, String theResourceName) {
this.myServer = theServer;
this.myRequestType = theRequestType;
this.myRestOperation = theRestOperation;
this.myRequestUrl = theRequestUrl;
this.myResourceName = theResourceName;
}
/**
* Set the resource
* @param resource the body contents of an http method
* @return the builder
*/
public Builder resource(String resource) {
this.myResource = resource;
return this;
}
/**
* Set the id
* @param id the resource id
* @return the builder
*/
public Builder id(String id) {
this.myId = id;
return this;
}
/**
* Set the id version
* @param version the version of the resource
* @return the builder
*/
public Builder version(String version) {
this.myVersion = version;
return this;
}
/**
* Set the compartment
* @param compartment the compartment
* @return the builder
*/
public Builder compartment(String compartment) {
this.myCompartment = compartment;
return this;
}
/**
* Create the jax-rs request
* @return the jax-rs request
*/
public JaxRsRequest build() {
JaxRsRequest result = new JaxRsRequest(myServer, myResource, myRequestType, myRestOperation);
if ((StringUtils.isNotBlank(myVersion) || StringUtils.isNotBlank(myCompartment))
&& StringUtils.isBlank(myId)) {
throw new InvalidRequestException("Don't know how to handle request path: "
+ myServer.getUriInfo().getRequestUri().toASCIIString());
}
FhirVersionEnum fhirContextVersion = myServer.getFhirContext().getVersion().getVersion();
if (StringUtils.isNotBlank(myVersion)) {
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion) || FhirVersionEnum.DSTU2_HL7ORG.equals(fhirContextVersion)) {
result.setId(
new IdType(myServer.getBaseForRequest(), UrlUtil.unescape(myId), UrlUtil.unescape(myVersion)));
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
result.setId(
new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId), UrlUtil.unescape(myVersion)));
}
} else if (StringUtils.isNotBlank(myId)) {
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion) || FhirVersionEnum.DSTU2_HL7ORG.equals(fhirContextVersion)) {
result.setId(new IdType(myServer.getBaseForRequest(), UrlUtil.unescape(myId)));
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
result.setId(new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId)));
}
}
if (myRestOperation == RestOperationTypeEnum.UPDATE) {
String contentLocation = result.getHeader(Constants.HEADER_CONTENT_LOCATION);
if (contentLocation != null) {
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion) || FhirVersionEnum.DSTU2_HL7ORG.equals(fhirContextVersion)) {
result.setId(new IdType(contentLocation));
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
result.setId(new IdDt(contentLocation));
}
}
}
result.setCompartmentName(myCompartment);
result.setCompleteUrl(myRequestUrl);
result.setResourceName(myResourceName);
return result;
}
}
private String myResourceString;
private HttpHeaders myHeaders;
private AbstractJaxRsProvider myServer;
/**
* Utility Constructor
* @param server the server
* @param resourceString the resource body
* @param requestType the request type
* @param restOperation the operation type
*/
public JaxRsRequest(AbstractJaxRsProvider server, String resourceString, RequestTypeEnum requestType,
RestOperationTypeEnum restOperation) {
this.myHeaders = server.getHeaders();
this.myResourceString = resourceString;
this.setRestOperationType(restOperation);
setServer(server);
setFhirServerBase(server.getBaseForServer());
setParameters(server.getParameters());
setRequestType(requestType);
}
@Override
public AbstractJaxRsProvider getServer() {
return myServer;
}
/**
* Set the server
* @param theServer the server to set
*/
public void setServer(AbstractJaxRsProvider theServer) {
this.myServer = theServer;
}
@Override
public String getHeader(String headerKey) {
List<String> requestHeader = getHeaders(headerKey);
return requestHeader.isEmpty() ? null : requestHeader.get(0);
}
@Override
public List<String> getHeaders(String name) {
List<String> requestHeader = myHeaders.getRequestHeader(name);
return requestHeader == null ? Collections.<String> emptyList() : requestHeader;
}
@Override
public String getServerBaseForRequest() {
return getServer().getServerAddressStrategy().determineServerBase(null, null);
}
@Override
protected byte[] getByteStreamRequestContents() {
return StringUtils.defaultString(myResourceString, "")
.getBytes(ResourceParameter.determineRequestCharset(this));
}
@Override
public IRestfulResponse getResponse() {
if (super.getResponse() == null) {
setResponse(new JaxRsResponse(this));
}
return super.getResponse();
}
@Override
public Reader getReader() throws IOException {
// not yet implemented
throw new UnsupportedOperationException();
}
@Override
public InputStream getInputStream() {
// not yet implemented
throw new UnsupportedOperationException();
}
@Override
public Charset getCharset() {
String charset = null;
if(myHeaders.getMediaType() != null && myHeaders.getMediaType().getParameters() != null) {
charset = myHeaders.getMediaType().getParameters().get(MediaType.CHARSET_PARAMETER);
}
if(charset != null) {
return Charset.forName(charset);
} else {
return null;
}
}
}