Tests passing

This commit is contained in:
jamesagnew 2016-06-25 10:55:31 -04:00
parent bf303507d8
commit 556058a7b7
56 changed files with 450 additions and 302 deletions

View File

@ -24,7 +24,6 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
public class MethodOutcome { public class MethodOutcome {
@ -33,7 +32,6 @@ public class MethodOutcome {
private IIdType myId; private IIdType myId;
private IBaseOperationOutcome myOperationOutcome; private IBaseOperationOutcome myOperationOutcome;
private IBaseResource myResource; private IBaseResource myResource;
private IdDt myVersionId;
/** /**
* Constructor * Constructor
@ -91,27 +89,6 @@ public class MethodOutcome {
myCreated = theCreated; myCreated = theCreated;
} }
/**
* @deprecated Use the constructor which accepts a single IIdType parameter, and include the logical ID and version ID in that IIdType instance
*/
@Deprecated
@CoverageIgnore
public MethodOutcome(IIdType theId, IdDt theVersionId) {
myId = theId;
myVersionId = theVersionId;
}
/**
* @deprecated Use the constructor which accepts a single IdDt parameter, and include the logical ID and version ID in that IdDt instance
*/
@Deprecated
@CoverageIgnore
public MethodOutcome(IIdType theId, IdDt theVersionId, IBaseOperationOutcome theBaseOperationOutcome) {
myId = theId;
myVersionId = theVersionId;
myOperationOutcome = theBaseOperationOutcome;
}
/** /**
* Constructor * Constructor
* *
@ -122,6 +99,16 @@ public class MethodOutcome {
myId = theId; myId = theId;
} }
/**
* Constructor
*
* @param theOperationOutcome
* The operation outcome resource to return
*/
public MethodOutcome(IBaseOperationOutcome theOperationOutcome) {
myOperationOutcome = theOperationOutcome;
}
/** /**
* This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are * This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are
* returned to client instances, if the server has responded with an HTTP 201 Created. * returned to client instances, if the server has responded with an HTTP 201 Created.
@ -152,15 +139,6 @@ public class MethodOutcome {
return myResource; return myResource;
} }
/**
* @deprecated {@link MethodOutcome#getId()} should return the complete ID including version if it is available
*/
@Deprecated
@CoverageIgnore
public IdDt getVersionId() {
return myVersionId;
}
/** /**
* If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called whether the * If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called whether the
* result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist. * result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
@ -205,13 +183,4 @@ public class MethodOutcome {
myResource = theResource; myResource = theResource;
} }
/**
* @deprecated Put the ID and version ID into the same IdDt instance and pass it to {@link #setId(IIdType)}
*/
@Deprecated
@CoverageIgnore
public void setVersionId(IdDt theVersionId) {
myVersionId = theVersionId;
}
} }

View File

@ -1663,7 +1663,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override @Override
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException { public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
MethodOutcome response = MethodUtil.process2xxResponse(myContext, myResourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders); MethodOutcome response = MethodUtil.process2xxResponse(myContext, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
if (theResponseStatusCode == Constants.STATUS_HTTP_201_CREATED) { if (theResponseStatusCode == Constants.STATUS_HTTP_201_CREATED) {
response.setCreated(true); response.setCreated(true);
} }

View File

@ -40,7 +40,6 @@ import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.PreferReturnEnum; import ca.uhn.fhir.rest.api.PreferReturnEnum;
@ -167,7 +166,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
if (myReturnVoid) { if (myReturnVoid) {
return null; return null;
} }
MethodOutcome retVal = MethodUtil.process2xxResponse(getContext(), getResourceName(), theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders); MethodOutcome retVal = MethodUtil.process2xxResponse(getContext(), theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
return retVal; return retVal;
} else { } else {
throw processNon2xxResponseAndReturnExceptionToThrow(theResponseStatusCode, theResponseMimeType, theResponseReader); throw processNon2xxResponseAndReturnExceptionToThrow(theResponseStatusCode, theResponseMimeType, theResponseReader);
@ -283,7 +282,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
} }
} }
protected static void parseContentLocation(FhirContext theContext, MethodOutcome theOutcomeToPopulate, String theResourceName, String theLocationHeader) { protected static void parseContentLocation(FhirContext theContext, MethodOutcome theOutcomeToPopulate, String theLocationHeader) {
if (StringUtils.isBlank(theLocationHeader)) { if (StringUtils.isBlank(theLocationHeader)) {
return; return;
} }
@ -291,22 +290,6 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
IIdType id = theContext.getVersion().newIdType(); IIdType id = theContext.getVersion().newIdType();
id.setValue(theLocationHeader); id.setValue(theLocationHeader);
theOutcomeToPopulate.setId(id); theOutcomeToPopulate.setId(id);
String resourceNamePart = "/" + theResourceName + "/";
int resourceIndex = theLocationHeader.lastIndexOf(resourceNamePart);
if (resourceIndex > -1) {
int idIndexStart = resourceIndex + resourceNamePart.length();
int idIndexEnd = theLocationHeader.indexOf('/', idIndexStart);
if (idIndexEnd == -1) {
// nothing
} else {
String versionIdPart = "/_history/";
int historyIdStart = theLocationHeader.indexOf(versionIdPart, idIndexEnd);
if (historyIdStart != -1) {
theOutcomeToPopulate.setVersionId(new IdDt(theLocationHeader.substring(historyIdStart + versionIdPart.length())));
}
}
}
} }
} }

View File

@ -747,7 +747,7 @@ public class MethodUtil {
} }
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) { public static MethodOutcome process2xxResponse(FhirContext theContext, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
List<String> locationHeaders = new ArrayList<String>(); List<String> locationHeaders = new ArrayList<String>();
List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC); List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC);
if (lh != null) { if (lh != null) {
@ -761,7 +761,7 @@ public class MethodUtil {
MethodOutcome retVal = new MethodOutcome(); MethodOutcome retVal = new MethodOutcome();
if (locationHeaders != null && locationHeaders.size() > 0) { if (locationHeaders != null && locationHeaders.size() > 0) {
String locationHeader = locationHeaders.get(0); String locationHeader = locationHeaders.get(0);
BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, theResourceName, locationHeader); BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, locationHeader);
} }
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) { if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType); EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType);

View File

