diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
index ee4b0af5013..b9e398b4a56 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
@@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.server;
* 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.
@@ -19,42 +19,62 @@ package ca.uhn.fhir.rest.server;
* limitations under the License.
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.isBlank;
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
-
-import java.io.*;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.jar.Manifest;
-
-import javax.servlet.ServletException;
-import javax.servlet.UnavailableException;
-import javax.servlet.http.*;
+import ca.uhn.fhir.context.ConfigurationException;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.ProvidedResourceScanner;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
+import ca.uhn.fhir.context.api.AddProfileTagEnum;
+import ca.uhn.fhir.context.api.BundleInclusionRule;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.rest.annotation.Destroy;
+import ca.uhn.fhir.rest.annotation.IdParam;
+import ca.uhn.fhir.rest.annotation.Initialize;
+import ca.uhn.fhir.rest.api.Constants;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.RequestTypeEnum;
+import ca.uhn.fhir.rest.api.server.IFhirVersionServer;
+import ca.uhn.fhir.rest.api.server.IRestfulServer;
+import ca.uhn.fhir.rest.api.server.ParseAction;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
+import ca.uhn.fhir.rest.server.exceptions.*;
+import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
+import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
+import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
+import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
+import ca.uhn.fhir.rest.server.method.ConformanceMethodBinding;
+import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.rest.server.tenant.ITenantIdentificationStrategy;
+import ca.uhn.fhir.util.*;
+import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
-import ca.uhn.fhir.context.*;
-import ca.uhn.fhir.context.api.AddProfileTagEnum;
-import ca.uhn.fhir.context.api.BundleInclusionRule;
-import ca.uhn.fhir.parser.IParser;
-import ca.uhn.fhir.rest.annotation.*;
-import ca.uhn.fhir.rest.api.*;
-import ca.uhn.fhir.rest.api.server.*;
-import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
-import ca.uhn.fhir.rest.server.exceptions.*;
-import ca.uhn.fhir.rest.server.interceptor.*;
-import ca.uhn.fhir.rest.server.method.*;
-import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
-import ca.uhn.fhir.util.*;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.jar.Manifest;
+
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
@SuppressWarnings("WeakerAccess")
public class RestfulServer extends HttpServlet implements IRestfulServer {
@@ -96,7 +116,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServer myServerConformanceMethod;
private Object myServerConformanceProvider;
private String myServerName = "HAPI FHIR Server";
- /** This is configurable but by default we just use HAPI version */
+ /**
+ * This is configurable but by default we just use HAPI version
+ */
private String myServerVersion = VersionUtil.getVersion();
private boolean myStarted;
private Map myTypeToProvider = new HashMap<>();
@@ -121,10 +143,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer 0 && (nextString.charAt(0) == '_' || nextString.charAt(0) == '$' || nextString.equals(Constants.URL_TOKEN_METADATA));
- }
-
private void addContentLocationHeaders(RequestDetails theRequest, HttpServletResponse servletResponse, MethodOutcome response, String resourceName) {
if (response != null && response.getId() != null) {
addLocationHeader(theRequest, servletResponse, response, Constants.HEADER_LOCATION, resourceName);
@@ -140,15 +158,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer
*/
public void addHeadersToResponse(HttpServletResponse theHttpResponse) {
- StringBuilder b = new StringBuilder();
- b.append("HAPI FHIR ");
- b.append(VersionUtil.getVersion());
- b.append(" REST Server (FHIR Server; FHIR ");
- b.append(myFhirContext.getVersion().getVersion().getFhirVersionString());
- b.append('/');
- b.append(myFhirContext.getVersion().getVersion().name());
- b.append(")");
- theHttpResponse.addHeader("X-Powered-By", b.toString());
+ String b = createPoweredByHeader();
+ theHttpResponse.addHeader("X-Powered-By", b);
}
private void addLocationHeader(RequestDetails theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation, String resourceName) {
@@ -198,6 +209,33 @@ public class RestfulServer extends HttpServlet implements IRestfulServer createPoweredByAttributes() {
+ return Lists.newArrayList("FHIR Server", "FHIR " + myFhirContext.getVersion().getVersion().getFhirVersionString() + "/" + myFhirContext.getVersion().getVersion().name());
+ }
+
+ protected String createPoweredByHeader() {
+ StringBuilder b = new StringBuilder();
+ b.append(createPoweredByHeaderProductName());
+ b.append(" ");
+ b.append(VersionUtil.getVersion());
+ b.append(" REST Server (");
+
+ List poweredByAttributes = createPoweredByAttributes();
+ for (ListIterator iter = poweredByAttributes.listIterator(); iter.hasNext(); ) {
+ if (iter.nextIndex() > 0) {
+ b.append("; ");
+ }
+ b.append(iter.next());
+ }
+
+ b.append(")");
+ return b.toString();
+ }
+
+ protected String createPoweredByHeaderProductName() {
+ return "HAPI FHIR";
+ }
+
@Override
public void destroy() {
if (getResourceProviders() != null) {
@@ -253,6 +291,31 @@ public class RestfulServer extends HttpServlet implements IRestfulServernull. Default is
* {@link #DEFAULT_ETAG_SUPPORT}
*
- * @param theETagSupport
- * The ETag support mode
+ * @param theETagSupport The ETag support mode
*/
public void setETagSupport(ETagSupportEnum theETagSupport) {
if (theETagSupport == null) {
@@ -477,8 +537,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theList) {
- myInterceptors.clear();
- if (theList != null) {
- myInterceptors.addAll(theList);
- }
- }
-
@Override
public IPagingProvider getPagingProvider() {
return myPagingProvider;
@@ -533,25 +579,13 @@ public class RestfulServer extends HttpServlet implements IRestfulServer
* Note that this method can only be called before the server is initialized.
*
- * @throws IllegalStateException
- * Note that this method can only be called prior to {@link #init() initialization} and will throw an
- * {@link IllegalStateException} if called after that.
+ * @throws IllegalStateException Note that this method can only be called prior to {@link #init() initialization} and will throw an
+ * {@link IllegalStateException} if called after that.
*/
public void setServerConformanceProvider(Object theServerConformanceProvider) {
if (myStarted) {
@@ -670,9 +694,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServernull), the tenant identification
- * strategy provides a mechanism for a multitenant server to identify which tenant
- * a given request corresponds to.
- */
- public void setTenantIdentificationStrategy(ITenantIdentificationStrategy theTenantIdentificationStrategy) {
- myTenantIdentificationStrategy = theTenantIdentificationStrategy;
- }
-
/**
* Gets the server's name, as exported in conformance profiles exported by the server. This is informational only,
* but can be helpful to set with something appropriate.
@@ -1029,10 +1044,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServer clazz) {
+ for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
+ Initialize initialize = m.getAnnotation(Initialize.class);
+ if (initialize != null) {
+ invokeInitializeOrDestroyMethod(theProvider, m, "initialize");
+ }
+ }
+
+ Class> supertype = clazz.getSuperclass();
+ if (!Object.class.equals(supertype)) {
+ invokeInitialize(theProvider, supertype);
+ }
+ }
+
private void invokeInitializeOrDestroyMethod(Object theProvider, Method m, String theMethodDescription) {
Class>[] paramTypes = m.getParameterTypes();
@@ -1078,24 +1110,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer clazz) {
- for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
- Initialize initialize = m.getAnnotation(Initialize.class);
- if (initialize != null) {
- invokeInitializeOrDestroyMethod(theProvider, m, "initialize");
- }
- }
-
- Class> supertype = clazz.getSuperclass();
- if (!Object.class.equals(supertype)) {
- invokeInitialize(theProvider, supertype);
- }
- }
-
/**
* Should the server "pretty print" responses by default (requesting clients can always override this default by
* supplying an Accept
header in the request, or a _pretty
@@ -1119,8 +1133,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServerfalse
*
*
- * @param theDefaultPrettyPrint
- * The default pretty print setting
+ * @param theDefaultPrettyPrint The default pretty print setting
*/
public void setDefaultPrettyPrint(boolean theDefaultPrettyPrint) {
myDefaultPrettyPrint = theDefaultPrettyPrint;
@@ -1174,8 +1187,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer providers) {
myProviderRegistrationMutex.lock();
@@ -1327,7 +1339,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer clazz = theProvider.getClass();
Class> supertype = clazz.getSuperclass();
@@ -1447,50 +1459,46 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theList) {
+ myInterceptors.clear();
+ if (theList != null) {
+ myInterceptors.addAll(theList);
+ }
}
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- handleRequest(RequestTypeEnum.GET, request, response);
- }
-
- @Override
- protected void doOptions(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
- handleRequest(RequestTypeEnum.OPTIONS, theReq, theResp);
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- handleRequest(RequestTypeEnum.POST, request, response);
- }
-
- @Override
- protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- handleRequest(RequestTypeEnum.PUT, request, response);
+ /**
+ * Sets the non-resource specific providers which implement method calls on this server.
+ *
+ * @see #setResourceProviders(Collection)
+ */
+ public void setPlainProviders(Object... theProv) {
+ setPlainProviders(Arrays.asList(theProv));
}
/**
@@ -1505,6 +1513,25 @@ public class RestfulServer extends HttpServlet implements IRestfulServernull), the tenant identification
+ * strategy provides a mechanism for a multitenant server to identify which tenant
+ * a given request corresponds to.
+ */
+ public void setTenantIdentificationStrategy(ITenantIdentificationStrategy theTenantIdentificationStrategy) {
+ myTenantIdentificationStrategy = theTenantIdentificationStrategy;
+ }
+
public void unregisterInterceptor(IServerInterceptor theInterceptor) {
Validate.notNull(theInterceptor, "Interceptor can not be null");
myInterceptors.remove(theInterceptor);
@@ -1567,6 +1594,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer 0 && (nextString.charAt(0) == '_' || nextString.charAt(0) == '$' || nextString.equals(Constants.URL_TOKEN_METADATA));
+ }
+
// /**
// * Returns the read method binding for the given resource type, or
// * returns null
if not