Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2016-08-05 12:37:06 -04:00
commit a3f4864bd6
34 changed files with 3089 additions and 901 deletions

View File

@ -53,4 +53,14 @@ public class BasicSecurityInterceptor extends InterceptorAdapter
}
//END SNIPPET: basicAuthInterceptor
public void basicAuthInterceptorRealm() {
//START SNIPPET: basicAuthInterceptorRealm
AuthenticationException ex = new AuthenticationException();
ex.addAuthenticateHeaderForRealm("myRealm");
throw ex;
//END SNIPPET: basicAuthInterceptorRealm
}
}

View File

@ -36,6 +36,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@ -1522,6 +1523,15 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
private void writeExceptionToResponse(HttpServletResponse theResponse, BaseServerResponseException theException) throws IOException {
theResponse.setStatus(theException.getStatusCode());
addHeadersToResponse(theResponse);
if (theException.hasResponseHeaders()) {
for (Entry<String, List<String>> nextEntry : theException.getResponseHeaders().entrySet()) {
for (String nextValue : nextEntry.getValue()) {
if (isNotBlank(nextValue)) {
theResponse.addHeader(nextEntry.getKey(), nextValue);
}
}
}
}
theResponse.setContentType("text/plain");
theResponse.setCharacterEncoding("UTF-8");
theResponse.getWriter().write(theException.getMessage());

View File

@ -44,5 +44,16 @@ public class AuthenticationException extends BaseServerResponseException {
public AuthenticationException(String theMessage, Throwable theCause) {
super(STATUS_CODE, theMessage, theCause);
}
/**
* Adds a <code>WWW-Authenticate</code> header to the response, of the form:<br/>
* <code>WWW-Authenticate: Basic realm="theRealm"</code>
*
* @return Returns a reference to <code>this</code> for easy method chaining
*/
public AuthenticationException addAuthenticateHeaderForRealm(String theRealm) {
addResponseHeader("WWW-Authenticate", "Basic realm=\"" + theRealm + "\"");
return this;
}
}

View File

@ -1,12 +1,14 @@
package ca.uhn.fhir.rest.server.exceptions;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import ca.uhn.fhir.rest.server.IResourceProvider;
@ -70,13 +72,10 @@ public abstract class BaseServerResponseException extends RuntimeException {
private List<String> myAdditionalMessages = null;
private IBaseOperationOutcome myBaseOperationOutcome;
private String myResponseBody;
private Map<String, List<String>> myResponseHeaders;
private String myResponseMimeType;
private int myStatusCode;
public static void main (String[] args) {
BaseServerResponseException.class.getName();
}
/**
* Constructor
*
@ -90,7 +89,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
myStatusCode = theStatusCode;
myBaseOperationOutcome = null;
}
/**
* Constructor
*
@ -107,7 +106,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
myAdditionalMessages = Arrays.asList(Arrays.copyOfRange(theMessages, 1, theMessages.length, String[].class));
}
}
/**
* Constructor
*
@ -188,15 +187,26 @@ public abstract class BaseServerResponseException extends RuntimeException {
myBaseOperationOutcome = theBaseOperationOutcome;
}
public List<String> getAdditionalMessages() {
return myAdditionalMessages;
/**
* Add a header which will be added to any responses
*
* @param theName The header name
* @param theValue The header value
* @return Returns a reference to <code>this</code> for easy method chaining
* @since 2.0
*/
public BaseServerResponseException addResponseHeader(String theName, String theValue) {
Validate.notBlank(theName, "theName must not be null or empty");
Validate.notBlank(theValue, "theValue must not be null or empty");
if (getResponseHeaders().containsKey(theName) == false) {
getResponseHeaders().put(theName, new ArrayList<String>());
}
getResponseHeaders().get(theName).add(theValue);
return this;
}
/**
* Returns the HTTP headers associated with this exception.
*/
public Map<String, String[]> getAssociatedHeaders() {
return Collections.emptyMap();
public List<String> getAdditionalMessages() {
return myAdditionalMessages;
}
/**
@ -216,6 +226,21 @@ public abstract class BaseServerResponseException extends RuntimeException {
return myResponseBody;
}
/**
* Returns a map containing any headers which should be added to the outgoing
* response. This methos creates the map if none exists, so it will never
* return <code>null</code>
*
* @since 2.0 (note that this method existed in previous versions of HAPI but the method
* signature has been changed from <code>Map&lt;String, String[]&gt;</code> to <code>Map&lt;String, List&lt;String&gt;&gt;</code>
*/
public Map<String, List<String>> getResponseHeaders() {
if (myResponseHeaders == null) {
myResponseHeaders = new HashMap<String, List<String>>();
}
return myResponseHeaders;
}
/**
* In a RESTful client, this method will be populated with the HTTP status code that was returned with the HTTP response.
* <p>
@ -233,6 +258,16 @@ public abstract class BaseServerResponseException extends RuntimeException {
return myStatusCode;
}
/**
* Does the exception have any headers which should be added to the outgoing response?
*
* @see #getResponseHeaders()
* @since 2.0
*/
public boolean hasResponseHeaders() {
return myResponseHeaders != null && myResponseHeaders.isEmpty() == false;
}
/**
* Sets the BaseOperationOutcome resource associated with this exception. In server implementations, this is the OperartionOutcome resource to include with the HTTP response. In client
* implementations you should not call this method.

View File

@ -1,8 +1,6 @@
package ca.uhn.fhir.rest.server.exceptions;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
@ -20,7 +18,7 @@ import ca.uhn.fhir.rest.server.Constants;
* 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
* 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,
@ -48,11 +46,11 @@ public class MethodNotAllowedException extends BaseServerResponseException {
* Constructor
*
* @param theMessage
* The message
* The message
* @param theOperationOutcome
* The OperationOutcome resource to return to the client
* The OperationOutcome resource to return to the client
* @param theAllowedMethods
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
*/
public MethodNotAllowedException(String theMessage, IBaseOperationOutcome theOperationOutcome, RequestTypeEnum... theAllowedMethods) {
super(STATUS_CODE, theMessage, theOperationOutcome);
@ -63,9 +61,9 @@ public class MethodNotAllowedException extends BaseServerResponseException {
* Constructor
*
* @param theMessage
* The message
* The message
* @param theAllowedMethods
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
* A list of allowed methods (see {@link #setAllowedMethods(RequestTypeEnum...)} )
*/
public MethodNotAllowedException(String theMessage, RequestTypeEnum... theAllowedMethods) {
super(STATUS_CODE, theMessage);
@ -76,9 +74,9 @@ public class MethodNotAllowedException extends BaseServerResponseException {
* Constructor
*
* @param theMessage
* The message
* The message
* @param theOperationOutcome
* The OperationOutcome resource to return to the client
* The OperationOutcome resource to return to the client
*/
public MethodNotAllowedException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
super(STATUS_CODE, theMessage, theOperationOutcome);
@ -88,7 +86,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
* Constructor
*
* @param theMessage
* The message
* The message
*/
public MethodNotAllowedException(String theMessage) {
super(STATUS_CODE, theMessage);
@ -101,22 +99,6 @@ public class MethodNotAllowedException extends BaseServerResponseException {
return myAllowedMethods;
}
@Override
public Map<String, String[]> getAssociatedHeaders() {
if (myAllowedMethods != null && myAllowedMethods.size() > 0) {
StringBuilder b = new StringBuilder();
for (RequestTypeEnum next : myAllowedMethods) {
if (b.length() > 0) {
b.append(',');
}
b.append(next.name());
}
return Collections.singletonMap(Constants.HEADER_ALLOW, new String[] { b.toString() });
} else {
return super.getAssociatedHeaders();
}
}
/**
* Specifies the list of allowed HTTP methods (GET, POST, etc). This is provided in an <code>Allow</code> header, as required by the HTTP specification (RFC 2616).
*/
@ -129,6 +111,7 @@ public class MethodNotAllowedException extends BaseServerResponseException {
myAllowedMethods.add(next);
}
}
updateAllowHeader();
}
/**
@ -136,6 +119,20 @@ public class MethodNotAllowedException extends BaseServerResponseException {
*/
public void setAllowedMethods(Set<RequestTypeEnum> theAllowedMethods) {
myAllowedMethods = theAllowedMethods;
updateAllowHeader();
}
private void updateAllowHeader() {
getResponseHeaders().remove(Constants.HEADER_ALLOW);
StringBuilder b = new StringBuilder();
for (RequestTypeEnum next : myAllowedMethods) {
if (b.length() > 0) {
b.append(',');
}
b.append(next.name());
}
addResponseHeader(Constants.HEADER_ALLOW, b.toString());
}
}

View File

@ -23,6 +23,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -68,9 +69,9 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
int statusCode = theException.getStatusCode();
// Add headers associated with the specific error code
Map<String, String[]> additional = theException.getAssociatedHeaders();
if (additional != null) {
for (Entry<String, String[]> next : additional.entrySet()) {
if (theException.hasResponseHeaders()) {
Map<String, List<String>> additional = theException.getResponseHeaders();
for (Entry<String, List<String>> next : additional.entrySet()) {
if (isNotBlank(next.getKey()) && next.getValue() != null) {
String nextKey = next.getKey();
for (String nextValue : next.getValue()) {
@ -79,7 +80,7 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
}
}
}
String statusMessage = null;
if (theException instanceof UnclassifiedServerFailureException) {
String sm = theException.getMessage();
@ -89,12 +90,7 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
}
return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, statusMessage, false, false);
// theResponse.setStatus(statusCode);
// theRequestDetails.getServer().addHeadersToResponse(theResponse);
// theResponse.setContentType("text/plain");
// theResponse.setCharacterEncoding("UTF-8");
// theResponse.getWriter().append(theException.getMessage());
// theResponse.getWriter().close();
}
@Override

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>hapi-fhir</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hapi-fhir-client-okhttp</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR OkHttp Client</name>
<dependencies>
<!-- HAPI DEPENDENCIES -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>2.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- conformance profile -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.4.1</version>
</dependency>
<!-- Unit test dependencies -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<classFolders>
<classFolder>${basedir}/target/classes</classFolder>
<classFolder>${basedir}/../hapi-fhir-base/target/classes</classFolder>
</classFolders>
<sourceFolders>
<sourceFolder>${basedir}/src/main/java</sourceFolder>
<sourceFolder>${basedir}/../hapi-fhir-base/src/main/java</sourceFolder>
</sourceFolders>
<dumpOnExit>true</dumpOnExit>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,183 @@
package ca.uhn.fhir.okhttp.client;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.HttpClientUtil;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import okhttp3.*;
import okhttp3.internal.Version;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import java.util.List;
import java.util.Map;
import static ca.uhn.fhir.okhttp.utils.UrlStringUtils.*;
/**
* A Http Request based on OkHttp. This is an adapter around the class
* {@link OkHttpClient}
*
* @author Matthew Clarke | matthew.clarke@orionhealth.com | Orion Health
*/
public class OkHttpRestfulClient implements IHttpClient {
private OkHttpClient myClient;
private StringBuilder myUrl;
private Map<String, List<String>> myIfNoneExistParams;
private String myIfNoneExistString;
private RequestTypeEnum myRequestType;
private List<Header> myHeaders;
private OkHttpRestfulRequest myRequest;
public OkHttpRestfulClient(OkHttpClient theClient,
StringBuilder theUrl,
Map<String, List<String>> theIfNoneExistParams,
String theIfNoneExistString,
RequestTypeEnum theRequestType,
List<Header> theHeaders) {
myClient = theClient;
myUrl = theUrl;
myIfNoneExistParams = theIfNoneExistParams;
myIfNoneExistString = theIfNoneExistString;
myRequestType = theRequestType;
myHeaders = theHeaders;
}
@Override
public IHttpRequest createByteRequest(FhirContext theContext, String theContents, String theContentType, EncodingEnum theEncoding) {
initBaseRequest(theContext, theEncoding, createPostBody(theContents, theContentType));
return myRequest;
}
private void initBaseRequest(FhirContext theContext, EncodingEnum theEncoding, RequestBody body) {
String sanitisedUrl = withTrailingQuestionMarkRemoved(myUrl.toString());
myRequest = new OkHttpRestfulRequest(myClient, sanitisedUrl, myRequestType, body);
addHeadersToRequest(myRequest, theEncoding, theContext);
}
private RequestBody createPostBody(String theContents, String theContentType) {
return RequestBody.create(MediaType.parse(theContentType), theContents);
}
@Override
public IHttpRequest createParamRequest(FhirContext theContext, Map<String, List<String>> theParams, EncodingEnum theEncoding) {
initBaseRequest(theContext, theEncoding, getFormBodyFromParams(theParams));
return myRequest;
}
private RequestBody getFormBodyFromParams(Map<String, List<String>> queryParams) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (Map.Entry<String, List<String>> paramEntry : queryParams.entrySet()) {
for (String value : paramEntry.getValue()) {
formBuilder.add(paramEntry.getKey(), value);
}
}
return formBuilder.build();
}
@Override
public IHttpRequest createBinaryRequest(FhirContext theContext, IBaseBinary theBinary) {
initBaseRequest(theContext, null, createPostBody(theBinary.getContent(), theBinary.getContentType()));
return myRequest;
}
private RequestBody createPostBody(byte[] theContents, String theContentType) {
return RequestBody.create(MediaType.parse(theContentType), theContents);
}
@Override
public IHttpRequest createGetRequest(FhirContext theContext, EncodingEnum theEncoding) {
initBaseRequest(theContext, theEncoding, null);
return myRequest;
}
private void addHeadersToRequest(OkHttpRestfulRequest theHttpRequest, EncodingEnum theEncoding, FhirContext theContext) {
if (myHeaders != null) {
for (Header next : myHeaders) {
theHttpRequest.addHeader(next.getName(), next.getValue());
}
}
addUserAgentHeader(theHttpRequest, theContext);
addAcceptCharsetHeader(theHttpRequest);
addAcceptHeader(theHttpRequest, theEncoding);
addIfNoneExistHeader(theHttpRequest);
}
private void addUserAgentHeader(OkHttpRestfulRequest theHttpRequest, FhirContext theContext) {
theHttpRequest.addHeader("User-Agent", HttpClientUtil.createUserAgentString(theContext, Version.userAgent()));
}
private void addAcceptCharsetHeader(OkHttpRestfulRequest theHttpRequest) {
theHttpRequest.addHeader("Accept-Charset", "utf-8");
}
private void addAcceptHeader(OkHttpRestfulRequest theHttpRequest, EncodingEnum theEncoding) {
Request.Builder builder = theHttpRequest.getRequest();
if (theEncoding == null) {
builder.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY);
} else if (theEncoding == EncodingEnum.JSON) {
builder.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON);
} else if (theEncoding == EncodingEnum.XML) {
builder.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML);
}
}
private void addIfNoneExistHeader(IHttpRequest result) {
if (myIfNoneExistParams != null) {
addIfNoneExistHeaderFromParams(result, myIfNoneExistParams);
} else if (myIfNoneExistString != null) {
addIfNoneExistHeaderFromString(result, myIfNoneExistString);
}
}
private void addIfNoneExistHeaderFromString(IHttpRequest result, String ifNoneExistString) {
StringBuilder sb = newHeaderBuilder(myUrl);
boolean shouldAddQuestionMark = !hasQuestionMark(sb);
sb.append(shouldAddQuestionMark ? '?' : '&');
sb.append(everythingAfterFirstQuestionMark(ifNoneExistString));
result.addHeader(Constants.HEADER_IF_NONE_EXIST, sb.toString());
}
private void addIfNoneExistHeaderFromParams(IHttpRequest result, Map<String, List<String>> ifNoneExistParams) {
StringBuilder sb = newHeaderBuilder(myUrl);
boolean shouldAddInitialQuestionMark = !hasQuestionMark(sb);
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(ifNoneExistParams, sb, shouldAddInitialQuestionMark);
result.addHeader(Constants.HEADER_IF_NONE_EXIST, sb.toString());
}
public static StringBuilder newHeaderBuilder(StringBuilder baseUrl) {
StringBuilder sb = new StringBuilder(baseUrl);
if (endsWith(baseUrl, '/')) {
deleteLastCharacter(sb);
}
return sb;
}
}

View File

@ -0,0 +1,96 @@
package ca.uhn.fhir.okhttp.client;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.RestfulClientFactory;
import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import okhttp3.OkHttpClient;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.Map;
/**
* A Restful client factory based on OkHttp.
*
* @author Matthew Clarke | matthew.clarke@orionhealth.com | Orion Health
*/
public class OkHttpRestfulClientFactory extends RestfulClientFactory {
private OkHttpClient myNativeClient;
public OkHttpRestfulClientFactory() {
super();
}
public OkHttpRestfulClientFactory(FhirContext theFhirContext) {
super(theFhirContext);
}
@Override
protected IHttpClient getHttpClient(String theServerBase) {
return new OkHttpRestfulClient(getNativeClient(), new StringBuilder(theServerBase), null, null, null, null);
}
@Override
protected void resetHttpClient() {
myNativeClient = null;
}
public synchronized OkHttpClient getNativeClient() {
if (myNativeClient == null) {
myNativeClient = new OkHttpClient();
}
return myNativeClient;
}
@Override
public IHttpClient getHttpClient(StringBuilder theUrl,
Map<String, List<String>> theIfNoneExistParams,
String theIfNoneExistString,
RequestTypeEnum theRequestType,
List<Header> theHeaders) {
return new OkHttpRestfulClient(getNativeClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
}
/**
* Only accepts clients of type {@link OkHttpClient}
*
* @param okHttpClient
*/
@Override
public void setHttpClient(Object okHttpClient) {
myNativeClient = (OkHttpClient) okHttpClient;
}
@Override
public void setProxy(String theHost, Integer thePort) {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(theHost, thePort));
OkHttpClient.Builder builder = getNativeClient().newBuilder().proxy(proxy);
setHttpClient(builder.build());
}
}

View File

@ -0,0 +1,94 @@
package ca.uhn.fhir.okhttp.client;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Adapter for building an OkHttp-specific request.
*
* @author Matthew Clarke | matthew.clarke@orionhealth.com | Orion Health
*/
public class OkHttpRestfulRequest implements IHttpRequest {
private final Request.Builder myRequestBuilder;
private OkHttpClient myClient;
private String myUrl;
private RequestTypeEnum myRequestTypeEnum;
private RequestBody myRequestBody;
public OkHttpRestfulRequest(OkHttpClient theClient, String theUrl, RequestTypeEnum theRequestTypeEnum, RequestBody theRequestBody) {
myClient = theClient;
myUrl = theUrl;
myRequestTypeEnum = theRequestTypeEnum;
myRequestBody = theRequestBody;
myRequestBuilder = new Request.Builder().url(theUrl);
}
public Request.Builder getRequest() {
return myRequestBuilder;
}
@Override
public void addHeader(String theName, String theValue) {
myRequestBuilder.addHeader(theName, theValue);
}
@Override
public IHttpResponse execute() throws IOException {
myRequestBuilder.method(getHttpVerbName(), myRequestBody);
Call call = myClient.newCall(myRequestBuilder.build());
return new OkHttpRestfulResponse(call.execute());
}
@Override
public Map<String, List<String>> getAllHeaders() {
return myRequestBuilder.build().headers().toMultimap();
}
@Override
public String getRequestBodyFromStream() throws IOException {
// returning null to indicate this is not supported, as documented in IHttpRequest's contract
return null;
}
@Override
public String getUri() {
return myUrl;
}
@Override
public String getHttpVerbName() {
return myRequestTypeEnum.name();
}
}

View File

@ -0,0 +1,129 @@
package ca.uhn.fhir.okhttp.client;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import okhttp3.MediaType;
import okhttp3.Response;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.List;
import java.util.Map;
/**
* Wraps an OkHttp {@link Response}
*
* @author Matthew Clarke | matthew.clarke@orionhealth.com | Orion Health
*/
public class OkHttpRestfulResponse implements IHttpResponse {
private Response myResponse;
private boolean myEntityBuffered = false;
private byte[] myEntityBytes;
public OkHttpRestfulResponse(Response theResponse) {
this.myResponse = theResponse;
}
@Override
public int getStatus() {
return myResponse.code();
}
@Override
public Object getResponse() {
return myResponse;
}
@Override
public String getMimeType() {
String contentType = myResponse.header(Constants.HEADER_CONTENT_TYPE);
if (contentType == null) {
return null;
}
MediaType mediaType = MediaType.parse(contentType);
if (mediaType == null) {
return null;
}
return typeAndSubtypeOnly(mediaType).toString();
}
private MediaType typeAndSubtypeOnly(MediaType input) {
return MediaType.parse(input.type() + "/" + input.subtype());
}
@Override
public Map<String, List<String>> getAllHeaders() {
return myResponse.headers().toMultimap();
}
@Override
public String getStatusInfo() {
return myResponse.message();
}
@Override
public Reader createReader() throws IOException {
if (!myEntityBuffered && myResponse.body() == null) {
return new StringReader("");
} else {
return new InputStreamReader(readEntity());
}
}
@Override
public InputStream readEntity() throws IOException {
if (this.myEntityBuffered) {
return new ByteArrayInputStream(myEntityBytes);
} else if (myResponse.body() != null) {
return myResponse.body().byteStream();
} else {
return null;
}
}
@Override
public void close() {
myResponse.close();
}
@Override
public void bufferEntitity() throws IOException {
if (myEntityBuffered) {
return;
}
InputStream responseEntity = readEntity();
if (responseEntity != null) {
myEntityBuffered = true;
try {
myEntityBytes = IOUtils.toByteArray(responseEntity);
} catch (IllegalStateException e) {
throw new InternalErrorException(e);
}
}
}
}

View File

@ -0,0 +1,44 @@
package ca.uhn.fhir.okhttp.utils;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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%
*/
public class UrlStringUtils {
public static String withTrailingQuestionMarkRemoved(String input) {
return input.replaceAll("\\?$", "");
}
public static String everythingAfterFirstQuestionMark(String input) {
return input.substring(input.indexOf('?') + 1);
}
public static boolean hasQuestionMark(StringBuilder sb) {
return sb.indexOf("?") != -1;
}
public static void deleteLastCharacter(StringBuilder sb) {
sb.deleteCharAt(sb.length() - 1);
}
public static boolean endsWith(StringBuilder sb, char c) {
return sb.length() > 0 && sb.charAt(sb.length() - 1) == c;
}
}

View File

@ -0,0 +1,44 @@
package ca.uhn.fhir.okhttp;
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
import okhttp3.OkHttpClient;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
public class OkHttpRestfulClientFactoryTest {
private OkHttpRestfulClientFactory clientFactory;
@Before
public void setUp() {
clientFactory = new OkHttpRestfulClientFactory();
}
@Test
public void testGetNativeClient_noClientSet_returnsADefault() throws Exception {
OkHttpClient actualNativeClient = clientFactory.getNativeClient();
assertNotNull(actualNativeClient);
}
@Test
public void testGetNativeClient_noProxySet_defaultHasNoProxySet() throws Exception {
OkHttpClient actualNativeClient = clientFactory.getNativeClient();
assertEquals(null, actualNativeClient.proxy());
}
@Test
public void testSetHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient.Builder().writeTimeout(5000, TimeUnit.MILLISECONDS).build();
clientFactory.setHttpClient(okHttpClient);
assertSame(okHttpClient, clientFactory.getNativeClient());
}
}

View File

@ -0,0 +1,36 @@
package ca.uhn.fhir.okhttp;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
/**
* Provides server ports
*/
public class RandomServerPortProvider {
private static List<Integer> ourPorts = new ArrayList<Integer>();
public static int findFreePort() {
ServerSocket server;
try {
server = new ServerSocket(0);
int port = server.getLocalPort();
ourPorts.add(port);
server.close();
Thread.sleep(500);
return port;
} catch (IOException e) {
throw new Error(e);
} catch (InterruptedException e) {
throw new Error(e);
}
}
public static List<Integer> list() {
return ourPorts;
}
}

View File

@ -0,0 +1,24 @@
package ca.uhn.fhir.okhttp.client;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
public class OkHttpRestfulClientTest {
@Test
public void testNewHeaderBuilder_urlHasTrailingSlash_shouldTrim() {
StringBuilder headerBuilder = OkHttpRestfulClient.newHeaderBuilder(new StringBuilder("http://localhost/"));
assertThat(headerBuilder.toString(), equalTo("http://localhost"));
}
@Test
public void testNewHeaderBuilder_urlHasNoTrailingSlash_shouldNotTrimLastCharacter() {
StringBuilder headerBuilder = OkHttpRestfulClient.newHeaderBuilder(new StringBuilder("http://example.com"));
assertThat(headerBuilder.toString(), equalTo("http://example.com"));
}
}

View File

@ -0,0 +1,69 @@
<Bundle xmlns="http://hl7.org/fhir">
<id value="487d3669-0e1c-4867-b124-400d1849548d"></id>
<type value="searchset"></type>
<base value="http://localhost:19080/fhir/dstu1"></base>
<link>
<relation value="just trying add link"></relation>
<url value="blarion"></url>
</link>
<link>
<relation value="self"></relation>
<url value="http://localhost:19080/fhir/dstu1/Observation?subject.identifier=puppet|CLONE-AA102"></url>
</link>
<entry>
<link>
<relation value="orionhealth.edit"></relation>
<url value="Observation"></url>
</link>
<resource>
<Observation xmlns="http://hl7.org/fhir">
<id value="0d87f02c-da2c-4551-9ead-2956f0165a4f"></id>
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
</extension>
<code>
<coding>
<system value="http://loinc.org"></system>
<code value="8867-4"></code>
</coding>
</code>
<valueString value="observationValue"></valueString>
<status value="final"></status>
<reliability value="ok"></reliability>
<subject>
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
</subject>
</Observation>
</resource>
</entry>
<entry>
<link>
<relation value="orionhealth.edit"></relation>
<url value="Observation"></url>
</link>
<resource>
<Observation xmlns="http://hl7.org/fhir">
<id value="c54ac0cc-a99f-40aa-9541-c5aa853a2e88"></id>
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
</extension>
<code>
<coding>
<system value="http://loinc.org"></system>
<code value="3141-9"></code>
</coding>
</code>
<valueString value="observationValue"></valueString>
<status value="final"></status>
<reliability value="ok"></reliability>
<subject>
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
</subject>
</Observation>
</resource>
</entry>
</Bundle>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="build/classes"/>
</classpath>

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>hapi-fhir-cobertura</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -1,2 +0,0 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -1,7 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View File

@ -1,4 +0,0 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="java" version="1.7"/>
</faceted-project>

View File

@ -1,410 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- The parent of this project is the deployable POM. This project isn't deployable, but this keeps it before the root pom in the reactor order when building the site. I don't know why this works...
Need to investigate this. -->
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>2.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-cobertura</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Cobertura Test Coverage</name>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
<!-- Use an older version of SLF4j just to make sure we compile correctly against old SLF4j - Some people can't upgrade and we have no real need for recent features. -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Test Database -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<classifier>jdk15</classifier>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<classifier>jdk15-sources</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>directory-naming</groupId>
<artifactId>naming-java</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<maxmem>712m</maxmem>
<instrumentation>
<ignores>
<ignore>ca.uhn.fhir.model.dstu.valueset.*</ignore>
</ignores>
<excludes>
<ignore>**/valueset/*.class</ignore>
<ignore>**/exceptions/*.class</ignore>
</excludes>
<ignoreMethodAnnotation>ca.uhn.fhir.util.CoverageIgnore</ignoreMethodAnnotation>
<!-- <ignoreMethodAnnotations> <ignoreMethodAnnotation>net.sourceforge.cobertura.CoverageIgnore</ignoreMethodAnnotation> </ignoreMethodAnnotations> -->
</instrumentation>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<configuration>
<coberturaReports>
<coberturaReport>
${basedir}/target/coverage.xml
</coberturaReport>
</coberturaReports>
<sourceEncoding>UTF-8</sourceEncoding>
<serviceName>travis-ci</serviceName>
<serviceJobId>${env.TRAVIS_JOB_ID}</serviceJobId>
<sourceDirectories>
<sourceDirectory>../hapi-fhir-structures-dstu/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-hl7org-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/main/java</sourceDirectory>
</sourceDirectories>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-base/src/main/java</source>
<source>../hapi-fhir-jpaserver-base/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-structures-dstu/src/test/java</source>
<source>../hapi-fhir-structures-dstu2/src/test/java</source>
<source>../hapi-fhir-structures-hl7org-dstu2/src/test/java</source>
<source>../hapi-fhir-structures-dstu3/src/test/java</source>
<source>../hapi-fhir-jpaserver-base/src/test/java</source>
<source>../hapi-fhir-base/src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<runOrder>alphabetical</runOrder>
<argLine>-Xmx1624m</argLine>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<!--<reportFormat>plain</reportFormat> -->
<!--<argLine>-Xmx600m -XX:+HeapDumpOnOutOfMemoryError</argLine> -->
<!--<reuseForks>false</reuseForks> -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<!--
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
-->
</plugins>
<resources>
</resources>
<testResources>
<testResource>
<directory>../hapi-fhir-base/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-jpaserver-base/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu2/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-hl7org-dstu2/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu3/src/test/resources</directory>
</testResource>
</testResources>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>cobertura</report>
</reports>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${maven_project_info_plugin_version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</reporting>
</project>

View File

@ -1,378 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- The parent of this project is the deployable POM. This project isn't deployable, but this keeps it before the root pom in the reactor order when building the site. I don't know why this works...
Need to investigate this. -->
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>1.2-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-cobertura</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Cobertura Test Coverage</name>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<!--
Use an older version of SLF4j just to make sure we compile correctly
against old SLF4j - Some people can't upgrade and we have no real
need for recent features.
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Test Database -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15-sources</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>directory-naming</groupId>
<artifactId>naming-java</artifactId>
<version>0.8</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_version}</version>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>${xmlunit_version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<maxmem>256m</maxmem>
<instrumentation>
<ignores>
<ignore>ca.uhn.fhir.model.dstu.valueset.*</ignore>
</ignores>
<excludes>
<ignore>**/valueset/*.class</ignore>
<ignore>**/exceptions/*.class</ignore>
</excludes>
<!-- <ignoreMethodAnnotations> <ignoreMethodAnnotation>net.sourceforge.cobertura.CoverageIgnore</ignoreMethodAnnotation> </ignoreMethodAnnotations> -->
</instrumentation>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<coberturaReports>
<coberturaReport>
${basedir}/target/coverage.xml
</coberturaReport>
</coberturaReports>
<sourceEncoding>UTF-8</sourceEncoding>
<serviceName>travis-ci</serviceName>
<serviceJobId>${env.TRAVIS_JOB_ID}</serviceJobId>
<sourceDirectories>
<sourceDirectory>../hapi-fhir-structures-dstu/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-hl7org-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/main/java</sourceDirectory>
</sourceDirectories>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${maven_build_helper_plugin_version}</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-base/src/main/java</source>
<source>../hapi-fhir-jpaserver-base/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-structures-dstu/src/test/java</source>
<source>../hapi-fhir-structures-dstu2/src/test/java</source>
<source>../hapi-fhir-structures-hl7org-dstu2/src/test/java</source>
<source>../hapi-fhir-jpaserver-base/src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<runOrder>alphabetical</runOrder>
<argLine>-Xms512m -Xmx1024m</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>${maven_cobertura_plugin_version}</version> <configuration> <check> <branchRate>85</branchRate>
<lineRate>85</lineRate> <haltOnFailure>true</haltOnFailure> <totalBranchRate>85</totalBranchRate> <totalLineRate>85</totalLineRate> <packageLineRate>85</packageLineRate> <packageBranchRate>85</packageBranchRate>
<regexes> <regex> <pattern>com.example.reallyimportant.*</pattern> <branchRate>90</branchRate> <lineRate>80</lineRate> </regex> <regex> <pattern>com.example.boringcode.*</pattern> <branchRate>40</branchRate>
<lineRate>30</lineRate> </regex> </regexes> </check> </configuration> <executions> <execution> <goals> <goal>clean</goal> <goal>check</goal> </goals> </execution> </executions> </plugin> -->
</plugins>
<resources>
</resources>
<testResources>
<testResource>
<directory>../hapi-fhir-jpaserver-base/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu2/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-hl7org-dstu2/src/test/resources</directory>
</testResource>
</testResources>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>cobertura</report>
</reports>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${maven_project_info_plugin_version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>TRAVIS</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Travis build seems to run out of memory unless we don't reuse JVMs -->
<reuseForks>false</reuseForks>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -56,6 +56,11 @@
<artifactId>hapi-fhir-jpaserver-base</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-client-okhttp</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
@ -226,6 +231,7 @@
<include>hapi-fhir-structures-hl7org-dstu2/target/jacoco.exec</include>
<include>hapi-fhir-structures-dstu3/target/jacoco.exec</include>
<include>hapi-fhir-jpaserver-base/target/jacoco.exec</include>
<include>hapi-fhir-client-okhttp/target/jacoco.exec</include>
</includes>
</fileSet>
</fileSets>
@ -241,12 +247,13 @@
<serviceName>travis-ci</serviceName>
<serviceJobId>${env.TRAVIS_JOB_ID}</serviceJobId>
<sourceDirectories>
<sourceDirectory>../hapi-fhir-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-hl7org-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu3/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-client-okhttp/src/main/java</sourceDirectory>
</sourceDirectories>
</configuration>
</plugin>

View File

@ -0,0 +1,138 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
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.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
public class ServerExceptionDstu3Test {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = FhirContext.forDstu3();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerExceptionDstu3Test.class);
private static int ourPort;
private static Server ourServer;
public static BaseServerResponseException ourException;
@Test
public void testAddHeadersNotFound() throws Exception {
OperationOutcome operationOutcome = new OperationOutcome();
operationOutcome.addIssue().setCode(IssueType.BUSINESSRULE);
ourException = new ResourceNotFoundException("SOME MESSAGE");
ourException.addResponseHeader("X-Foo", "BAR BAR");
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(status.getStatusLine().toString());
ourLog.info(responseContent);
assertEquals(404, status.getStatusLine().getStatusCode());
assertEquals("BAR BAR", status.getFirstHeader("X-Foo").getValue());
assertThat(status.getFirstHeader("X-Powered-By").getValue(), containsString("HAPI FHIR"));
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
}
}
@Test
public void testAuthorize() throws Exception {
OperationOutcome operationOutcome = new OperationOutcome();
operationOutcome.addIssue().setCode(IssueType.BUSINESSRULE);
ourException = new AuthenticationException().addAuthenticateHeaderForRealm("REALM");
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(status.getStatusLine().toString());
ourLog.info(responseContent);
assertEquals(401, status.getStatusLine().getStatusCode());
assertEquals("Basic realm=\"REALM\"", status.getFirstHeader("WWW-Authenticate").getValue());
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
}
}
@AfterClass
public static void afterClassClearContext() throws Exception {
ourServer.stop();
TestUtil.clearAllStaticFieldsForUnitTest();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
servlet.setPagingProvider(new FifoMemoryPagingProvider(10));
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();
}
public static class DummyPatientResourceProvider implements IResourceProvider {
@Override
public Class<? extends IBaseResource> getResourceType() {
return Patient.class;
}
@Search()
public List<Patient> search() {
throw ourException;
}
}
}

View File

@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -21,13 +22,11 @@ import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
@ -51,7 +50,7 @@ public class UnclassifiedServerExceptionDstu3Test {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(status.getStatusLine().toString());
ourLog.info(responseContent);
assertEquals(477, status.getStatusLine().getStatusCode());

View File

@ -407,9 +407,9 @@ public class Controller extends BaseController {
clientCodeJsonWriter.nullValue();
}
if (client.getPrettyPrint() != null) {
if (client.isPrettyPrint()) {
clientCodeJsonWriter.name("pretty");
clientCodeJsonWriter.value(client.getPrettyPrint().toString());
clientCodeJsonWriter.value("true");
} else {
clientCodeJsonWriter.name("pretty");
clientCodeJsonWriter.nullValue();

View File

@ -236,6 +236,11 @@
<id>mion00</id>
<name>Carlo Mion</name>
</developer>
<developer>
<id>kiwiandroiddev</id>
<name>Matt Clarke</name>
<organization>Orion Health</organization>
</developer>
</developers>
<licenses>
@ -1554,6 +1559,7 @@
<module>restful-server-example-test</module>
<module>hapi-fhir-testpage-overlay</module>
<module>hapi-fhir-jpaserver-uhnfhirtest</module>
<module>hapi-fhir-client-okhttp</module>
<module>hapi-fhir-android</module>
<module>hapi-fhir-cli</module>
<module>hapi-fhir-dist</module>

View File

@ -127,6 +127,19 @@
Client that declares explicitly that it is searching/reading/etc for
a custom type did not automatically parse into that type.
</action>
<action type="add" issue="406">
Allow servers to specify the authentication realm of their choosing when
throwing an AuthenticationException. Thanks to GitHub user @allanbrohansen
for the suggestion!
</action>
<action type="add" issue="416">
Add a new client implementation which uses the
<![CDATA[<a href="http://square.github.io/okhttp/">OkHttp</a>]]>
library as the HTTP client implementation (instead of Apache HttpClient).
This is particularly useful for Android (where HttpClient is a pain) but
could also be useful in other places too.
Thanks to Matt Clarke of Orion Health for the contribution!
</action>
</release>
<release version="1.6" date="2016-07-07">
<action type="fix">

View File

@ -64,6 +64,21 @@
<param name="id" value="basicAuthInterceptor" />
<param name="file" value="examples/src/main/java/example/SecurityInterceptors.java" />
</macro>
<subsection name="HTTP Basic Auth">
<p>
Note that if you are implementing HTTP Basic Auth, you may want to
return a <code>WWW-Authenticate</code> header with the response.
The following snippet shows how to add such a header with a custom
realm:
</p>
<macro name="snippet">
<param name="id" value="basicAuthInterceptorRealm" />
<param name="file" value="examples/src/main/java/example/SecurityInterceptors.java" />
</macro>
</subsection>
</section>