@ -112,7 +112,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
myName = theOperationName; myName = theOperationName;
if (theContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU1)) { if (theContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU1)) {
throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name()); throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name() + " - Found one on class " + theMethod.getDeclaringClass().getName());
} }
if (theReturnTypeFromRp != null) { if (theReturnTypeFromRp != null) {

View File

@ -83,7 +83,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
if (isNotBlank(locationHeader)) { if (isNotBlank(locationHeader)) {
MethodOutcome mo = new MethodOutcome(); MethodOutcome mo = new MethodOutcome();
parseContentLocation(getContext(), mo, getResourceName(), locationHeader); parseContentLocation(getContext(), mo, locationHeader);
if (mo.getId() == null || mo.getId().isEmpty()) { if (mo.getId() == null || mo.getId().isEmpty()) {
throw new InvalidRequestException("Invalid Content-Location header for resource " + getResourceName() + ": " + locationHeader); throw new InvalidRequestException("Invalid Content-Location header for resource " + getResourceName() + ": " + locationHeader);
} }

View File

@ -176,9 +176,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
if (response.getId().hasVersionIdPart()) { if (response.getId().hasVersionIdPart()) {
b.append("/" + Constants.PARAM_HISTORY + "/"); b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getId().getVersionIdPart()); b.append(response.getId().getVersionIdPart());
} else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getVersionId().getValue());
} }
theResponse.addHeader(headerLocation, b.toString()); theResponse.addHeader(headerLocation, b.toString());

View File

@ -371,23 +371,37 @@ public interface IServerInterceptor {
private IBaseResource myResource; private IBaseResource myResource;
private final String myResourceType; private final String myResourceType;
public ActionRequestDetails(IIdType theId, String theResourceType, FhirContext theContext, RequestDetails theRequestDetails) { public ActionRequestDetails(RequestDetails theRequestDetails) {
myId = theRequestDetails.getId();
myResourceType = theRequestDetails.getResourceName();
myContext = theRequestDetails.getServer().getFhirContext();
myRequestDetails = theRequestDetails;
}
public ActionRequestDetails(RequestDetails theRequestDetails, FhirContext theContext, IBaseResource theResource) {
this(theRequestDetails, theContext, theContext.getResourceDefinition(theResource).getName(), theResource.getIdElement());
myResource = theResource;
}
public ActionRequestDetails(RequestDetails theRequestDetails, FhirContext theContext, String theResourceType, IIdType theId) {
myId = theId; myId = theId;
myResourceType = theResourceType; myResourceType = theResourceType;
myContext = theContext; myContext = theContext;
myRequestDetails = theRequestDetails; myRequestDetails = theRequestDetails;
} }
public ActionRequestDetails(IIdType theId, String theResourceType, IBaseResource theResource, FhirContext theContext, RequestDetails theRequestDetails) { public ActionRequestDetails(RequestDetails theRequestDetails, IBaseResource theResource) {
this(theId, theResourceType, theContext, theRequestDetails); this(theRequestDetails, theRequestDetails.getServer().getFhirContext().getResourceDefinition(theResource).getName(), theResource.getIdElement());
myResource = theResource; myResource = theResource;
} }
public ActionRequestDetails(RequestDetails theRequestDetails) { public ActionRequestDetails(RequestDetails theRequestDetails, IBaseResource theResource, String theResourceType, IIdType theId) {
myId = theRequestDetails.getId(); this(theRequestDetails, theResourceType, theId);
myResourceType = theRequestDetails.getResourceName(); myResource = theResource;
myContext = theRequestDetails.getServer().getFhirContext(); }
myRequestDetails = theRequestDetails;
public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
} }
public FhirContext getContext() { public FhirContext getContext() {
@ -436,13 +450,6 @@ public interface IServerInterceptor {
return myRequestDetails.getUserData(); return myRequestDetails.getUserData();
} }
/**
* This method should not be called by client code
*/
public void setResource(IBaseResource theObject) {
myResource = theObject;
}
/** /**
* This method may be invoked by user code to notify interceptors that a nested * This method may be invoked by user code to notify interceptors that a nested
* operation is being invoked which is denoted by this request details. * operation is being invoked which is denoted by this request details.
@ -462,6 +469,13 @@ public interface IServerInterceptor {
} }
} }
/**
* This method should not be called by client code
*/
public void setResource(IBaseResource theObject) {
myResource = theObject;
}
} }
} }

View File

@ -27,6 +27,8 @@ import ca.uhn.fhir.jpa.demo.FhirServerConfigDstu3;
public class RunServerCommand extends BaseCommand { public class RunServerCommand extends BaseCommand {
private static final String OPTION_LOWMEM = "lowmem";
private static final String OPTION_ALLOW_EXTERNAL_REFS = "allow-external-refs";
private static final int DEFAULT_PORT = 8080; private static final int DEFAULT_PORT = 8080;
private static final String OPTION_P = "p"; private static final String OPTION_P = "p";
@ -45,7 +47,8 @@ public class RunServerCommand extends BaseCommand {
Options options = new Options(); Options options = new Options();
addFhirVersionOption(options); addFhirVersionOption(options);
options.addOption(OPTION_P, "port", true, "The port to listen on (default is " + DEFAULT_PORT + ")"); options.addOption(OPTION_P, "port", true, "The port to listen on (default is " + DEFAULT_PORT + ")");
options.addOption(null, "lowmem", false, "If this flag is set, the server will operate in low memory mode (some features disabled)"); options.addOption(null, OPTION_LOWMEM, false, "If this flag is set, the server will operate in low memory mode (some features disabled)");
options.addOption(null, OPTION_ALLOW_EXTERNAL_REFS, false, "If this flag is set, the server will allow resources to be persisted contaning external resource references");
return options; return options;
} }
@ -61,11 +64,16 @@ public class RunServerCommand extends BaseCommand {
public void run(CommandLine theCommandLine) throws ParseException { public void run(CommandLine theCommandLine) throws ParseException {
myPort = parseOptionInteger(theCommandLine, OPTION_P, DEFAULT_PORT); myPort = parseOptionInteger(theCommandLine, OPTION_P, DEFAULT_PORT);
if (theCommandLine.hasOption("lowmem")) { if (theCommandLine.hasOption(OPTION_LOWMEM)) {
ourLog.info("Running in low memory mode, some features disabled"); ourLog.info("Running in low memory mode, some features disabled");
System.setProperty("lowmem", "lowmem"); System.setProperty(OPTION_LOWMEM, OPTION_LOWMEM);
} }
if (theCommandLine.hasOption(OPTION_ALLOW_EXTERNAL_REFS)) {
ourLog.info("Server is configured to allow external references");
ContextHolder.setAllowExternalRefs(true);
}
ContextHolder.setCtx(getSpecVersionContext(theCommandLine)); ContextHolder.setCtx(getSpecVersionContext(theCommandLine));
ourLog.info("Preparing HAPI FHIR JPA server on port {}", myPort); ourLog.info("Preparing HAPI FHIR JPA server on port {}", myPort);

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.context.FhirContext;
public class ContextHolder { public class ContextHolder {
private static boolean ourAllowExternalRefs;
private static FhirContext ourCtx; private static FhirContext ourCtx;
private static String ourPath; private static String ourPath;
@ -15,6 +16,19 @@ public class ContextHolder {
return ourCtx; return ourCtx;
} }
public static String getPath() {
Validate.notNull(ourPath, "Context not set");
return ourPath;
}
public static boolean isAllowExternalRefs() {
return ourAllowExternalRefs;
}
public static void setAllowExternalRefs(boolean theAllowExternalRefs) {
ourAllowExternalRefs = theAllowExternalRefs;
}
public static void setCtx(FhirContext theCtx) throws ParseException { public static void setCtx(FhirContext theCtx) throws ParseException {
switch (theCtx.getVersion().getVersion()) { switch (theCtx.getVersion().getVersion()) {
case DSTU2: case DSTU2:
@ -29,10 +43,5 @@ public class ContextHolder {
ourCtx = theCtx; ourCtx = theCtx;
} }
public static String getPath() {
Validate.notNull(ourPath, "Context not set");
return ourPath;
}
} }

View File

@ -147,6 +147,9 @@ public class JpaServerDemo extends RestfulServer {
this.registerInterceptor(interceptor); this.registerInterceptor(interceptor);
} }
DaoConfig daoConfig = myAppCtx.getBean(DaoConfig.class);
daoConfig.setAllowExternalReferences(ContextHolder.isAllowExternalRefs());
} }
} }

View File

@ -133,10 +133,6 @@ public class JaxRsResponseDstu3Test {
@Test @Test
public void testNoOutcomeXml() throws IOException { public void testNoOutcomeXml() throws IOException {
int operationStatus = Constants.STATUS_HTTP_204_NO_CONTENT;
boolean allowPrefer = true;
String resourceName = "Patient";
MethodOutcome methodOutcome = new MethodOutcome(null);
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML}); response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
boolean addContentLocationHeader = true; boolean addContentLocationHeader = true;
boolean respondGzip = true; boolean respondGzip = true;

View File

@ -129,7 +129,6 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.MethodUtil; import ca.uhn.fhir.rest.method.MethodUtil;
import ca.uhn.fhir.rest.method.QualifiedParamList; import ca.uhn.fhir.rest.method.QualifiedParamList;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam;
@ -1076,8 +1075,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, RequestDetails theRequestDetails) { boolean theUpdateVersion, Date theUpdateTime) {
ourLog.info("Starting entity update"); ourLog.info("Starting entity update");
/* /*
@ -1085,7 +1084,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
*/ */
if (theResource != null) { if (theResource != null) {
if (thePerformIndexing) { if (thePerformIndexing) {
validateResourceForStorage((T) theResource, theEntity, theRequestDetails); validateResourceForStorage((T) theResource, theEntity);
} }
String resourceType = myContext.getResourceDefinition(theResource).getName(); String resourceType = myContext.getResourceDefinition(theResource).getName();
if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) { if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) {
@ -1394,9 +1393,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
return theEntity; return theEntity;
} }
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, Date theUpdateTime, protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable entity, Date theDeletedTimestampOrNull, Date theUpdateTime) {
RequestDetails theRequestDetails) { return updateEntity(theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime);
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true, theUpdateTime, theRequestDetails);
} }
protected void validateDeleteConflictsEmptyOrThrowException(List<DeleteConflict> theDeleteConflicts) { protected void validateDeleteConflictsEmptyOrThrowException(List<DeleteConflict> theDeleteConflicts) {
@ -1423,10 +1421,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
* The resource that is about to be persisted * The resource that is about to be persisted
* @param theEntityToSave * @param theEntityToSave
* TODO * TODO
* @param theRequestDetails
* TODO
*/ */
protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) {
Object tag = null; Object tag = null;
if (theResource instanceof IResource) { if (theResource instanceof IResource) {
IResource res = (IResource) theResource; IResource res = (IResource) theResource;

View File

@ -197,20 +197,26 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
validateOkToDelete(deleteConflicts, entity); validateOkToDelete(deleteConflicts, entity);
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType(), getContext(), theRequestDetails); if (theRequestDetails != null) {
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
}
Date updateTime = new Date(); Date updateTime = new Date();
ResourceTable savedEntity = updateEntity(null, entity, true, updateTime, updateTime, theRequestDetails); ResourceTable savedEntity = updateEntity(null, entity, updateTime, updateTime);
// Notify JPA interceptors // Notify JPA interceptors
T resourceToDelete = toResource(myResourceType, entity, false); if (theRequestDetails != null) {
theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
for (IServerInterceptor next : getConfig().getInterceptors()) { T resourceToDelete = toResource(myResourceType, entity, false);
if (next instanceof IJpaServerInterceptor) { theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete);
((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); for (IServerInterceptor next : getConfig().getInterceptors()) {
if (next instanceof IJpaServerInterceptor) {
((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity);
}
} }
} }
return savedEntity; return savedEntity;
} }
@ -245,12 +251,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
// Notify interceptors // Notify interceptors
IdDt idToDelete = entity.getIdDt(); IdDt idToDelete = entity.getIdDt();
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete);
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
// Perform delete // Perform delete
Date updateTime = new Date(); Date updateTime = new Date();
updateEntity(null, entity, true, updateTime, updateTime, theRequestDetails); updateEntity(null, entity, updateTime, updateTime);
// Notify JPA interceptors // Notify JPA interceptors
T resourceToDelete = toResource(myResourceType, entity, false); T resourceToDelete = toResource(myResourceType, entity, false);
@ -322,21 +328,26 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource, getContext(), theRequestDetails); if (theRequestDetails != null) {
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource);
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
}
// Perform actual DB update // Perform actual DB update
updateEntity(theResource, entity, false, null, thePerformIndexing, true, theUpdateTime, theRequestDetails); updateEntity(theResource, entity, null, thePerformIndexing, true, theUpdateTime);
theResource.setId(entity.getIdDt()); theResource.setId(entity.getIdDt());
// Notify JPA interceptors // Notify JPA interceptors
theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); if (theRequestDetails != null) {
for (IServerInterceptor next : getConfig().getInterceptors()) { ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource);
if (next instanceof IJpaServerInterceptor) { theRequestDetails.getRequestOperationCallback().resourceCreated(theResource);
((IJpaServerInterceptor) next).resourceCreated(requestDetails, entity); for (IServerInterceptor next : getConfig().getInterceptors()) {
if (next instanceof IJpaServerInterceptor) {
((IJpaServerInterceptor) next).resourceCreated(requestDetails, entity);
}
} }
} }
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true); DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart()); String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
@ -401,7 +412,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public TagList getAllResourceTags(RequestDetails theRequestDetails) { public TagList getAllResourceTags(RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails); notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -424,7 +435,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public TagList getTags(IIdType theResourceId, RequestDetails theRequestDetails) { public TagList getTags(IIdType theResourceId, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, null, theResourceId);
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails); notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -436,7 +447,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) { public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails); notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -448,7 +459,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public IBundleProvider history(final IIdType theId, final Date theSince, Date theUntil, RequestDetails theRequestDetails) { public IBundleProvider history(final IIdType theId, final Date theSince, Date theUntil, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId);
notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails); notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -547,7 +558,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequestDetails) { public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId);
notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails); notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -577,7 +588,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) { public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId);
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails); notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -609,7 +620,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequestDetails) { public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId);
notifyInterceptors(RestOperationTypeEnum.META, requestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
Set<TagDefinition> tagDefs = new HashSet<TagDefinition>(); Set<TagDefinition> tagDefs = new HashSet<TagDefinition>();
@ -628,7 +639,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, RequestDetails theRequestDetails) { public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.META, requestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)"; String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)";
@ -704,10 +715,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
validateResourceTypeAndThrowIllegalArgumentException(theId); validateResourceTypeAndThrowIllegalArgumentException(theId);
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); if (theRequestDetails != null) {
RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ; ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId);
notifyInterceptors(operationType, requestDetails); RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ;
notifyInterceptors(operationType, requestDetails);
}
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
BaseHasResource entity = readEntity(theId); BaseHasResource entity = readEntity(theId);
validateResourceType(entity); validateResourceType(entity);
@ -790,14 +803,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
@Override @Override
public void reindex(T theResource, ResourceTable theEntity, RequestDetails theRequestDetails) { public void reindex(T theResource, ResourceTable theEntity) {
updateEntity(theResource, theEntity, false, null, true, false, theEntity.getUpdatedDate(), theRequestDetails); updateEntity(theResource, theEntity, null, true, false, theEntity.getUpdatedDate());
} }
@Override @Override
public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails) { public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId);
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails); notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -838,7 +851,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override @Override
public IBundleProvider search(final SearchParameterMap theParams) { public IBundleProvider search(final SearchParameterMap theParams) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theParams.getRequestDetails()); ActionRequestDetails requestDetails = new ActionRequestDetails(theParams.getRequestDetails(), getContext(), getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails); notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao,
@ -1010,11 +1023,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, getResourceName(), resourceId);
notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails); notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails);
// Perform update // Perform update
ResourceTable savedEntity = updateEntity(theResource, entity, true, null, thePerformIndexing, true, new Date(), theRequestDetails); ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, true, new Date());
// Notify interceptors // Notify interceptors
theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource); theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource);

View File

@ -79,21 +79,21 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@Override @Override
public void deleteAllTagsOnServer(RequestDetails theRequestDetails) { public void deleteAllTagsOnServer(RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails); notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
myEntityManager.createQuery("DELETE from ResourceTag t").executeUpdate(); myEntityManager.createQuery("DELETE from ResourceTag t").executeUpdate();
} }
private int doPerformReindexingPass(final Integer theCount, final RequestDetails theRequestDetails) { private int doPerformReindexingPass(final Integer theCount) {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED); txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
int retVal = doPerformReindexingPassForResources(theCount, theRequestDetails, txTemplate); int retVal = doPerformReindexingPassForResources(theCount, txTemplate);
retVal += doPerformReindexingPassForConcepts(txTemplate); retVal += doPerformReindexingPassForConcepts(txTemplate);
return retVal; return retVal;
} }
private int doPerformReindexingPassForResources(final Integer theCount, final RequestDetails theRequestDetails, TransactionTemplate txTemplate) { private int doPerformReindexingPassForResources(final Integer theCount, TransactionTemplate txTemplate) {
return txTemplate.execute(new TransactionCallback<Integer>() { return txTemplate.execute(new TransactionCallback<Integer>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
@ -135,7 +135,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
final IFhirResourceDao dao = getDao(resource.getClass()); final IFhirResourceDao dao = getDao(resource.getClass());
dao.reindex(resource, resourceTable, theRequestDetails); dao.reindex(resource, resourceTable);
} catch (Exception e) { } catch (Exception e) {
ourLog.error("Failed to index resource {}: {}", new Object[] { resourceTable.getIdDt(), e.toString(), e }); ourLog.error("Failed to index resource {}: {}", new Object[] { resourceTable.getIdDt(), e.toString(), e });
throw new ReindexFailureException(resourceTable.getId()); throw new ReindexFailureException(resourceTable.getId());
@ -186,7 +186,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@Override @Override
public TagList getAllTags(RequestDetails theRequestDetails) { public TagList getAllTags(RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails); notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -221,7 +221,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@Override @Override
public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) { public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails); notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
@ -260,9 +260,9 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@Override @Override
@Transactional(propagation = Propagation.NOT_SUPPORTED) @Transactional(propagation = Propagation.NOT_SUPPORTED)
public int performReindexingPass(final Integer theCount, RequestDetails theRequestDetails) { public int performReindexingPass(final Integer theCount) {
try { try {
return doPerformReindexingPass(theCount, theRequestDetails); return doPerformReindexingPass(theCount);
} catch (ReindexFailureException e) { } catch (ReindexFailureException e) {
ourLog.warn("Reindexing failed for resource {}", e.getResourceId()); ourLog.warn("Reindexing failed for resource {}", e.getResourceId());
markResourceAsIndexingFailed(e.getResourceId()); markResourceAsIndexingFailed(e.getResourceId());

View File

@ -100,7 +100,7 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
@Override @Override
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) {
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, null, theId);
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails); notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
if (theMode == ValidationModeEnum.DELETE) { if (theMode == ValidationModeEnum.DELETE) {

View File

@ -73,7 +73,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
@Override @Override
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative); return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
@ -82,7 +82,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
@Override @Override
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative); return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);

View File

@ -35,7 +35,6 @@ import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire; import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
@ -64,8 +63,8 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
} }
@Override @Override
protected void validateResourceForStorage(QuestionnaireResponse theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { protected void validateResourceForStorage(QuestionnaireResponse theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave, theRequestDetails); super.validateResourceForStorage(theResource, theEntityToSave);
if (!myValidateResponses) { if (!myValidateResponses) {
return; return;
} }
@ -80,7 +79,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
val.setValidateAgainstStandardSchematron(false); val.setValidateAgainstStandardSchematron(false);
FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator(); FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator();
module.setResourceLoader(new JpaResourceLoader(theRequestDetails)); module.setResourceLoader(new JpaResourceLoader());
val.registerValidatorModule(module); val.registerValidatorModule(module);
ValidationResult result = val.validateWithResult(myRefImplCtx.newJsonParser().parseResource(getContext().newJsonParser().encodeResourceToString(qa))); ValidationResult result = val.validateWithResult(myRefImplCtx.newJsonParser().parseResource(getContext().newJsonParser().encodeResourceToString(qa)));
@ -92,10 +91,8 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
public class JpaResourceLoader implements IResourceLoader { public class JpaResourceLoader implements IResourceLoader {
private RequestDetails myRequestDetails; public JpaResourceLoader() {
super();
public JpaResourceLoader(RequestDetails theRequestDetails) {
myRequestDetails = theRequestDetails;
} }
@Override @Override
@ -107,7 +104,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
*/ */
if ("ValueSet".equals(theType.getSimpleName())) { if ("ValueSet".equals(theType.getSimpleName())) {
IFhirResourceDao<ValueSet> dao = getDao(ValueSet.class); IFhirResourceDao<ValueSet> dao = getDao(ValueSet.class);
ValueSet in = dao.read(theId, myRequestDetails); ValueSet in = dao.read(theId, null);
String encoded = getContext().newJsonParser().encodeResourceToString(in); String encoded = getContext().newJsonParser().encodeResourceToString(in);
// TODO: this is temporary until structures-dstu2 catches up to structures-hl7org.dstu2 // TODO: this is temporary until structures-dstu2 catches up to structures-hl7org.dstu2
@ -116,7 +113,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
return myRefImplCtx.newJsonParser().parseResource(theType, encoded); return myRefImplCtx.newJsonParser().parseResource(theType, encoded);
} else if ("Questionnaire".equals(theType.getSimpleName())) { } else if ("Questionnaire".equals(theType.getSimpleName())) {
IFhirResourceDao<Questionnaire> dao = getDao(Questionnaire.class); IFhirResourceDao<Questionnaire> dao = getDao(Questionnaire.class);
Questionnaire vs = dao.read(theId, myRequestDetails); Questionnaire vs = dao.read(theId, null);
return myRefImplCtx.newJsonParser().parseResource(theType, getContext().newJsonParser().encodeResourceToString(vs)); return myRefImplCtx.newJsonParser().parseResource(theType, getContext().newJsonParser().encodeResourceToString(vs));
} else { } else {
// Should not happen, validator will only ask for these two // Should not happen, validator will only ask for these two

View File

@ -27,8 +27,6 @@ import org.springframework.scheduling.annotation.Scheduled;
import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.SearchParameter; import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<SearchParameter>implements IFhirResourceDaoSearchParameter<SearchParameter> { public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<SearchParameter>implements IFhirResourceDaoSearchParameter<SearchParameter> {
@ -48,10 +46,9 @@ public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<Se
return; return;
} }
RequestDetails requestDetails = new ServletRequestDetails(); int count = mySystemDao.performReindexingPass(100);
int count = mySystemDao.performReindexingPass(100, requestDetails);
for (int i = 0; i < 50 && count > 0; i++) { for (int i = 0; i < 50 && count > 0; i++) {
count = mySystemDao.performReindexingPass(100, requestDetails); count = mySystemDao.performReindexingPass(100);
try { try {
Thread.sleep(DateUtils.MILLIS_PER_SECOND); Thread.sleep(DateUtils.MILLIS_PER_SECOND);
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@ -52,7 +52,6 @@ import ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource;
import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.dstu2.resource.Subscription; import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -60,9 +59,9 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
@ -162,8 +161,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
ourLog.debug("Subscription {} search from {} to {}", new Object[] { subscription.getId().getIdPart(), new InstantDt(new Date(start)), new InstantDt(new Date(end)) }); ourLog.debug("Subscription {} search from {} to {}", new Object[] { subscription.getId().getIdPart(), new InstantDt(new Date(start)), new InstantDt(new Date(end)) });
DateRangeParam range = new DateRangeParam(); DateRangeParam range = new DateRangeParam();
range.setLowerBound(new DateParam(QuantityCompararatorEnum.GREATERTHAN, start)); range.setLowerBound(new DateParam(ParamPrefixEnum.GREATERTHAN, start));
range.setUpperBound(new DateParam(QuantityCompararatorEnum.LESSTHAN, end)); range.setUpperBound(new DateParam(ParamPrefixEnum.LESSTHAN, end));
criteriaUrl.setLastUpdated(range); criteriaUrl.setLastUpdated(range);
criteriaUrl.setSort(new SortSpec(Constants.PARAM_LASTUPDATED, SortOrderEnum.ASC)); criteriaUrl.setSort(new SortSpec(Constants.PARAM_LASTUPDATED, SortOrderEnum.ASC));
IFhirResourceDao<? extends IBaseResource> dao = getDao(resourceDef.getImplementingClass()); IFhirResourceDao<? extends IBaseResource> dao = getDao(resourceDef.getImplementingClass());
@ -252,7 +251,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
txTemplate.execute(new TransactionCallback<Void>() { txTemplate.execute(new TransactionCallback<Void>() {
@Override @Override
public Void doInTransaction(TransactionStatus theStatus) { public Void doInTransaction(TransactionStatus theStatus) {
delete(subscriptionId, new ServletRequestDetails()); delete(subscriptionId, null);
return null; return null;
} }
}); });
@ -260,9 +259,9 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
} }
@Override @Override
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, RequestDetails theRequestDetails) { Date theUpdateTime) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theUpdateHistory, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theRequestDetails); ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime);
Subscription resource = (Subscription) theResource; Subscription resource = (Subscription) theResource;
Long resourceId = theEntity.getId(); Long resourceId = theEntity.getId();
@ -311,8 +310,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
} }
@Override @Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave, theRequestDetails); super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource); RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);

View File

@ -64,7 +64,7 @@ public class FhirSystemDaoDstu1 extends BaseHapiFhirSystemDao<List<IResource>, M
ourLog.info("Beginning transaction with {} resources", theResources.size()); ourLog.info("Beginning transaction with {} resources", theResources.size());
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -270,7 +270,7 @@ public class FhirSystemDaoDstu1 extends BaseHapiFhirSystemDao<List<IResource>, M
ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull)); ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
} }
updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull, updateTime, theRequestDetails); updateEntity(resource, table, deletedTimestampOrNull, updateTime);
} }
long delay = System.currentTimeMillis() - start; long delay = System.currentTimeMillis() - start;

View File

@ -200,7 +200,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
@Override @Override
public MetaDt metaGetOperation(RequestDetails theRequestDetails) { public MetaDt metaGetOperation(RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.META, requestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)"; String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)";
@ -259,7 +259,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
@Transactional(propagation = Propagation.REQUIRED) @Transactional(propagation = Propagation.REQUIRED)
@Override @Override
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) { public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
String actionName = "Transaction"; String actionName = "Transaction";
@ -474,7 +474,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource); InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null; Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false, updateTime, theRequestDetails); updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime);
} }
myEntityManager.flush(); myEntityManager.flush();

View File

@ -143,9 +143,8 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
/** /**
* Updates index tables associated with the given resource. Does not create a new * Updates index tables associated with the given resource. Does not create a new
* version or update the resource's update time. * version or update the resource's update time.
* @param theRequestDetails TODO
*/ */
void reindex(T theResource, ResourceTable theEntity, RequestDetails theRequestDetails); void reindex(T theResource, ResourceTable theEntity);
void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails); void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails);

View File

@ -62,7 +62,7 @@ public interface IFhirSystemDao<T, MT> extends IDao {
*/ */
MT metaGetOperation(RequestDetails theRequestDetails); MT metaGetOperation(RequestDetails theRequestDetails);
int performReindexingPass(Integer theCount, RequestDetails theRequestDetails); int performReindexingPass(Integer theCount);
T transaction(RequestDetails theRequestDetails, T theResources); T transaction(RequestDetails theRequestDetails, T theResources);

View File

@ -35,7 +35,6 @@ import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -198,9 +197,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
} }
@Override @Override
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, RequestDetails theRequestDetails) { boolean theUpdateVersion, Date theUpdateTime) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theUpdateHistory, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theRequestDetails); ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime);
CodeSystem cs = (CodeSystem) theResource; CodeSystem cs = (CodeSystem) theResource;

View File

@ -31,7 +31,6 @@ import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.OperationOutcome; import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity; import org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.dstu3.model.OperationOutcome.OperationOutcomeIssueComponent; import org.hl7.fhir.dstu3.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.instance.model.OperationOutcome.IssueType;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -104,7 +103,7 @@ public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirRe
@Override @Override
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) {
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, null, theId);
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails); notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
if (theMode == ValidationModeEnum.DELETE) { if (theMode == ValidationModeEnum.DELETE) {

View File

@ -72,7 +72,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>im
@Override @Override
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative); return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
@ -81,7 +81,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>im
@Override @Override
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative); return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);

View File

@ -29,8 +29,6 @@ import org.springframework.scheduling.annotation.Scheduled;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter>implements IFhirResourceDaoSearchParameter<SearchParameter> { public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter>implements IFhirResourceDaoSearchParameter<SearchParameter> {
@ -50,10 +48,9 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
return; return;
} }
RequestDetails requestDetails = new ServletRequestDetails(); int count = mySystemDao.performReindexingPass(100);
int count = mySystemDao.performReindexingPass(100, requestDetails);
for (int i = 0; i < 50 && count > 0; i++) { for (int i = 0; i < 50 && count > 0; i++) {
count = mySystemDao.performReindexingPass(100, requestDetails); count = mySystemDao.performReindexingPass(100);
try { try {
Thread.sleep(DateUtils.MILLIS_PER_SECOND); Thread.sleep(DateUtils.MILLIS_PER_SECOND);
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@ -64,7 +64,6 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
@ -257,7 +256,7 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
txTemplate.execute(new TransactionCallback<Void>() { txTemplate.execute(new TransactionCallback<Void>() {
@Override @Override
public Void doInTransaction(TransactionStatus theStatus) { public Void doInTransaction(TransactionStatus theStatus) {
delete(subscriptionId, new ServletRequestDetails()); delete(subscriptionId, null);
return null; return null;
} }
}); });
@ -265,9 +264,9 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
} }
@Override @Override
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, RequestDetails theRequestDetails) { Date theUpdateTime) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theUpdateHistory, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theRequestDetails); ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime);
Subscription resource = (Subscription) theResource; Subscription resource = (Subscription) theResource;
Long resourceId = theEntity.getId(); Long resourceId = theEntity.getId();
@ -316,8 +315,8 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
} }
@Override @Override
protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { protected void validateResourceForStorage(Subscription theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave, theRequestDetails); super.validateResourceForStorage(theResource, theEntityToSave);
RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource); RuntimeResourceDefinition resDef = validateCriteriaAndReturnResourceDefinition(theResource);

View File

@ -205,7 +205,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
@Override @Override
public Meta metaGetOperation(RequestDetails theRequestDetails) { public Meta metaGetOperation(RequestDetails theRequestDetails) {
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
notifyInterceptors(RestOperationTypeEnum.META, requestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)"; String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)";
@ -264,7 +264,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
@Transactional(propagation = Propagation.REQUIRED) @Transactional(propagation = Propagation.REQUIRED)
@Override @Override
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) { public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext(), theRequestDetails); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
String actionName = "Transaction"; String actionName = "Transaction";
@ -488,7 +488,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource); IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null; Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false, updateTime, theRequestDetails); updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime);
} }
myEntityManager.flush(); myEntityManager.flush();

View File

@ -24,6 +24,9 @@ import java.util.Date;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Required;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
@ -31,22 +34,36 @@ import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.annotation.At; import ca.uhn.fhir.rest.annotation.At;
import ca.uhn.fhir.rest.annotation.GetTags; import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.History; import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Since; import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.util.ParametersUtil;
public class BaseJpaSystemProvider<T, MT> extends BaseJpaProvider { public class BaseJpaSystemProvider<T, MT> extends BaseJpaProvider {
public static final String MARK_ALL_RESOURCES_FOR_REINDEXING = "$mark-all-resources-for-reindexing";
private IFhirSystemDao<T, MT> myDao; private IFhirSystemDao<T, MT> myDao;
public BaseJpaSystemProvider() { public BaseJpaSystemProvider() {
// nothing // nothing
} }
@Required @GetTags
public void setDao(IFhirSystemDao<T, MT> theDao) { public TagList getAllTagsOnServer(HttpServletRequest theRequest, RequestDetails theRequestDetails) {
myDao = theDao; startRequest(theRequest);
try {
return myDao.getAllTags(theRequestDetails);
} finally {
endRequest(theRequest);
}
}
protected IFhirSystemDao<T, MT> getDao() {
return myDao;
} }
@History @History
@ -60,18 +77,9 @@ public class BaseJpaSystemProvider<T, MT> extends BaseJpaProvider {
} }
} }
protected IFhirSystemDao<T, MT> getDao() { @Required
return myDao; public void setDao(IFhirSystemDao<T, MT> theDao) {
} myDao = theDao;
@GetTags
public TagList getAllTagsOnServer(HttpServletRequest theRequest, RequestDetails theRequestDetails) {
startRequest(theRequest);
try {
return myDao.getAllTags(theRequestDetails);
} finally {
endRequest(theRequest);
}
} }
} }

View File

@ -0,0 +1,30 @@
package ca.uhn.fhir.jpa.provider;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.util.ParametersUtil;
public abstract class BaseJpaSystemProviderDstu2Plus<T, MT> extends BaseJpaSystemProvider<T, MT> {
//@formatter:off
@Operation(name=MARK_ALL_RESOURCES_FOR_REINDEXING, idempotent=true, returnParameters= {
@OperationParam(name="status")
})
//@formatter:on
public IBaseResource markAllResourcesForReindexing() {
int count = getDao().markAllResourcesForReindexing();
IBaseParameters retVal = ParametersUtil.newInstance(getContext());
IPrimitiveType<?> string = ParametersUtil.createString(getContext(), "Marked " + count + " resources");
ParametersUtil.addParameterToParameters(getContext(), retVal, string, "status");
return retVal;
}
}

View File

@ -50,7 +50,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle, MetaDt> { public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundle, MetaDt> {
@Autowired() @Autowired()
@Qualifier("mySystemDaoDstu2") @Qualifier("mySystemDaoDstu2")
@ -169,18 +169,6 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle, MetaDt
return retVal; return retVal;
} }
//@formatter:off
@Operation(name="$mark-all-resources-for-reindexing", idempotent=true, returnParameters= {
@OperationParam(name="count", type=IntegerDt.class)
})
//@formatter:on
public Parameters markAllResourcesForReindexing() {
int count = mySystemDao.markAllResourcesForReindexing();
Parameters retVal = new Parameters();
retVal.addParameter().setName("count").setValue(new IntegerDt(count));
return retVal;
}
//@formatter:off //@formatter:off
@Operation(name="$meta", idempotent=true, returnParameters= { @Operation(name="$meta", idempotent=true, returnParameters= {

View File

@ -41,7 +41,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider; import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.OperationParam;
@ -51,7 +51,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class JpaSystemProviderDstu3 extends BaseJpaSystemProvider<Bundle, Meta> { public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundle, Meta> {
@Autowired() @Autowired()
@Qualifier("mySystemDaoDstu3") @Qualifier("mySystemDaoDstu3")
@ -170,19 +170,6 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProvider<Bundle, Meta>
return retVal; return retVal;
} }
//@formatter:off
@Operation(name="$mark-all-resources-for-reindexing", idempotent=true, returnParameters= {
@OperationParam(name="count", type=IntegerType.class)
})
//@formatter:on
public Parameters markAllResourcesForReindexing() {
int count = mySystemDao.markAllResourcesForReindexing();
Parameters retVal = new Parameters();
retVal.addParameter().setName("count").setValue(new IntegerType(count));
return retVal;
}
//@formatter:off //@formatter:off
@Operation(name="$meta", idempotent=true, returnParameters= { @Operation(name="$meta", idempotent=true, returnParameters= {
@OperationParam(name="return", type=Meta.class) @OperationParam(name="return", type=Meta.class)

View File

@ -48,13 +48,15 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class TerminologyUploaderProviderDstu3 extends BaseJpaProvider { public class TerminologyUploaderProviderDstu3 extends BaseJpaProvider {
public static final String UPLOAD_EXTERNAL_CODE_SYSTEM = "$upload-external-code-system";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TerminologyUploaderProviderDstu3.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TerminologyUploaderProviderDstu3.class);
@Autowired @Autowired
private IHapiTerminologyLoaderSvc myTerminologyLoaderSvc; private IHapiTerminologyLoaderSvc myTerminologyLoaderSvc;
//@formatter:off //@formatter:off
@Operation(name = "$upload-external-code-system", idempotent = false, returnParameters= { @Operation(name = UPLOAD_EXTERNAL_CODE_SYSTEM, idempotent = false, returnParameters= {
@OperationParam(name="conceptCount", type=IntegerType.class, min=1) @OperationParam(name="conceptCount", type=IntegerType.class, min=1)
}) })
public Parameters uploadExternalCodeSystem( public Parameters uploadExternalCodeSystem(

View File

@ -146,7 +146,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
public void closing() { public void closing() {
ourLog.info("Deleting subscription {}", mySubscriptionId); ourLog.info("Deleting subscription {}", mySubscriptionId);
try { try {
mySubscriptionDao.delete(mySubscriptionId, new ServletRequestDetails()); mySubscriptionDao.delete(mySubscriptionId, null);
} catch (Exception e) { } catch (Exception e) {
handleFailure(e); handleFailure(e);
} }
@ -233,7 +233,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
} }
try { try {
Subscription subscription = mySubscriptionDao.read(id, new ServletRequestDetails()); Subscription subscription = mySubscriptionDao.read(id, null);
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement(); mySubscriptionId = subscription.getIdElement();
myState = new BoundStaticSubscipriptionState(theSession); myState = new BoundStaticSubscipriptionState(theSession);
@ -270,7 +270,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
} }
} }
IIdType id = mySubscriptionDao.create(subscription, new ServletRequestDetails()).getId(); IIdType id = mySubscriptionDao.create(subscription, null).getId();
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement(); mySubscriptionId = subscription.getIdElement();

View File

@ -146,7 +146,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
public void closing() { public void closing() {
ourLog.info("Deleting subscription {}", mySubscriptionId); ourLog.info("Deleting subscription {}", mySubscriptionId);
try { try {
mySubscriptionDao.delete(mySubscriptionId, new ServletRequestDetails()); mySubscriptionDao.delete(mySubscriptionId, null);
} catch (Exception e) { } catch (Exception e) {
handleFailure(e); handleFailure(e);
} }
@ -233,7 +233,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
} }
try { try {
Subscription subscription = mySubscriptionDao.read(id, new ServletRequestDetails()); Subscription subscription = mySubscriptionDao.read(id, null);
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement(); mySubscriptionId = subscription.getIdElement();
myState = new BoundStaticSubscipriptionState(theSession); myState = new BoundStaticSubscipriptionState(theSession);
@ -270,7 +270,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
} }
} }
IIdType id = mySubscriptionDao.create(subscription, new ServletRequestDetails()).getId(); IIdType id = mySubscriptionDao.create(subscription, null).getId();
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement(); mySubscriptionId = subscription.getIdElement();

View File

@ -101,7 +101,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu2 extends Interc
if (requestId != null && requestId.hasIdPart()) { if (requestId != null && requestId.hasIdPart()) {
Subscription existing; Subscription existing;
try { try {
existing = myDao.read(requestId, new ServletRequestDetails()); existing = myDao.read(requestId, null);
SubscriptionStatusEnum existingStatus = existing.getStatusElement().getValueAsEnum(); SubscriptionStatusEnum existingStatus = existing.getStatusElement().getValueAsEnum();
if (existingStatus != newStatus) { if (existingStatus != newStatus) {
verifyActiveStatus(subscription, newStatus, existingStatus); verifyActiveStatus(subscription, newStatus, existingStatus);

View File

@ -38,7 +38,6 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
/** /**
@ -102,7 +101,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu3 extends Interc
if (requestId != null && requestId.hasIdPart()) { if (requestId != null && requestId.hasIdPart()) {
Subscription existing; Subscription existing;
try { try {
existing = myDao.read(requestId, new ServletRequestDetails()); existing = myDao.read(requestId, null);
SubscriptionStatus existingStatus = existing.getStatusElement().getValue(); SubscriptionStatus existingStatus = existing.getStatusElement().getValue();
if (existingStatus != newStatus) { if (existingStatus != newStatus) {
verifyActiveStatus(subscription, newStatus, existingStatus); verifyActiveStatus(subscription, newStatus, existingStatus);

View File

@ -39,7 +39,6 @@ import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
public class FhirResourceDaoDstu2SubscriptionTest extends BaseJpaDstu2Test { public class FhirResourceDaoDstu2SubscriptionTest extends BaseJpaDstu2Test {
@ -390,7 +389,7 @@ public class FhirResourceDaoDstu2SubscriptionTest extends BaseJpaDstu2Test {
*/ */
mySystemDao.markAllResourcesForReindexing(); mySystemDao.markAllResourcesForReindexing();
mySystemDao.performReindexingPass(100, mySrd); mySystemDao.performReindexingPass(100);
assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources()); assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources());

View File

@ -101,7 +101,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
}); });
assertEquals(null, entity.getIndexStatus()); assertEquals(null, entity.getIndexStatus());
mySystemDao.performReindexingPass(null, mySrd); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
@ -112,7 +112,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
assertEquals(Long.valueOf(1), entity.getIndexStatus()); assertEquals(Long.valueOf(1), entity.getIndexStatus());
// Just make sure this doesn't cause a choke // Just make sure this doesn't cause a choke
mySystemDao.performReindexingPass(100000, mySrd); mySystemDao.performReindexingPass(100000);
// Try making the resource unparseable // Try making the resource unparseable
@ -134,7 +134,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
} }
}); });
mySystemDao.performReindexingPass(null, mySrd); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override

View File

@ -81,7 +81,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
} }
private ServletRequestDetails mockSrd() { private ServletRequestDetails mockSrd() {
return new ServletRequestDetails(); return mySrd;
} }
@Test @Test

View File

@ -390,7 +390,7 @@ public class FhirResourceDaoDstu3SubscriptionTest extends BaseJpaDstu3Test {
*/ */
mySystemDao.markAllResourcesForReindexing(); mySystemDao.markAllResourcesForReindexing();
mySystemDao.performReindexingPass(100, mySrd); mySystemDao.performReindexingPass(100);
assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources()); assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources());

View File

@ -68,7 +68,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB")); .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB"));
//@formatter:on //@formatter:on
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
Set<TermConcept> codes = myTermSvc.findCodesBelow(id.getIdPartAsLong(), id.getVersionIdPartAsLong(), "A"); Set<TermConcept> codes = myTermSvc.findCodesBelow(id.getIdPartAsLong(), id.getVersionIdPartAsLong(), "A");
assertThat(toCodes(codes), containsInAnyOrder("A", "AA", "AB")); assertThat(toCodes(codes), containsInAnyOrder("A", "AA", "AB"));
@ -177,7 +177,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
@ -571,7 +571,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA")) .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB")); .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
//@formatter:on //@formatter:on
myCodeSystemDao.create(codeSystem, new ServletRequestDetails()); myCodeSystemDao.create(codeSystem, mySrd);
createLocalVs(codeSystem); createLocalVs(codeSystem);
} }
@ -590,13 +590,13 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.COMPLETE); codeSystem.setContent(CodeSystemContentMode.COMPLETE);
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
codeSystem = new CodeSystem(); codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.COMPLETE); codeSystem.setContent(CodeSystemContentMode.COMPLETE);
try { try {
myCodeSystemDao.create(codeSystem, new ServletRequestDetails()); myCodeSystemDao.create(codeSystem, mySrd);
fail(); fail();
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage()); assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());

View File

@ -191,7 +191,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
}); });
assertEquals(null, entity.getIndexStatus()); assertEquals(null, entity.getIndexStatus());
mySystemDao.performReindexingPass(null, mySrd); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
@ -202,7 +202,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
assertEquals(Long.valueOf(1), entity.getIndexStatus()); assertEquals(Long.valueOf(1), entity.getIndexStatus());
// Just make sure this doesn't cause a choke // Just make sure this doesn't cause a choke
mySystemDao.performReindexingPass(100000, mySrd); mySystemDao.performReindexingPass(100000);
// Try making the resource unparseable // Try making the resource unparseable
@ -224,7 +224,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
} }
}); });
mySystemDao.performReindexingPass(null, mySrd); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override

View File

@ -32,7 +32,6 @@ import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test { public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {

View File

@ -42,7 +42,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(CS_URL); codeSystem.setUrl(CS_URL);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
@ -109,14 +109,14 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test {
assertThat(mySystemDao.markAllResourcesForReindexing(), greaterThan(0)); assertThat(mySystemDao.markAllResourcesForReindexing(), greaterThan(0));
assertThat(mySystemDao.performReindexingPass(100, mySrd), greaterThan(0)); assertThat(mySystemDao.performReindexingPass(100), greaterThan(0));
} }
private IIdType createCodeSystem() { private IIdType createCodeSystem() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(CS_URL); codeSystem.setUrl(CS_URL);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
@ -173,7 +173,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(CS_URL); codeSystem.setUrl(CS_URL);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
@ -187,7 +187,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test {
cs = new TermCodeSystemVersion(); cs = new TermCodeSystemVersion();
TermConcept parentA = new TermConcept(cs, "ParentA"); TermConcept parentA = new TermConcept(cs, "ParentA");
cs.getConcepts().add(parentA); cs.getConcepts().add(parentA);
id = myCodeSystemDao.update(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); id = myCodeSystemDao.update(codeSystem, mySrd).getId().toUnqualified();
table = myResourceTableDao.findOne(id.getIdPartAsLong()); table = myResourceTableDao.findOne(id.getIdPartAsLong());
cs.setResource(table); cs.setResource(table);
cs.setResourceVersionId(table.getVersion()); cs.setResourceVersionId(table.getVersion());
@ -197,7 +197,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test {
codeSystem = new CodeSystem(); codeSystem = new CodeSystem();
codeSystem.setUrl(CS_URL); codeSystem.setUrl(CS_URL);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
table = myResourceTableDao.findOne(id.getIdPartAsLong()); table = myResourceTableDao.findOne(id.getIdPartAsLong());
cs.setResource(table); cs.setResource(table);
cs.setResourceVersionId(table.getVersion()); cs.setResourceVersionId(table.getVersion());

View File

@ -10,7 +10,6 @@ import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
@ -19,6 +18,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu1; import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu1;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
@Configuration @Configuration
@Import(CommonConfig.class) @Import(CommonConfig.class)
@ -38,6 +39,11 @@ public class TestDstu1Config extends BaseJavaConfigDstu1 {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();
} }
@Bean
public IServerInterceptor securityInterceptor() {
return new PublicSecurityInterceptor();
}
@Bean() @Bean()
public DaoConfig daoConfig() { public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig(); DaoConfig retVal = new DaoConfig();

View File

@ -23,6 +23,7 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2; import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
@Configuration @Configuration
@Import(CommonConfig.class) @Import(CommonConfig.class)
@ -46,6 +47,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();
} }
@Bean
public IServerInterceptor securityInterceptor() {
return new PublicSecurityInterceptor();
}
@Bean() @Bean()
public DaoConfig daoConfig() { public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig(); DaoConfig retVal = new DaoConfig();

View File

@ -28,6 +28,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
import ca.uhn.fhir.validation.ResultSeverityEnum; import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
@Configuration @Configuration
@Import(CommonConfig.class) @Import(CommonConfig.class)
@ -57,6 +58,11 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
return retVal; return retVal;
} }
@Bean
public IServerInterceptor securityInterceptor() {
return new PublicSecurityInterceptor();
}
@Bean(name = "myPersistenceDataSourceDstu3", destroyMethod = "close") @Bean(name = "myPersistenceDataSourceDstu3", destroyMethod = "close")
@DependsOn("dbServer") @DependsOn("dbServer")
public DataSource dataSource() { public DataSource dataSource() {

View File

@ -0,0 +1,61 @@
package ca.uhn.fhirtest.interceptor;
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule;
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
public class PublicSecurityInterceptor extends AuthorizationInterceptor {
private HashSet<String> myTokens;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PublicSecurityInterceptor.class);
public PublicSecurityInterceptor() {
String passwordsString = System.getProperty("fhir.tdlpass");
String[] passwords = passwordsString.split(",");
myTokens = new HashSet<String>(Arrays.asList(passwords));
ourLog.info("We have {} valid security tokens", myTokens.size());
}
@Override
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
String authHeader = theRequestDetails.getHeader("Authorization");
//@formatter:off
if (isBlank(authHeader)) {
return new RuleBuilder()
.deny().operation().named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING).onServer().andThen()
.deny().operation().named(TerminologyUploaderProviderDstu3.UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andThen()
.allowAll()
.build();
}
//@formatter:off
if (!authHeader.startsWith("Bearer ")) {
throw new ForbiddenOperationException("Invalid bearer token, must be in the form \"Authorization: Bearer [token]\"");
}
String token = authHeader.substring("Bearer ".length()).trim();
if (!myTokens.contains(token)) {
ourLog.error("Invalid token '{}' - Valid are: {}", token, myTokens);
throw new ForbiddenOperationException("Unknown/expired bearer token");
}
ourLog.info("User logged in with bearer token: " + token.substring(0, 4) + "...");
return new RuleBuilder()
.allowAll()
.build();
}
}

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.rest.server.interceptor.auth; package ca.uhn.fhir.rest.server.interceptor.auth;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -32,7 +33,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
@ -40,11 +40,13 @@ import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.annotation.Create; import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete; import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.IdParam;
@ -55,14 +57,18 @@ import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Transaction; import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.TransactionParam; import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.annotation.Update; import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.method.IRequestOperationCallback; import ca.uhn.fhir.rest.method.IRequestOperationCallback;
import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.AddProfileTagEnum; import ca.uhn.fhir.rest.server.AddProfileTagEnum;
import ca.uhn.fhir.rest.server.Constants; 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.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
@ -158,6 +164,14 @@ public class AuthorizationInterceptorDstu2Test {
assertThat(response, containsString("Access denied by rule: Rule 1")); assertThat(response, containsString("Access denied by rule: Rule 1"));
assertEquals(403, status.getStatusLine().getStatusCode()); assertEquals(403, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod); assertTrue(ourHitMethod);
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate");
status = ourClient.execute(httpGet);
extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
} }
@Test @Test
@ -404,6 +418,15 @@ public class AuthorizationInterceptorDstu2Test {
assertThat(response, containsString("Access denied by rule: Default Rule")); assertThat(response, containsString("Access denied by rule: Default Rule"));
assertEquals(403, status.getStatusLine().getStatusCode()); assertEquals(403, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod); assertTrue(ourHitMethod);
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
ourLog.info(response);
assertThat(response, containsString("Access denied by rule: Default Rule"));
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
} }
@Test @Test
@ -990,7 +1013,13 @@ public class AuthorizationInterceptorDstu2Test {
public static class DummyPatientResourceProvider implements IResourceProvider { public static class DummyPatientResourceProvider implements IResourceProvider {
@Create() @Create()
public MethodOutcome create(@ResourceParam Patient theResource) { public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
if (isNotBlank(theConditionalUrl)) {
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails);
}
ourHitMethod = true; ourHitMethod = true;
theResource.setId("Patient/1/_history/1"); theResource.setId("Patient/1/_history/1");
MethodOutcome retVal = new MethodOutcome(); MethodOutcome retVal = new MethodOutcome();
@ -999,6 +1028,7 @@ public class AuthorizationInterceptorDstu2Test {
return retVal; return retVal;
} }
@Delete() @Delete()
public MethodOutcome delete(IRequestOperationCallback theRequestOperationCallback, @IdParam IdDt theId) { public MethodOutcome delete(IRequestOperationCallback theRequestOperationCallback, @IdParam IdDt theId) {
ourHitMethod = true; ourHitMethod = true;
@ -1009,6 +1039,24 @@ public class AuthorizationInterceptorDstu2Test {
return retVal; return retVal;
} }
@Validate
public MethodOutcome validate(@ResourceParam Patient theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
@Validate.Profile String theProfile, RequestDetails theRequestDetails) {
ourHitMethod = true;
OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDiagnostics("OK");
return new MethodOutcome(oo);
}
@Validate
public MethodOutcome validate(@ResourceParam Patient theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
@Validate.Profile String theProfile, RequestDetails theRequestDetails) {
ourHitMethod = true;
OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDiagnostics("OK");
return new MethodOutcome(oo);
}
@Override @Override
public Class<? extends IResource> getResourceType() { public Class<? extends IResource> getResourceType() {
return Patient.class; return Patient.class;

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -3,7 +3,7 @@
xmlns="http://maven.apache.org/DECORATION/1.3.0" xmlns="http://maven.apache.org/DECORATION/1.3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd"
name="HAPI"> name="HAPI FHIR">
<!-- <!--
<bannerLeft> <bannerLeft>
@ -46,7 +46,7 @@
HAPI stylesheet comes after because it overwrites the Syntax Highlighter HAPI stylesheet comes after because it overwrites the Syntax Highlighter
font size font size
--> -->
<link rel="shortcut icon" href="http://jamesagnew.github.io/hapi-fhir/images/favicon.png" /> <link rel="shortcut icon" href="http://hapifhir.io/favicon.png" />
<link rel="stylesheet" type="text/css" href="hapi.css" /> <link rel="stylesheet" type="text/css" href="hapi.css" />
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" /> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
@ -218,7 +218,7 @@
<name><![CDATA[ <name><![CDATA[
<span class="color-highlight">HAPI</span> FHIR <span class="color-highlight">HAPI</span> FHIR
]]></name> ]]></name>
<href>http://jamesagnew.github.io/hapi-fhir/</href> <href>http://hapifhir.io/</href>
</brand> </brand>
<titleTemplate>%2$s - HAPI FHIR</titleTemplate> <titleTemplate>%2$s - HAPI FHIR</titleTemplate>
</reflowSkin> </reflowSkin>

View File

@ -118,23 +118,54 @@
the response from the server in order to determine whether "read" operations the response from the server in order to determine whether "read" operations
are legal. are legal.
</p> </p>
</subsection>
<subsection name="Authorizing Read Operations">
<p> <p>
This approach has limitations however: If a request has a conditional operation, When authorizing a read operation, the AuthorizationInterceptor
such as a delete operation which uses a search URL, or a create operation which always allows client code to execute and generate a response.
uses an <code>If-None-Exist</code> header, the interceptor will not know the It then examines the response that would be returned before
actual target until the server actually processes the request. actually returning it to the client, and if rules do not permit
that data to be shown to the client the interceptor aborts the
request.
</p> </p>
<p> <p>
For better security, individual resource providers should notify interceptors Note that there are performance implications to this mechanism,
about their actual targets in the event of any "write" operations (create, since an unauthorized user can still cause the server to fetch data
operations embedded in transactions, etc.) even if they won't get to see it. This mechanism should be comprehensive
however, since it will prevent clients from using various features
in FHIR (e.g. <code>_include</code> or <code>_revinclude</code>) to
"trick" the server into showing them date they shouldn't be allowed to
see.
</p> </p>
<p> <p>
The mechanism for doing this isn't yet fully documented, this will be improved See the following diagram for an example of how this works.
over the next release cycle (post 1.5). Please get in touch on our google group
if you want to help!
</p> </p>
<img src="./images/hapi_authorizationinterceptor_read_normal.svg" alt="Write Authorization"/>
</subsection>
<subsection name="Authorizing Write Operations">
<p>
Write operations (create, update, etc.) are typically authorized
by the interceptor by examining the parsed URL and making a decision
about whether to authorize the operation before allowing Resource Provider
code to proceed. This means that client code will not have a chance to execute
and create resources that the client does not have permissions to create.
</p>
<p>
See the following diagram for an example of how this works.
</p>
<img src="./images/hapi_authorizationinterceptor_write_normal.svg" alt="Write Authorization"/>
</subsection> </subsection>
</section> </section>