Remove ActionRequestDetails (#3527)
* Add test * Add test * Start removing unneeded things * Fixes * Add changelog * Test fix * Address LGTM issues * Resolve fixme * Address review comment * Add changelog * Update doc * Test fixes
This commit is contained in:
parent
3bab3544ec
commit
917cf8d062
|
@ -344,9 +344,6 @@ public enum Pointcut implements IPointcut {
|
||||||
* <li>
|
* <li>
|
||||||
* ca.uhn.fhir.rest.api.RestOperationTypeEnum - The type of operation that the FHIR server has determined that the client is trying to invoke
|
* ca.uhn.fhir.rest.api.RestOperationTypeEnum - The type of operation that the FHIR server has determined that the client is trying to invoke
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
|
||||||
* ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails - This parameter is provided for legacy reasons only and will be removed in the future. Do not use.
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
* </ul>
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -360,8 +357,7 @@ public enum Pointcut implements IPointcut {
|
||||||
SERVER_INCOMING_REQUEST_PRE_HANDLED(void.class,
|
SERVER_INCOMING_REQUEST_PRE_HANDLED(void.class,
|
||||||
"ca.uhn.fhir.rest.api.server.RequestDetails",
|
"ca.uhn.fhir.rest.api.server.RequestDetails",
|
||||||
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
|
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
|
||||||
"ca.uhn.fhir.rest.api.RestOperationTypeEnum",
|
"ca.uhn.fhir.rest.api.RestOperationTypeEnum"
|
||||||
"ca.uhn.fhir.rest.server.interceptor.IServerInterceptor$ActionRequestDetails"
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,47 +62,25 @@ public class UrlUtil {
|
||||||
private static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*";
|
private static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*";
|
||||||
private static final Escaper PARAMETER_ESCAPER = new PercentEscaper(URL_FORM_PARAMETER_OTHER_SAFE_CHARS, false);
|
private static final Escaper PARAMETER_ESCAPER = new PercentEscaper(URL_FORM_PARAMETER_OTHER_SAFE_CHARS, false);
|
||||||
|
|
||||||
public static String sanitizeBaseUrl(String theBaseUrl) {
|
/**
|
||||||
return theBaseUrl.replaceAll("[^a-zA-Z0-9:/._-]", "");
|
* Non instantiable
|
||||||
|
*/
|
||||||
|
private UrlUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UrlParts {
|
/**
|
||||||
private String myParams;
|
* Cleans up a value that will be serialized as an HTTP header. This method:
|
||||||
private String myResourceId;
|
* <p>
|
||||||
private String myResourceType;
|
* - Strips any newline (\r or \n) characters
|
||||||
private String myVersionId;
|
*
|
||||||
|
* @since 6.2.0
|
||||||
|
*/
|
||||||
|
public static String sanitizeHeaderValue(String theHeader) {
|
||||||
|
return theHeader.replace("\n", "").replace("\r", "");
|
||||||
|
}
|
||||||
|
|
||||||
public String getParams() {
|
public static String sanitizeBaseUrl(String theBaseUrl) {
|
||||||
return myParams;
|
return theBaseUrl.replaceAll("[^a-zA-Z0-9:/._-]", "");
|
||||||
}
|
|
||||||
|
|
||||||
public void setParams(String theParams) {
|
|
||||||
myParams = theParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResourceId() {
|
|
||||||
return myResourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResourceId(String theResourceId) {
|
|
||||||
myResourceId = theResourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResourceType() {
|
|
||||||
return myResourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResourceType(String theResourceType) {
|
|
||||||
myResourceType = theResourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVersionId() {
|
|
||||||
return myVersionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVersionId(String theVersionId) {
|
|
||||||
myVersionId = theVersionId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,7 +164,6 @@ public class UrlUtil {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isAbsolute(String theValue) {
|
public static boolean isAbsolute(String theValue) {
|
||||||
String value = theValue.toLowerCase();
|
String value = theValue.toLowerCase();
|
||||||
return value.startsWith("http://") || value.startsWith("https://");
|
return value.startsWith("http://") || value.startsWith("https://");
|
||||||
|
@ -570,4 +547,43 @@ public class UrlUtil {
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class UrlParts {
|
||||||
|
private String myParams;
|
||||||
|
private String myResourceId;
|
||||||
|
private String myResourceType;
|
||||||
|
private String myVersionId;
|
||||||
|
|
||||||
|
public String getParams() {
|
||||||
|
return myParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(String theParams) {
|
||||||
|
myParams = theParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResourceId() {
|
||||||
|
return myResourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceId(String theResourceId) {
|
||||||
|
myResourceId = theResourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResourceType() {
|
||||||
|
return myResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceType(String theResourceType) {
|
||||||
|
myResourceType = theResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersionId() {
|
||||||
|
return myVersionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersionId(String theVersionId) {
|
||||||
|
myVersionId = theVersionId;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
type: remove
|
||||||
|
issue: 3527
|
||||||
|
title: "The `ActionRequestDetails` class has been dropped (it has been deprecated
|
||||||
|
since HAPI FHIR 4.0.0). This class was used as a parameter to the
|
||||||
|
`SERVER_INCOMING_REQUEST_PRE_HANDLED` interceptor pointcut, but can be
|
||||||
|
replaced in any existing client code with `RequestDetails`. This change
|
||||||
|
also removes an undocumented behaviour where the JPA server internally
|
||||||
|
invoked the `SERVER_INCOMING_REQUEST_PRE_HANDLED` a second time from
|
||||||
|
within various processing methods. This behaviour caused performance
|
||||||
|
problems for some interceptors (e.g. `SearchNarrowingInterceptor`) and
|
||||||
|
no longer offers any benefit so it is being removed."
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: perf
|
||||||
|
issue: 3527
|
||||||
|
title: "When using SearchNarrowingInterceptor, FHIR batch operations with a large number
|
||||||
|
of conditional create/update entries exhibited very slow performance due to an
|
||||||
|
unnecessary nested loop. This has been corrected."
|
|
@ -82,7 +82,6 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
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.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.rest.server.util.ResourceSearchParams;
|
import ca.uhn.fhir.rest.server.util.ResourceSearchParams;
|
||||||
|
@ -224,28 +223,18 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
@Autowired
|
@Autowired
|
||||||
ExpungeService myExpungeService;
|
ExpungeService myExpungeService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private HistoryBuilderFactory myHistoryBuilderFactory;
|
|
||||||
@Autowired
|
|
||||||
private DaoConfig myConfig;
|
private DaoConfig myConfig;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PlatformTransactionManager myPlatformTransactionManager;
|
|
||||||
@Autowired
|
|
||||||
private ISearchCacheSvc mySearchCacheSvc;
|
|
||||||
@Autowired
|
|
||||||
private ISearchParamPresenceSvc mySearchParamPresenceSvc;
|
private ISearchParamPresenceSvc mySearchParamPresenceSvc;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SearchParamWithInlineReferencesExtractor mySearchParamWithInlineReferencesExtractor;
|
private SearchParamWithInlineReferencesExtractor mySearchParamWithInlineReferencesExtractor;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DaoSearchParamSynchronizer myDaoSearchParamSynchronizer;
|
private DaoSearchParamSynchronizer myDaoSearchParamSynchronizer;
|
||||||
@Autowired
|
|
||||||
private SearchBuilderFactory mySearchBuilderFactory;
|
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private ApplicationContext myApplicationContext;
|
private ApplicationContext myApplicationContext;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PartitionSettings myPartitionSettings;
|
private PartitionSettings myPartitionSettings;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RequestPartitionHelperSvc myRequestPartitionHelperSvc;
|
|
||||||
@Autowired
|
|
||||||
private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory;
|
private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPartitionLookupSvc myPartitionLookupSvc;
|
private IPartitionLookupSvc myPartitionLookupSvc;
|
||||||
|
@ -272,7 +261,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
|
public void setApplicationContext(@Nonnull ApplicationContext theApplicationContext) throws BeansException {
|
||||||
/*
|
/*
|
||||||
* We do a null check here because Smile's module system tries to
|
* We do a null check here because Smile's module system tries to
|
||||||
* initialize the application context twice if two modules depend on
|
* initialize the application context twice if two modules depend on
|
||||||
|
@ -363,9 +352,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
private Set<ResourceTag> getAllTagDefinitions(ResourceTable theEntity) {
|
private Set<ResourceTag> getAllTagDefinitions(ResourceTable theEntity) {
|
||||||
HashSet<ResourceTag> retVal = Sets.newHashSet();
|
HashSet<ResourceTag> retVal = Sets.newHashSet();
|
||||||
if (theEntity.isHasTags()) {
|
if (theEntity.isHasTags()) {
|
||||||
for (ResourceTag next : theEntity.getTags()) {
|
retVal.addAll(theEntity.getTags());
|
||||||
retVal.add(next);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -1505,9 +1492,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
oldResource = toResource(entity, false);
|
oldResource = toResource(entity, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theRequest.getServer() != null) {
|
|
||||||
ActionRequestDetails actionRequestDetails = new ActionRequestDetails(theRequest, theResource, theResourceId.getResourceType(), theResourceId);
|
|
||||||
}
|
|
||||||
notifyInterceptors(theRequest, theResource, oldResource, theTransactionDetails, true);
|
notifyInterceptors(theRequest, theResource, oldResource, theTransactionDetails, true);
|
||||||
|
|
||||||
ResourceTable savedEntity = updateEntity(theRequest, theResource, entity, null, true, false, theTransactionDetails, false, false);
|
ResourceTable savedEntity = updateEntity(theRequest, theResource, entity, null, true, false, theTransactionDetails, false, false);
|
||||||
|
@ -1684,13 +1668,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
// now at least set it to something useful for the interceptors
|
// now at least set it to something useful for the interceptors
|
||||||
theResource.setId(entity.getIdDt());
|
theResource.setId(entity.getIdDt());
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails;
|
|
||||||
if (theRequestDetails != null && theRequestDetails.getServer() != null) {
|
|
||||||
requestDetails = new ActionRequestDetails(theRequestDetails, theResource, theResourceId.getResourceType(), theResourceId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify IServerOperationInterceptors about pre-action call
|
// Notify IServerOperationInterceptors about pre-action call
|
||||||
notifyInterceptors(theRequestDetails, theResource, theOldResource, theTransactionDetails, true);
|
notifyInterceptors(theRequestDetails, theResource, theOldResource, theTransactionDetails, true);
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,6 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.util.ObjectUtil;
|
import ca.uhn.fhir.util.ObjectUtil;
|
||||||
|
@ -126,7 +125,7 @@ import org.springframework.beans.factory.annotation.Required;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
@ -155,9 +154,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends BaseHapiFhirDao<T> implements IFhirResourceDao<T> {
|
public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends BaseHapiFhirDao<T> implements IFhirResourceDao<T> {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class);
|
|
||||||
public static final String BASE_RESOURCE_NAME = "resource";
|
public static final String BASE_RESOURCE_NAME = "resource";
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class);
|
||||||
@Autowired
|
@Autowired
|
||||||
protected PlatformTransactionManager myPlatformTransactionManager;
|
protected PlatformTransactionManager myPlatformTransactionManager;
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
|
@ -309,12 +307,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), theResource);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
String resourceIdBeforeStorage = theResource.getIdElement().getIdPart();
|
String resourceIdBeforeStorage = theResource.getIdElement().getIdPart();
|
||||||
boolean resourceHadIdBeforeStorage = isNotBlank(resourceIdBeforeStorage);
|
boolean resourceHadIdBeforeStorage = isNotBlank(resourceIdBeforeStorage);
|
||||||
boolean resourceIdWasServerAssigned = theResource.getUserData(JpaConstants.RESOURCE_ID_SERVER_ASSIGNED) == Boolean.TRUE;
|
boolean resourceIdWasServerAssigned = theResource.getUserData(JpaConstants.RESOURCE_ID_SERVER_ASSIGNED) == Boolean.TRUE;
|
||||||
|
@ -584,12 +576,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
preDelete(resourceToDelete, entity, theRequestDetails);
|
preDelete(resourceToDelete, entity, theRequestDetails);
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
if (theRequestDetails != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceTable savedEntity = updateEntityForDelete(theRequestDetails, theTransactionDetails, entity);
|
ResourceTable savedEntity = updateEntityForDelete(theRequestDetails, theTransactionDetails, entity);
|
||||||
resourceToDelete.setId(entity.getIdDt());
|
resourceToDelete.setId(entity.getIdDt());
|
||||||
|
|
||||||
|
@ -704,20 +690,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
myDeleteConflictService.validateOkToDelete(theDeleteConflicts, entity, false, theRequest, transactionDetails);
|
myDeleteConflictService.validateOkToDelete(theDeleteConflicts, entity, false, theRequest, transactionDetails);
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
IdDt idToDelete = entity.getIdDt();
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, idToDelete.getResourceType(), idToDelete);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform delete
|
// Perform delete
|
||||||
|
|
||||||
updateEntityForDelete(theRequest, transactionDetails, entity);
|
updateEntityForDelete(theRequest, transactionDetails, entity);
|
||||||
resourceToDelete.setId(entity.getIdDt());
|
resourceToDelete.setId(entity.getIdDt());
|
||||||
|
|
||||||
// Notify JPA interceptors
|
// Notify JPA interceptors
|
||||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeCommit(boolean readOnly) {
|
public void beforeCommit(boolean readOnly) {
|
||||||
HookParams hookParams = new HookParams()
|
HookParams hookParams = new HookParams()
|
||||||
|
@ -937,10 +916,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails);
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
IBundleProvider retVal = super.history(theRequestDetails, myResourceName, null, theSince, theUntil, theOffset);
|
IBundleProvider retVal = super.history(theRequestDetails, myResourceName, null, theSince, theUntil, theOffset);
|
||||||
ourLog.debug("Processed history on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
ourLog.debug("Processed history on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
||||||
|
@ -950,12 +925,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public IBundleProvider history(final IIdType theId, final Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequest) {
|
public IBundleProvider history(final IIdType theId, final Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequest) {
|
||||||
if (theRequest != null) {
|
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
|
||||||
IIdType id = theId.withResourceType(myResourceName).toUnqualifiedVersionless();
|
IIdType id = theId.withResourceType(myResourceName).toUnqualifiedVersionless();
|
||||||
|
@ -990,7 +959,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
addAllResourcesTypesToReindex(theBase, theRequestDetails, params);
|
addAllResourcesTypesToReindex(theBase, theRequestDetails, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadPartitionIdRequestDetails details= new ReadPartitionIdRequestDetails(null, RestOperationTypeEnum.EXTENDED_OPERATION_SERVER, null, null, null);
|
ReadPartitionIdRequestDetails details = new ReadPartitionIdRequestDetails(null, RestOperationTypeEnum.EXTENDED_OPERATION_SERVER, null, null, null);
|
||||||
RequestPartitionId requestPartition = myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, null, details);
|
RequestPartitionId requestPartition = myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, null, details);
|
||||||
params.setRequestPartitionId(requestPartition);
|
params.setRequestPartitionId(requestPartition);
|
||||||
|
|
||||||
|
@ -1034,12 +1003,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequest) {
|
public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequest) {
|
||||||
TransactionDetails transactionDetails = new TransactionDetails();
|
TransactionDetails transactionDetails = new TransactionDetails();
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theResourceId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
@ -1069,12 +1032,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequest) {
|
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequest) {
|
||||||
TransactionDetails transactionDetails = new TransactionDetails();
|
TransactionDetails transactionDetails = new TransactionDetails();
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theResourceId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
@ -1102,12 +1059,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequest) {
|
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequest) {
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<TagDefinition> tagDefs = new HashSet<>();
|
Set<TagDefinition> tagDefs = new HashSet<>();
|
||||||
BaseHasResource entity = readEntity(theId, theRequest);
|
BaseHasResource entity = readEntity(theId, theRequest);
|
||||||
for (BaseTag next : entity.getTags()) {
|
for (BaseTag next : entity.getTags()) {
|
||||||
|
@ -1124,12 +1075,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, RequestDetails theRequestDetails) {
|
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
if (theRequestDetails != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
|
|
||||||
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)";
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
q.setParameter("res_type", myResourceName);
|
q.setParameter("res_type", myResourceName);
|
||||||
|
@ -1273,13 +1218,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
public T doRead(IIdType theId, RequestDetails theRequest, boolean theDeletedOk) {
|
public T doRead(IIdType theId, RequestDetails theRequest, boolean theDeletedOk) {
|
||||||
assert TransactionSynchronizationManager.isActualTransactionActive();
|
assert TransactionSynchronizationManager.isActualTransactionActive();
|
||||||
|
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null && theRequest.getServer() != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theId);
|
|
||||||
RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ;
|
|
||||||
notifyInterceptors(operationType, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
BaseHasResource entity = readEntity(theId, theRequest);
|
BaseHasResource entity = readEntity(theId, theRequest);
|
||||||
validateResourceType(entity);
|
validateResourceType(entity);
|
||||||
|
@ -1485,12 +1423,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequest) {
|
public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequest) {
|
||||||
// Notify interceptors
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getResourceName(), theId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
BaseHasResource entity = readEntity(theId, theRequest);
|
BaseHasResource entity = readEntity(theId, theRequest);
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
@ -1537,7 +1469,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
if (theParams.getSearchContainedMode() != SearchContainedModeEnum.FALSE && !myModelConfig.isIndexOnContainedResources()) {
|
if (theParams.getSearchContainedMode() != SearchContainedModeEnum.FALSE && !myModelConfig.isIndexOnContainedResources()) {
|
||||||
throw new MethodNotAllowedException(Msg.code(984) + "Searching with _contained mode enabled is not enabled on this server");
|
throw new MethodNotAllowedException(Msg.code(984) + "Searching with _contained mode enabled is not enabled on this server");
|
||||||
}
|
}
|
||||||
|
|
||||||
translateListSearchParams(theParams);
|
translateListSearchParams(theParams);
|
||||||
|
|
||||||
notifySearchInterceptors(theParams, theRequest);
|
notifySearchInterceptors(theParams, theRequest);
|
||||||
|
@ -1587,8 +1519,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
private void notifySearchInterceptors(SearchParameterMap theParams, RequestDetails theRequest) {
|
private void notifySearchInterceptors(SearchParameterMap theParams, RequestDetails theRequest) {
|
||||||
if (theRequest != null) {
|
if (theRequest != null) {
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), getResourceName(), null);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
|
||||||
|
|
||||||
if (theRequest.isSubRequest()) {
|
if (theRequest.isSubRequest()) {
|
||||||
Integer max = getConfig().getMaximumSearchResultCountInTransaction();
|
Integer max = getConfig().getMaximumSearchResultCountInTransaction();
|
||||||
|
@ -1928,11 +1858,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequest) {
|
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequest) {
|
||||||
TransactionDetails transactionDetails = new TransactionDetails();
|
TransactionDetails transactionDetails = new TransactionDetails();
|
||||||
|
|
||||||
if (theRequest != null) {
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, theResource, null, theId);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theMode == ValidationModeEnum.DELETE) {
|
if (theMode == ValidationModeEnum.DELETE) {
|
||||||
if (theId == null || theId.hasIdPart() == false) {
|
if (theId == null || theId.hasIdPart() == false) {
|
||||||
throw new InvalidRequestException(Msg.code(991) + "No ID supplied. ID is required when validating with mode=DELETE");
|
throw new InvalidRequestException(Msg.code(991) + "No ID supplied. ID is required when validating with mode=DELETE");
|
||||||
|
|
|
@ -10,12 +10,10 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||||
import ca.uhn.fhir.jpa.util.QueryChunker;
|
import ca.uhn.fhir.jpa.util.QueryChunker;
|
||||||
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
@ -62,8 +60,8 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends BaseHapiFhirDao<IBaseResource> implements IFhirSystemDao<T, MT> {
|
public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends BaseHapiFhirDao<IBaseResource> implements IFhirSystemDao<T, MT> {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirSystemDao.class);
|
|
||||||
public static final Predicate[] EMPTY_PREDICATE_ARRAY = new Predicate[0];
|
public static final Predicate[] EMPTY_PREDICATE_ARRAY = new Predicate[0];
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirSystemDao.class);
|
||||||
public ResourceCountCache myResourceCountsCache;
|
public ResourceCountCache myResourceCountsCache;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransactionProcessor myTransactionProcessor;
|
private TransactionProcessor myTransactionProcessor;
|
||||||
|
@ -125,12 +123,6 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
public IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails) {
|
||||||
if (theRequestDetails != null) {
|
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
IBundleProvider retVal = super.history(theRequestDetails, null, null, theSince, theUntil, theOffset);
|
IBundleProvider retVal = super.history(theRequestDetails, null, null, theSince, theUntil, theOffset);
|
||||||
ourLog.info("Processed global history in {}ms", w.getMillisAndRestart());
|
ourLog.info("Processed global history in {}ms", w.getMillisAndRestart());
|
||||||
|
@ -242,8 +234,6 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,13 @@ import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
import ca.uhn.fhir.rest.api.CacheControlDirective;
|
import ca.uhn.fhir.rest.api.CacheControlDirective;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
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;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -91,9 +92,6 @@ public class FhirResourceDaoPatientDstu2 extends BaseHapiFhirResourceDao<Patient
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.SUPPORTS)
|
@Transactional(propagation = Propagation.SUPPORTS)
|
||||||
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, RequestDetails theRequestDetails, PatientEverythingParameters theQueryParams, IIdType theId) {
|
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, RequestDetails theRequestDetails, PatientEverythingParameters theQueryParams, IIdType theId) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
|
|
||||||
TokenOrListParam id = new TokenOrListParam().add(new TokenParam(theId.getIdPart()));
|
TokenOrListParam id = new TokenOrListParam().add(new TokenParam(theId.getIdPart()));
|
||||||
return doEverythingOperation(id, theQueryParams.getCount(), theQueryParams.getOffset(), theQueryParams.getLastUpdated(), theQueryParams.getSort(), theQueryParams.getContent(), theQueryParams.getNarrative(), theQueryParams.getFilter(), theQueryParams.getTypes(), theRequestDetails);
|
return doEverythingOperation(id, theQueryParams.getCount(), theQueryParams.getOffset(), theQueryParams.getLastUpdated(), theQueryParams.getSort(), theQueryParams.getContent(), theQueryParams.getNarrative(), theQueryParams.getFilter(), theQueryParams.getTypes(), theRequestDetails);
|
||||||
}
|
}
|
||||||
|
@ -101,10 +99,6 @@ public class FhirResourceDaoPatientDstu2 extends BaseHapiFhirResourceDao<Patient
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.SUPPORTS)
|
@Transactional(propagation = Propagation.SUPPORTS)
|
||||||
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, RequestDetails theRequestDetails, PatientEverythingParameters theQueryParams, TokenOrListParam theIds) {
|
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, RequestDetails theRequestDetails, PatientEverythingParameters theQueryParams, TokenOrListParam theIds) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
|
|
||||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
|
|
||||||
|
|
||||||
return doEverythingOperation(theIds, theQueryParams.getCount(), theQueryParams.getOffset(), theQueryParams.getLastUpdated(), theQueryParams.getSort(), theQueryParams.getContent(), theQueryParams.getNarrative(), theQueryParams.getFilter(), theQueryParams.getTypes(), theRequestDetails);
|
return doEverythingOperation(theIds, theQueryParams.getCount(), theQueryParams.getOffset(), theQueryParams.getLastUpdated(), theQueryParams.getSort(), theQueryParams.getContent(), theQueryParams.getNarrative(), theQueryParams.getFilter(), theQueryParams.getTypes(), theRequestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,7 @@ package ca.uhn.fhir.jpa.dao;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||||
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.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
@ -36,10 +34,6 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetaDt metaGetOperation(RequestDetails theRequestDetails) {
|
public MetaDt metaGetOperation(RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
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)";
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
|
@ -25,7 +25,6 @@ import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
@ -45,10 +44,6 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
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)";
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
|
@ -23,9 +23,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.Meta;
|
import org.hl7.fhir.r4.model.Meta;
|
||||||
|
@ -38,10 +36,6 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
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)";
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
|
@ -23,9 +23,7 @@ package ca.uhn.fhir.jpa.dao.r5;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.r5.model.Bundle;
|
import org.hl7.fhir.r5.model.Bundle;
|
||||||
import org.hl7.fhir.r5.model.Meta;
|
import org.hl7.fhir.r5.model.Meta;
|
||||||
|
@ -40,10 +38,6 @@ public class FhirSystemDaoR5 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
public Meta metaGetOperation(RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails);
|
|
||||||
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)";
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
|
@ -224,8 +224,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
|
||||||
|
|
||||||
transaction(bundle);
|
transaction(bundle);
|
||||||
|
|
||||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(2)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
||||||
assertEquals(RestOperationTypeEnum.CREATE, myParamsCaptor.getValue().get(RestOperationTypeEnum.class));
|
assertEquals(RestOperationTypeEnum.TRANSACTION, myParamsCaptor.getValue().get(RestOperationTypeEnum.class));
|
||||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED), myParamsCaptor.capture());
|
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED), myParamsCaptor.capture());
|
||||||
|
|
||||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED), myParamsCaptor.capture());
|
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED), myParamsCaptor.capture());
|
||||||
|
@ -326,9 +326,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
|
||||||
entry.getRequest().setIfNoneExist("Patient?name=" + methodName);
|
entry.getRequest().setIfNoneExist("Patient?name=" + methodName);
|
||||||
transaction(bundle);
|
transaction(bundle);
|
||||||
|
|
||||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(2)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
||||||
assertEquals(RestOperationTypeEnum.TRANSACTION, myParamsCaptor.getAllValues().get(0).get(RestOperationTypeEnum.class));
|
assertEquals(RestOperationTypeEnum.TRANSACTION, myParamsCaptor.getAllValues().get(0).get(RestOperationTypeEnum.class));
|
||||||
assertEquals(RestOperationTypeEnum.UPDATE, myParamsCaptor.getAllValues().get(1).get(RestOperationTypeEnum.class));
|
|
||||||
verify(interceptor, times(0)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED), any());
|
verify(interceptor, times(0)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED), any());
|
||||||
verify(interceptor, times(0)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED), any());
|
verify(interceptor, times(0)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED), any());
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ import ca.uhn.fhir.batch2.jobs.expunge.DeleteExpungeProvider;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.Hook;
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
|
import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.IPointcut;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.BinaryResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.BinaryResourceProvider;
|
||||||
|
@ -13,6 +16,7 @@ import ca.uhn.fhir.jpa.rp.r4.ObservationResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.OrganizationResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.OrganizationResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.PatientResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.PatientResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.PractitionerResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.PractitionerResourceProvider;
|
||||||
|
import ca.uhn.fhir.jpa.rp.r4.PractitionerRoleResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.r4.ServiceRequestResourceProvider;
|
import ca.uhn.fhir.jpa.rp.r4.ServiceRequestResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||||
|
@ -21,6 +25,7 @@ import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
|
||||||
|
@ -31,6 +36,8 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizedList;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.auth.SearchNarrowingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.test.utilities.BatchJobHelper;
|
import ca.uhn.fhir.test.utilities.BatchJobHelper;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
|
@ -58,6 +65,7 @@ import org.hl7.fhir.r4.hapi.rest.server.helper.BatchHelperR4;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
|
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
|
||||||
|
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||||
import org.hl7.fhir.r4.model.CodeType;
|
import org.hl7.fhir.r4.model.CodeType;
|
||||||
import org.hl7.fhir.r4.model.DecimalType;
|
import org.hl7.fhir.r4.model.DecimalType;
|
||||||
import org.hl7.fhir.r4.model.DiagnosticReport;
|
import org.hl7.fhir.r4.model.DiagnosticReport;
|
||||||
|
@ -69,12 +77,15 @@ import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
import org.hl7.fhir.r4.model.Organization;
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.Practitioner;
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -83,6 +94,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
@ -117,6 +129,8 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||||
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
||||||
myDaoConfig.setDeleteExpungeEnabled(new DaoConfig().isDeleteExpungeEnabled());
|
myDaoConfig.setDeleteExpungeEnabled(new DaoConfig().isDeleteExpungeEnabled());
|
||||||
|
myDaoConfig.setAutoCreatePlaceholderReferenceTargets(new DaoConfig().isAutoCreatePlaceholderReferenceTargets());
|
||||||
|
myDaoConfig.setPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets(new DaoConfig().isPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets());
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -144,11 +158,15 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
diagnosticReportRp.setDao(myDiagnosticReportDao);
|
diagnosticReportRp.setDao(myDiagnosticReportDao);
|
||||||
ServiceRequestResourceProvider diagnosticOrderRp = new ServiceRequestResourceProvider();
|
ServiceRequestResourceProvider diagnosticOrderRp = new ServiceRequestResourceProvider();
|
||||||
diagnosticOrderRp.setDao(myServiceRequestDao);
|
diagnosticOrderRp.setDao(myServiceRequestDao);
|
||||||
|
|
||||||
PractitionerResourceProvider practitionerRp = new PractitionerResourceProvider();
|
PractitionerResourceProvider practitionerRp = new PractitionerResourceProvider();
|
||||||
practitionerRp.setDao(myPractitionerDao);
|
practitionerRp.setDao(myPractitionerDao);
|
||||||
|
|
||||||
|
PractitionerRoleResourceProvider practitionerRoleRp = new PractitionerRoleResourceProvider();
|
||||||
|
practitionerRoleRp.setDao(myPractitionerRoleDao);
|
||||||
|
|
||||||
RestfulServer restServer = new RestfulServer(ourCtx);
|
RestfulServer restServer = new RestfulServer(ourCtx);
|
||||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, locationRp, binaryRp, diagnosticReportRp, diagnosticOrderRp, practitionerRp);
|
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp, locationRp, binaryRp, diagnosticReportRp, diagnosticOrderRp, practitionerRp, practitionerRoleRp);
|
||||||
|
|
||||||
restServer.registerProviders(mySystemProvider, myDeleteExpungeProvider);
|
restServer.registerProviders(mySystemProvider, myDeleteExpungeProvider);
|
||||||
|
|
||||||
|
@ -490,6 +508,78 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the interceptor is called an appropriate number of times
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBatchWithMultipleConditionalCreates() {
|
||||||
|
|
||||||
|
AtomicInteger counter0 = new AtomicInteger(0);
|
||||||
|
AtomicInteger counter1 = new AtomicInteger(0);
|
||||||
|
AtomicInteger counter2 = new AtomicInteger(0);
|
||||||
|
|
||||||
|
class MyAnonymousInterceptor0 implements IAnonymousInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(IPointcut thePointcut, HookParams theArgs) {
|
||||||
|
int count = counter0.incrementAndGet();
|
||||||
|
ourLog.info("counter0 have been called {} times", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyAnonymousInterceptor1 implements IAnonymousInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(IPointcut thePointcut, HookParams theArgs) {
|
||||||
|
int count = counter1.incrementAndGet();
|
||||||
|
ourLog.info("counter1 have been called {} times", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MySearchNarrowingInterceptor extends SearchNarrowingInterceptor {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(MySearchNarrowingInterceptor.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthorizedList buildAuthorizedList(RequestDetails theRequestDetails) {
|
||||||
|
int count = counter2.incrementAndGet();
|
||||||
|
ourLog.info("Have been called {} times", count);
|
||||||
|
return super.buildAuthorizedList(theRequestDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BundleBuilder bb = new BundleBuilder(myFhirContext);
|
||||||
|
bb.setType("batch");
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
Practitioner p0 = new Practitioner();
|
||||||
|
p0.addIdentifier().setSystem("sys").setValue("p" + i);
|
||||||
|
bb.addTransactionCreateEntry(p0).conditional("Practitioner?identifier=sys|p" + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid the auto-CS fetching affecting counts
|
||||||
|
myClient.capabilities().ofType(CapabilityStatement.class).execute();
|
||||||
|
|
||||||
|
Bundle input = (Bundle) bb.getBundle();
|
||||||
|
|
||||||
|
MyAnonymousInterceptor0 interceptor0 = new MyAnonymousInterceptor0();
|
||||||
|
ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, interceptor0);
|
||||||
|
MyAnonymousInterceptor1 interceptor1 = new MyAnonymousInterceptor1();
|
||||||
|
ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED, interceptor1);
|
||||||
|
MySearchNarrowingInterceptor interceptor2 = new MySearchNarrowingInterceptor();
|
||||||
|
ourRestServer.getInterceptorService().registerInterceptor(interceptor2);
|
||||||
|
try {
|
||||||
|
myClient.transaction().withBundle(input).execute();
|
||||||
|
assertEquals(1, counter0.get());
|
||||||
|
assertEquals(1, counter1.get());
|
||||||
|
assertEquals(5, counter2.get());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
ourRestServer.getInterceptorService().unregisterInterceptor(interceptor1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionFromBundle() throws Exception {
|
public void testTransactionFromBundle() throws Exception {
|
||||||
InputStream bundleRes = SystemProviderR4Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
InputStream bundleRes = SystemProviderR4Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
||||||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||||
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
|
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||||
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.rest.server.servlet.ServletRequestDetails;
|
||||||
|
@ -32,10 +33,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
public class AnalyticsInterceptor extends InterceptorAdapter {
|
public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AnalyticsInterceptor.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AnalyticsInterceptor.class);
|
||||||
|
private final LinkedList<AnalyticsEvent> myEventBuffer = new LinkedList<>();
|
||||||
private String myAnalyticsTid;
|
private String myAnalyticsTid;
|
||||||
private int myCollectThreshold = 100000;
|
private int myCollectThreshold = 100000;
|
||||||
private final LinkedList<AnalyticsEvent> myEventBuffer = new LinkedList<>();
|
|
||||||
private String myHostname;
|
private String myHostname;
|
||||||
private HttpClient myHttpClient;
|
private HttpClient myHttpClient;
|
||||||
private long mySubmitPeriod = 60000;
|
private long mySubmitPeriod = 60000;
|
||||||
|
@ -63,16 +63,6 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
mySchedulerService.scheduleLocalJob(5000, jobDetail);
|
mySchedulerService.scheduleLocalJob(5000, jobDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Job implements HapiJob {
|
|
||||||
@Autowired
|
|
||||||
private AnalyticsInterceptor myAnalyticsInterceptor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(JobExecutionContext theContext) {
|
|
||||||
myAnalyticsInterceptor.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void stop() throws IOException {
|
public void stop() throws IOException {
|
||||||
if (myHttpClient instanceof CloseableHttpClient) {
|
if (myHttpClient instanceof CloseableHttpClient) {
|
||||||
|
@ -105,13 +95,13 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
b.append("&an=").append(UrlUtil.escapeUrlParam(myHostname)).append('+').append(UrlUtil.escapeUrlParam(next.getApplicationName()));
|
b.append("&an=").append(UrlUtil.escapeUrlParam(myHostname)).append('+').append(UrlUtil.escapeUrlParam(next.getApplicationName()));
|
||||||
b.append("&ec=").append(next.getResourceName());
|
b.append("&ec=").append(next.getResourceName());
|
||||||
b.append("&ea=").append(next.getRestOperation());
|
b.append("&ea=").append(next.getRestOperation());
|
||||||
|
|
||||||
b.append("&cid=").append(next.getClientId());
|
b.append("&cid=").append(next.getClientId());
|
||||||
b.append("&uip=").append(UrlUtil.escapeUrlParam(next.getSourceIp()));
|
b.append("&uip=").append(UrlUtil.escapeUrlParam(next.getSourceIp()));
|
||||||
b.append("&ua=").append(UrlUtil.escapeUrlParam(next.getUserAgent()));
|
b.append("&ua=").append(UrlUtil.escapeUrlParam(next.getUserAgent()));
|
||||||
b.append("\n");
|
b.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
String contents = b.toString();
|
String contents = b.toString();
|
||||||
HttpPost post = new HttpPost("https://www.google-analytics.com/batch");
|
HttpPost post = new HttpPost("https://www.google-analytics.com/batch");
|
||||||
post.setEntity(new StringEntity(contents, ContentType.APPLICATION_FORM_URLENCODED));
|
post.setEntity(new StringEntity(contents, ContentType.APPLICATION_FORM_URLENCODED));
|
||||||
|
@ -121,7 +111,7 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ourLog.error("Failed to submit analytics:", e);
|
ourLog.error("Failed to submit analytics:", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void flush() {
|
private synchronized void flush() {
|
||||||
|
@ -145,15 +135,15 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theRequest) {
|
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, RequestDetails theRequest) {
|
||||||
ServletRequestDetails details = (ServletRequestDetails) theRequest.getRequestDetails();
|
ServletRequestDetails details = (ServletRequestDetails) theRequest;
|
||||||
|
|
||||||
// Make sure we only send one event per request
|
// Make sure we only send one event per request
|
||||||
if (details.getUserData().containsKey(getClass().getName())) {
|
if (details.getUserData().containsKey(getClass().getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
details.getUserData().put(getClass().getName(), "");
|
details.getUserData().put(getClass().getName(), "");
|
||||||
|
|
||||||
String sourceIp = details.getHeader("x-forwarded-for");
|
String sourceIp = details.getHeader("x-forwarded-for");
|
||||||
if (isBlank(sourceIp)) {
|
if (isBlank(sourceIp)) {
|
||||||
sourceIp = details.getServletRequest().getRemoteAddr();
|
sourceIp = details.getServletRequest().getRemoteAddr();
|
||||||
|
@ -178,64 +168,74 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
||||||
myEventBuffer.add(event);
|
myEventBuffer.add(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnalyticsTid(String theAnalyticsTid) {
|
public void setAnalyticsTid(String theAnalyticsTid) {
|
||||||
myAnalyticsTid = theAnalyticsTid;
|
myAnalyticsTid = theAnalyticsTid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Job implements HapiJob {
|
||||||
|
@Autowired
|
||||||
|
private AnalyticsInterceptor myAnalyticsInterceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext theContext) {
|
||||||
|
myAnalyticsInterceptor.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class AnalyticsEvent {
|
public static class AnalyticsEvent {
|
||||||
private String myApplicationName;
|
private String myApplicationName;
|
||||||
private String myClientId;
|
private String myClientId;
|
||||||
private String myResourceName;
|
private String myResourceName;
|
||||||
private RestOperationTypeEnum myRestOperation;
|
private RestOperationTypeEnum myRestOperation;
|
||||||
private String mySourceIp;
|
private String mySourceIp;
|
||||||
|
|
||||||
private String myUserAgent;
|
private String myUserAgent;
|
||||||
|
|
||||||
String getApplicationName() {
|
String getApplicationName() {
|
||||||
return myApplicationName;
|
return myApplicationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getClientId() {
|
|
||||||
return myClientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getResourceName() {
|
|
||||||
return myResourceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
RestOperationTypeEnum getRestOperation() {
|
|
||||||
return myRestOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getSourceIp() {
|
|
||||||
return mySourceIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getUserAgent() {
|
|
||||||
return myUserAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setApplicationName(String theApplicationName) {
|
void setApplicationName(String theApplicationName) {
|
||||||
myApplicationName = theApplicationName;
|
myApplicationName = theApplicationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getClientId() {
|
||||||
|
return myClientId;
|
||||||
|
}
|
||||||
|
|
||||||
void setClientId(String theClientId) {
|
void setClientId(String theClientId) {
|
||||||
myClientId = theClientId;
|
myClientId = theClientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getResourceName() {
|
||||||
|
return myResourceName;
|
||||||
|
}
|
||||||
|
|
||||||
void setResourceName(String theResourceName) {
|
void setResourceName(String theResourceName) {
|
||||||
myResourceName = theResourceName;
|
myResourceName = theResourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RestOperationTypeEnum getRestOperation() {
|
||||||
|
return myRestOperation;
|
||||||
|
}
|
||||||
|
|
||||||
void setRestOperation(RestOperationTypeEnum theRestOperation) {
|
void setRestOperation(RestOperationTypeEnum theRestOperation) {
|
||||||
myRestOperation = theRestOperation;
|
myRestOperation = theRestOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getSourceIp() {
|
||||||
|
return mySourceIp;
|
||||||
|
}
|
||||||
|
|
||||||
void setSourceIp(String theSourceIp) {
|
void setSourceIp(String theSourceIp) {
|
||||||
mySourceIp = theSourceIp;
|
mySourceIp = theSourceIp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getUserAgent() {
|
||||||
|
return myUserAgent;
|
||||||
|
}
|
||||||
|
|
||||||
void setUserAgent(String theUserAgent) {
|
void setUserAgent(String theUserAgent) {
|
||||||
myUserAgent = theUserAgent;
|
myUserAgent = theUserAgent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,6 @@ public interface IServerInterceptor {
|
||||||
* Invoked before an incoming request is processed. Note that this method is called
|
* Invoked before an incoming request is processed. Note that this method is called
|
||||||
* after the server has begin preparing the response to the incoming client request.
|
* after the server has begin preparing the response to the incoming client request.
|
||||||
* As such, it is not able to supply a response to the incoming request in the way that
|
* As such, it is not able to supply a response to the incoming request in the way that
|
||||||
* {@link #incomingRequestPreHandled(RestOperationTypeEnum, ActionRequestDetails)} and
|
|
||||||
* {@link #incomingRequestPostProcessed(RequestDetails, HttpServletRequest, HttpServletResponse)}
|
* {@link #incomingRequestPostProcessed(RequestDetails, HttpServletRequest, HttpServletResponse)}
|
||||||
* are.
|
* are.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -132,7 +131,7 @@ public interface IServerInterceptor {
|
||||||
* server, e.g. the FHIR operation type and the parsed resource body (if any).
|
* server, e.g. the FHIR operation type and the parsed resource body (if any).
|
||||||
*/
|
*/
|
||||||
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
||||||
void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theProcessedRequest);
|
void incomingRequestPreHandled(RestOperationTypeEnum theOperation, RequestDetails theProcessedRequest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called before any other processing takes place for each incoming request. It may be used to provide
|
* This method is called before any other processing takes place for each incoming request. It may be used to provide
|
||||||
|
@ -291,168 +290,4 @@ public interface IServerInterceptor {
|
||||||
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED_NORMALLY)
|
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED_NORMALLY)
|
||||||
void processingCompletedNormally(ServletRequestDetails theRequestDetails);
|
void processingCompletedNormally(ServletRequestDetails theRequestDetails);
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated This class doesn't bring anything that can't be done with {@link RequestDetails}. That
|
|
||||||
* class should be used instead. Deprecated in 4.0.0
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
class ActionRequestDetails {
|
|
||||||
private final FhirContext myContext;
|
|
||||||
private final IIdType myId;
|
|
||||||
private final String myResourceType;
|
|
||||||
private RequestDetails myRequestDetails;
|
|
||||||
private IBaseResource myResource;
|
|
||||||
|
|
||||||
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.getResourceType(theResource), theResource.getIdElement());
|
|
||||||
myResource = theResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, FhirContext theContext, String theResourceType, IIdType theId) {
|
|
||||||
if (theId != null && isBlank(theId.getValue())) {
|
|
||||||
myId = null;
|
|
||||||
} else {
|
|
||||||
myId = theId;
|
|
||||||
}
|
|
||||||
myResourceType = theResourceType;
|
|
||||||
myContext = theContext;
|
|
||||||
myRequestDetails = theRequestDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, IBaseResource theResource) {
|
|
||||||
this(theRequestDetails, theRequestDetails.getServer().getFhirContext().getResourceType(theResource), theResource.getIdElement());
|
|
||||||
myResource = theResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, IBaseResource theResource, String theResourceType, IIdType theId) {
|
|
||||||
this(theRequestDetails, theResourceType, theId);
|
|
||||||
myResource = theResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param theRequestDetails The request details to wrap
|
|
||||||
* @param theId The ID of the resource being created (note that the ID should have the resource type populated)
|
|
||||||
*/
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, IIdType theId) {
|
|
||||||
this(theRequestDetails, theId.getResourceType(), theId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
|
|
||||||
this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FhirContext getContext() {
|
|
||||||
return myContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ID of the incoming request (typically this is from the request URL)
|
|
||||||
*/
|
|
||||||
public IIdType getId() {
|
|
||||||
return myId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the request details associated with this request
|
|
||||||
*/
|
|
||||||
public RequestDetails getRequestDetails() {
|
|
||||||
return myRequestDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For requests where a resource is passed from the client to the server (e.g. create, update, etc.) this method
|
|
||||||
* will return the resource which was provided by the client. Otherwise, this method will return <code>null</code>
|
|
||||||
* .
|
|
||||||
* <p>
|
|
||||||
* Note that this method is currently only populated if the handling method has a parameter annotated with the
|
|
||||||
* {@link ResourceParam} annotation.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public IBaseResource getResource() {
|
|
||||||
return myResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method should not be called by client code
|
|
||||||
*/
|
|
||||||
public void setResource(IBaseResource theObject) {
|
|
||||||
myResource = theObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the resource type this request pertains to, or <code>null</code> if this request is not type specific
|
|
||||||
* (e.g. server-history)
|
|
||||||
*/
|
|
||||||
public String getResourceType() {
|
|
||||||
return myResourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
|
||||||
.append("id", myId)
|
|
||||||
.append("resourceType", myResourceType)
|
|
||||||
.append("resource", myResource)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the same map which was
|
|
||||||
*/
|
|
||||||
public Map<Object, Object> getUserData() {
|
|
||||||
if (myRequestDetails == null) {
|
|
||||||
/*
|
|
||||||
* Technically this shouldn't happen.. But some of the unit tests use old IXXXDao methods that don't
|
|
||||||
* take in a RequestDetails object. Eventually I guess we should clean that up.
|
|
||||||
*/
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
return myRequestDetails.getUserData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public void notifyIncomingRequestPreHandled(RestOperationTypeEnum theOperationType) {
|
|
||||||
RequestDetails requestDetails = getRequestDetails();
|
|
||||||
if (requestDetails == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IRestfulServerDefaults server = requestDetails.getServer();
|
|
||||||
if (server == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IIdType previousRequestId = requestDetails.getId();
|
|
||||||
requestDetails.setId(getId());
|
|
||||||
|
|
||||||
IInterceptorService interceptorService = server.getInterceptorService();
|
|
||||||
if (interceptorService == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HookParams params = new HookParams();
|
|
||||||
params.add(RestOperationTypeEnum.class, theOperationType);
|
|
||||||
params.add(this);
|
|
||||||
params.add(RequestDetails.class, this.getRequestDetails());
|
|
||||||
params.addIfMatchesType(ServletRequestDetails.class, this.getRequestDetails());
|
|
||||||
interceptorService.callHooks(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, params);
|
|
||||||
|
|
||||||
// Reset the request ID
|
|
||||||
requestDetails.setId(previousRequestId);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,21 +20,19 @@ package ca.uhn.fhir.rest.server.interceptor;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
||||||
|
@ -44,7 +42,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +52,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theProcessedRequest) {
|
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, RequestDetails theProcessedRequest) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +80,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
throws AuthenticationException {
|
throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +97,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
throws AuthenticationException {
|
throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,7 +208,8 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation, IBaseResource theRequestResource) {
|
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation) {
|
||||||
|
|
||||||
switch (theOperation) {
|
switch (theOperation) {
|
||||||
case ADD_TAGS:
|
case ADD_TAGS:
|
||||||
case DELETE_TAGS:
|
case DELETE_TAGS:
|
||||||
|
@ -232,13 +233,6 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
||||||
case CREATE:
|
case CREATE:
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
case PATCH:
|
case PATCH:
|
||||||
// if (theRequestResource != null) {
|
|
||||||
// if (theRequestResource.getIdElement() != null) {
|
|
||||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
|
||||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return OperationExamineDirection.IN;
|
return OperationExamineDirection.IN;
|
||||||
|
|
||||||
case META:
|
case META:
|
||||||
|
@ -363,7 +357,7 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
||||||
IBaseResource inputResource = null;
|
IBaseResource inputResource = null;
|
||||||
IIdType inputResourceId = null;
|
IIdType inputResourceId = null;
|
||||||
|
|
||||||
switch (determineOperationDirection(theRequest.getRestOperationType(), theRequest.getResource())) {
|
switch (determineOperationDirection(theRequest.getRestOperationType())) {
|
||||||
case IN:
|
case IN:
|
||||||
case BOTH:
|
case BOTH:
|
||||||
inputResource = theRequest.getResource();
|
inputResource = theRequest.getResource();
|
||||||
|
@ -422,7 +416,8 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkOutgoingResourceAndFailIfDeny(RequestDetails theRequestDetails, IBaseResource theResponseObject, Pointcut thePointcut) {
|
private void checkOutgoingResourceAndFailIfDeny(RequestDetails theRequestDetails, IBaseResource theResponseObject, Pointcut thePointcut) {
|
||||||
switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) {
|
|
||||||
|
switch (determineOperationDirection(theRequestDetails.getRestOperationType())) {
|
||||||
case IN:
|
case IN:
|
||||||
case NONE:
|
case NONE:
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -52,6 +52,9 @@ public class RuleImplConditional extends BaseRule implements IAuthRule {
|
||||||
if (theRequestDetails.getConditionalUrl(myOperationType) == null) {
|
if (theRequestDetails.getConditionalUrl(myOperationType) == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (theInputResource == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
switch (myAppliesTo) {
|
switch (myAppliesTo) {
|
||||||
case ALL_RESOURCES:
|
case ALL_RESOURCES:
|
||||||
|
@ -65,7 +68,7 @@ public class RuleImplConditional extends BaseRule implements IAuthRule {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String inputResourceName = theRequestDetails.getFhirContext().getResourceType(theInputResource);
|
String inputResourceName = theRequestDetails.getFhirContext().getResourceType(theInputResource);
|
||||||
if (theInputResource == null || !myAppliesToTypes.contains(inputResourceName)) {
|
if (!myAppliesToTypes.contains(inputResourceName)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import ca.uhn.fhir.rest.server.BundleProviders;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
|
@ -242,15 +241,13 @@ public abstract class BaseMethodBinding {
|
||||||
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
||||||
if (operationType != null) {
|
if (operationType != null) {
|
||||||
|
|
||||||
ActionRequestDetails details = new ActionRequestDetails(theRequest);
|
populateRequestDetailsForInterceptor(theRequest, theMethodParams);
|
||||||
populateActionRequestDetailsForInterceptor(theRequest, details, theMethodParams);
|
|
||||||
|
|
||||||
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||||
HookParams preHandledParams = new HookParams();
|
HookParams preHandledParams = new HookParams();
|
||||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||||
preHandledParams.add(RequestDetails.class, theRequest);
|
preHandledParams.add(RequestDetails.class, theRequest);
|
||||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||||
preHandledParams.add(ActionRequestDetails.class, details);
|
|
||||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||||
theRequest
|
theRequest
|
||||||
.getInterceptorBroadcaster()
|
.getInterceptorBroadcaster()
|
||||||
|
@ -293,12 +290,10 @@ public abstract class BaseMethodBinding {
|
||||||
/**
|
/**
|
||||||
* Subclasses may override this method (but should also call super) to provide method specifics to the
|
* Subclasses may override this method (but should also call super) to provide method specifics to the
|
||||||
* interceptors.
|
* interceptors.
|
||||||
*
|
|
||||||
* @param theRequestDetails The server request details
|
* @param theRequestDetails The server request details
|
||||||
* @param theDetails The details object to populate
|
|
||||||
* @param theMethodParams The method params as generated by the specific method binding
|
* @param theMethodParams The method params as generated by the specific method binding
|
||||||
*/
|
*/
|
||||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,10 @@ import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
|
|
||||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||||
private Integer myIdParamIndex;
|
private final Integer myIdParamIndex;
|
||||||
private String myResourceName;
|
private final String myResourceName;
|
||||||
private int myResourceParameterIndex = -1;
|
private int myResourceParameterIndex = -1;
|
||||||
private Class<? extends IBaseResource> myResourceType;
|
private Class<? extends IBaseResource> myResourceType;
|
||||||
private Class<? extends IIdType> myIdParamType;
|
private Class<? extends IIdType> myIdParamType;
|
||||||
|
@ -122,8 +121,8 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
||||||
|
@ -136,10 +135,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
||||||
}
|
}
|
||||||
|
|
||||||
theRequestDetails.setResource(resource);
|
theRequestDetails.setResource(resource);
|
||||||
if (theDetails != null) {
|
|
||||||
theDetails.setResource(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
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.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
|
@ -38,7 +38,6 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
|
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||||
|
|
||||||
|
@ -152,15 +151,15 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
// Handle server action interceptors
|
// Handle server action interceptors
|
||||||
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
||||||
if (operationType != null) {
|
if (operationType != null) {
|
||||||
IServerInterceptor.ActionRequestDetails details = new IServerInterceptor.ActionRequestDetails(theRequest);
|
|
||||||
populateActionRequestDetailsForInterceptor(theRequest, details, theMethodParams);
|
populateRequestDetailsForInterceptor(theRequest, theMethodParams);
|
||||||
|
|
||||||
// Interceptor hook: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
// Interceptor hook: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||||
HookParams preHandledParams = new HookParams();
|
HookParams preHandledParams = new HookParams();
|
||||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||||
preHandledParams.add(RequestDetails.class, theRequest);
|
preHandledParams.add(RequestDetails.class, theRequest);
|
||||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||||
preHandledParams.add(IServerInterceptor.ActionRequestDetails.class, details);
|
|
||||||
theRequest
|
theRequest
|
||||||
.getInterceptorBroadcaster()
|
.getInterceptorBroadcaster()
|
||||||
.callHooks(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, preHandledParams);
|
.callHooks(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, preHandledParams);
|
||||||
|
@ -196,7 +195,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
myCachedResponse.set(conf);
|
myCachedResponse.set(conf);
|
||||||
myCachedResponseExpires.set(System.currentTimeMillis() + getCacheMillis());
|
myCachedResponseExpires.set(System.currentTimeMillis() + getCacheMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +238,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
public IBaseConformance provideCapabilityStatement(RestfulServer theServer, RequestDetails theRequest) {
|
public IBaseConformance provideCapabilityStatement(RestfulServer theServer, RequestDetails theRequest) {
|
||||||
Object[] params = createMethodParams(theRequest);
|
Object[] params = createMethodParams(theRequest);
|
||||||
IBundleProvider resultObj = invokeServer(theServer, theRequest, params);
|
IBundleProvider resultObj = invokeServer(theServer, theRequest, params);
|
||||||
return (IBaseConformance) resultObj.getResources(0,1).get(0);
|
return (IBaseConformance) resultObj.getResources(0, 1).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
@ -373,14 +372,10 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails
|
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||||
theDetails, Object[] theMethodParams) {
|
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
|
||||||
IBaseResource resource = (IBaseResource) theRequestDetails.getUserData().get(OperationParameter.REQUEST_CONTENTS_USERDATA_KEY);
|
IBaseResource resource = (IBaseResource) theRequestDetails.getUserData().get(OperationParameter.REQUEST_CONTENTS_USERDATA_KEY);
|
||||||
theRequestDetails.setResource(resource);
|
theRequestDetails.setResource(resource);
|
||||||
if (theDetails != null) {
|
|
||||||
theDetails.setResource(resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isManualRequestMode() {
|
public boolean isManualRequestMode() {
|
||||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
@ -39,7 +39,6 @@ import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -54,12 +53,12 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PageMethodBinding.class);
|
||||||
|
|
||||||
public PageMethodBinding(FhirContext theContext, Method theMethod) {
|
public PageMethodBinding(FhirContext theContext, Method theMethod) {
|
||||||
super(null, theMethod, theContext, null);
|
super(null, theMethod, theContext, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PageMethodBinding.class);
|
|
||||||
|
|
||||||
public IBaseResource provider() {
|
public IBaseResource provider() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +82,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
public IBaseResource doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
|
public IBaseResource doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
|
||||||
return handlePagingRequest(theServer, theRequest, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]);
|
return handlePagingRequest(theServer, theRequest, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IBaseResource handlePagingRequest(IRestfulServer<?> theServer, RequestDetails theRequest, String thePagingAction) {
|
private IBaseResource handlePagingRequest(IRestfulServer<?> theServer, RequestDetails theRequest, String thePagingAction) {
|
||||||
IPagingProvider pagingProvider = theServer.getPagingProvider();
|
IPagingProvider pagingProvider = theServer.getPagingProvider();
|
||||||
if (pagingProvider == null) {
|
if (pagingProvider == null) {
|
||||||
|
@ -91,13 +90,11 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||||
IServerInterceptor.ActionRequestDetails details = new IServerInterceptor.ActionRequestDetails(theRequest);
|
populateRequestDetailsForInterceptor(theRequest, ReflectionUtil.EMPTY_OBJECT_ARRAY);
|
||||||
populateActionRequestDetailsForInterceptor(theRequest, details, ReflectionUtil.EMPTY_OBJECT_ARRAY);
|
|
||||||
HookParams preHandledParams = new HookParams();
|
HookParams preHandledParams = new HookParams();
|
||||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||||
preHandledParams.add(RequestDetails.class, theRequest);
|
preHandledParams.add(RequestDetails.class, theRequest);
|
||||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||||
preHandledParams.add(IServerInterceptor.ActionRequestDetails.class, details);
|
|
||||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||||
theRequest
|
theRequest
|
||||||
.getInterceptorBroadcaster()
|
.getInterceptorBroadcaster()
|
||||||
|
@ -152,8 +149,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String linkSelfBase = theRequest.getFhirServerBase(); // myServerAddressStrategy.determineServerBase(getServletContext(),
|
String linkSelfBase = theRequest.getFhirServerBase();
|
||||||
// theRequest.getServletRequest());
|
|
||||||
String completeUrl = theRequest.getCompleteUrl();
|
String completeUrl = theRequest.getCompleteUrl();
|
||||||
String linkSelf = linkSelfBase + completeUrl.substring(theRequest.getCompleteUrl().indexOf('?'));
|
String linkSelf = linkSelfBase + completeUrl.substring(theRequest.getCompleteUrl().indexOf('?'));
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
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.i18n.Msg;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
|
@ -34,7 +34,6 @@ import ca.uhn.fhir.rest.api.server.IRestfulServer;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.method.TransactionParameter.ParamStyle;
|
import ca.uhn.fhir.rest.server.method.TransactionParameter.ParamStyle;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
@ -58,8 +57,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
if (next instanceof TransactionParameter) {
|
if (next instanceof TransactionParameter) {
|
||||||
if (myTransactionParamIndex != -1) {
|
if (myTransactionParamIndex != -1) {
|
||||||
throw new ConfigurationException(Msg.code(372) + "Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " has multiple parameters annotated with the @"
|
throw new ConfigurationException(Msg.code(372) + "Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " has multiple parameters annotated with the @"
|
||||||
+ TransactionParam.class + " annotation, exactly one is required for @" + Transaction.class
|
+ TransactionParam.class + " annotation, exactly one is required for @" + Transaction.class
|
||||||
+ " methods");
|
+ " methods");
|
||||||
}
|
}
|
||||||
myTransactionParamIndex = index;
|
myTransactionParamIndex = index;
|
||||||
myTransactionParamStyle = ((TransactionParameter) next).getParamStyle();
|
myTransactionParamStyle = ((TransactionParameter) next).getParamStyle();
|
||||||
|
@ -69,7 +68,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
|
|
||||||
if (myTransactionParamIndex == -1) {
|
if (myTransactionParamIndex == -1) {
|
||||||
throw new ConfigurationException(Msg.code(373) + "Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with the @"
|
throw new ConfigurationException(Msg.code(373) + "Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with the @"
|
||||||
+ TransactionParam.class + " annotation");
|
+ TransactionParam.class + " annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +142,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
||||||
|
@ -158,10 +157,6 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
theRequestDetails.setResource(resource);
|
theRequestDetails.setResource(resource);
|
||||||
if (theDetails != null) {
|
|
||||||
theDetails.setResource(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.util.ValidateUtil;
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
@ -262,6 +263,8 @@ public class BulkDataImportProvider {
|
||||||
|
|
||||||
public void writePollingLocationToResponseHeaders(ServletRequestDetails theRequestDetails, String theJobId) {
|
public void writePollingLocationToResponseHeaders(ServletRequestDetails theRequestDetails, String theJobId) {
|
||||||
String pollLocation = createPollLocationLink(theRequestDetails, theJobId);
|
String pollLocation = createPollLocationLink(theRequestDetails, theJobId);
|
||||||
|
pollLocation = UrlUtil.sanitizeHeaderValue(pollLocation);
|
||||||
|
|
||||||
HttpServletResponse response = theRequestDetails.getServletResponse();
|
HttpServletResponse response = theRequestDetails.getServletResponse();
|
||||||
// Add standard headers
|
// Add standard headers
|
||||||
theRequestDetails.getServer().addHeadersToResponse(response);
|
theRequestDetails.getServer().addHeadersToResponse(response);
|
||||||
|
|
|
@ -53,6 +53,7 @@ import ca.uhn.fhir.util.ArrayUtil;
|
||||||
import ca.uhn.fhir.util.JsonUtil;
|
import ca.uhn.fhir.util.JsonUtil;
|
||||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||||
import ca.uhn.fhir.util.SearchParameterUtil;
|
import ca.uhn.fhir.util.SearchParameterUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -113,7 +114,7 @@ public class BulkDataExportProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startJob(ServletRequestDetails theRequestDetails,
|
private void startJob(ServletRequestDetails theRequestDetails,
|
||||||
BulkDataExportOptions theOptions){
|
BulkDataExportOptions theOptions) {
|
||||||
// permission check
|
// permission check
|
||||||
HookParams params = (new HookParams()).add(BulkDataExportOptions.class, theOptions)
|
HookParams params = (new HookParams()).add(BulkDataExportOptions.class, theOptions)
|
||||||
.add(RequestDetails.class, theRequestDetails)
|
.add(RequestDetails.class, theRequestDetails)
|
||||||
|
@ -124,7 +125,6 @@ public class BulkDataExportProvider {
|
||||||
boolean useCache = shouldUseCache(theRequestDetails);
|
boolean useCache = shouldUseCache(theRequestDetails);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BulkExportParameters parameters = BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions);
|
BulkExportParameters parameters = BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions);
|
||||||
parameters.setUseExistingJobsFirst(useCache);
|
parameters.setUseExistingJobsFirst(useCache);
|
||||||
|
|
||||||
|
@ -434,6 +434,7 @@ public class BulkDataExportProvider {
|
||||||
throw new InternalErrorException(Msg.code(2136) + "Unable to get the server base.");
|
throw new InternalErrorException(Msg.code(2136) + "Unable to get the server base.");
|
||||||
}
|
}
|
||||||
String pollLocation = serverBase + "/" + JpaConstants.OPERATION_EXPORT_POLL_STATUS + "?" + JpaConstants.PARAM_EXPORT_POLL_STATUS_JOB_ID + "=" + theOutcome.getJobMetadataId();
|
String pollLocation = serverBase + "/" + JpaConstants.OPERATION_EXPORT_POLL_STATUS + "?" + JpaConstants.PARAM_EXPORT_POLL_STATUS_JOB_ID + "=" + theOutcome.getJobMetadataId();
|
||||||
|
pollLocation = UrlUtil.sanitizeHeaderValue(pollLocation);
|
||||||
|
|
||||||
HttpServletResponse response = theRequestDetails.getServletResponse();
|
HttpServletResponse response = theRequestDetails.getServletResponse();
|
||||||
|
|
||||||
|
@ -445,14 +446,6 @@ public class BulkDataExportProvider {
|
||||||
response.setStatus(Constants.STATUS_HTTP_202_ACCEPTED);
|
response.setStatus(Constants.STATUS_HTTP_202_ACCEPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void validatePreferAsyncHeader(ServletRequestDetails theRequestDetails, String theOperationName) {
|
|
||||||
String preferHeader = theRequestDetails.getHeader(Constants.HEADER_PREFER);
|
|
||||||
PreferHeader prefer = RestfulServerUtils.parsePreferHeader(null, preferHeader);
|
|
||||||
if (prefer.getRespondAsync() == false) {
|
|
||||||
throw new InvalidRequestException(Msg.code(513) + "Must request async processing for " + theOperationName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> splitTypeFilters(List<IPrimitiveType<String>> theTypeFilter) {
|
private Set<String> splitTypeFilters(List<IPrimitiveType<String>> theTypeFilter) {
|
||||||
if (theTypeFilter == null) {
|
if (theTypeFilter == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -470,4 +463,12 @@ public class BulkDataExportProvider {
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void validatePreferAsyncHeader(ServletRequestDetails theRequestDetails, String theOperationName) {
|
||||||
|
String preferHeader = theRequestDetails.getHeader(Constants.HEADER_PREFER);
|
||||||
|
PreferHeader prefer = RestfulServerUtils.parsePreferHeader(null, preferHeader);
|
||||||
|
if (prefer.getRespondAsync() == false) {
|
||||||
|
throw new InvalidRequestException(Msg.code(513) + "Must request async processing for " + theOperationName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||||
import ca.uhn.fhir.rest.api.QualifiedParamList;
|
import ca.uhn.fhir.rest.api.QualifiedParamList;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
|
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
|
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
@ -49,12 +48,10 @@ import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.rest.param.QualifierDetails;
|
import ca.uhn.fhir.rest.param.QualifierDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
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.IServerInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
import ca.uhn.fhir.rest.server.util.CompositeInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||||
|
@ -106,42 +103,6 @@ public abstract class BaseStorageDao {
|
||||||
@Autowired
|
@Autowired
|
||||||
protected DaoConfig myDaoConfig;
|
protected DaoConfig myDaoConfig;
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ModelConfig#getAutoVersionReferenceAtPaths()
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static Set<IBaseReference> extractReferencesToAutoVersion(FhirContext theFhirContext, ModelConfig theModelConfig, IBaseResource theResource) {
|
|
||||||
Map<IBaseReference, Object> references = Collections.emptyMap();
|
|
||||||
if (!theModelConfig.getAutoVersionReferenceAtPaths().isEmpty()) {
|
|
||||||
String resourceName = theFhirContext.getResourceType(theResource);
|
|
||||||
for (String nextPath : theModelConfig.getAutoVersionReferenceAtPathsByResourceType(resourceName)) {
|
|
||||||
List<IBaseReference> nextReferences = theFhirContext.newTerser().getValues(theResource, nextPath, IBaseReference.class);
|
|
||||||
for (IBaseReference next : nextReferences) {
|
|
||||||
if (next.getReferenceElement().hasVersionIdPart()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (references.isEmpty()) {
|
|
||||||
references = new IdentityHashMap<>();
|
|
||||||
}
|
|
||||||
references.put(next, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return references.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearRequestAsProcessingSubRequest(RequestDetails theRequestDetails) {
|
|
||||||
if (theRequestDetails != null) {
|
|
||||||
theRequestDetails.getUserData().remove(PROCESSING_SUB_REQUEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void markRequestAsProcessingSubRequest(RequestDetails theRequestDetails) {
|
|
||||||
if (theRequestDetails != null) {
|
|
||||||
theRequestDetails.getUserData().put(PROCESSING_SUB_REQUEST, Boolean.TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void setSearchParamRegistry(ISearchParamRegistry theSearchParamRegistry) {
|
public void setSearchParamRegistry(ISearchParamRegistry theSearchParamRegistry) {
|
||||||
mySearchParamRegistry = theSearchParamRegistry;
|
mySearchParamRegistry = theSearchParamRegistry;
|
||||||
|
@ -171,7 +132,7 @@ public abstract class BaseStorageDao {
|
||||||
|
|
||||||
verifyBundleTypeIsAppropriateForStorage(theResource);
|
verifyBundleTypeIsAppropriateForStorage(theResource);
|
||||||
|
|
||||||
if(!getConfig().getTreatBaseUrlsAsLocal().isEmpty()) {
|
if (!getConfig().getTreatBaseUrlsAsLocal().isEmpty()) {
|
||||||
replaceAbsoluteReferencesWithRelative(theResource, myFhirContext.newTerser());
|
replaceAbsoluteReferencesWithRelative(theResource, myFhirContext.newTerser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,16 +180,16 @@ public abstract class BaseStorageDao {
|
||||||
* Replace absolute references with relative ones if configured to do so
|
* Replace absolute references with relative ones if configured to do so
|
||||||
*/
|
*/
|
||||||
private void replaceAbsoluteReferencesWithRelative(IBaseResource theResource, FhirTerser theTerser) {
|
private void replaceAbsoluteReferencesWithRelative(IBaseResource theResource, FhirTerser theTerser) {
|
||||||
List<ResourceReferenceInfo> refs = theTerser.getAllResourceReferences(theResource);
|
List<ResourceReferenceInfo> refs = theTerser.getAllResourceReferences(theResource);
|
||||||
for (ResourceReferenceInfo nextRef : refs) {
|
for (ResourceReferenceInfo nextRef : refs) {
|
||||||
IIdType refId = nextRef.getResourceReference().getReferenceElement();
|
IIdType refId = nextRef.getResourceReference().getReferenceElement();
|
||||||
if (refId != null && refId.hasBaseUrl()) {
|
if (refId != null && refId.hasBaseUrl()) {
|
||||||
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
|
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
|
||||||
IIdType newRefId = refId.toUnqualified();
|
IIdType newRefId = refId.toUnqualified();
|
||||||
nextRef.getResourceReference().setReference(newRefId.getValue());
|
nextRef.getResourceReference().setReference(newRefId.getValue());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -463,15 +424,40 @@ public abstract class BaseStorageDao {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyInterceptors(RestOperationTypeEnum theOperationType, IServerInterceptor.ActionRequestDetails theRequestDetails) {
|
/**
|
||||||
if (theRequestDetails.getId() != null && theRequestDetails.getId().hasResourceType() && isNotBlank(theRequestDetails.getResourceType())) {
|
* @see ModelConfig#getAutoVersionReferenceAtPaths()
|
||||||
if (theRequestDetails.getId().getResourceType().equals(theRequestDetails.getResourceType()) == false) {
|
*/
|
||||||
throw new InternalErrorException(Msg.code(525) + "Inconsistent server state - Resource types don't match: " + theRequestDetails.getId().getResourceType() + " / " + theRequestDetails.getResourceType());
|
@Nonnull
|
||||||
|
public static Set<IBaseReference> extractReferencesToAutoVersion(FhirContext theFhirContext, ModelConfig theModelConfig, IBaseResource theResource) {
|
||||||
|
Map<IBaseReference, Object> references = Collections.emptyMap();
|
||||||
|
if (!theModelConfig.getAutoVersionReferenceAtPaths().isEmpty()) {
|
||||||
|
String resourceName = theFhirContext.getResourceType(theResource);
|
||||||
|
for (String nextPath : theModelConfig.getAutoVersionReferenceAtPathsByResourceType(resourceName)) {
|
||||||
|
List<IBaseReference> nextReferences = theFhirContext.newTerser().getValues(theResource, nextPath, IBaseReference.class);
|
||||||
|
for (IBaseReference next : nextReferences) {
|
||||||
|
if (next.getReferenceElement().hasVersionIdPart()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (references.isEmpty()) {
|
||||||
|
references = new IdentityHashMap<>();
|
||||||
|
}
|
||||||
|
references.put(next, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return references.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
if (theRequestDetails.getUserData().get(PROCESSING_SUB_REQUEST) == Boolean.TRUE) {
|
public static void clearRequestAsProcessingSubRequest(RequestDetails theRequestDetails) {
|
||||||
theRequestDetails.notifyIncomingRequestPreHandled(theOperationType);
|
if (theRequestDetails != null) {
|
||||||
|
theRequestDetails.getUserData().remove(PROCESSING_SUB_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void markRequestAsProcessingSubRequest(RequestDetails theRequestDetails) {
|
||||||
|
if (theRequestDetails != null) {
|
||||||
|
theRequestDetails.getUserData().put(PROCESSING_SUB_REQUEST, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,11 +203,6 @@ public abstract class BaseTransactionProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <BUNDLE extends IBaseBundle> BUNDLE transaction(RequestDetails theRequestDetails, BUNDLE theRequest, boolean theNestedMode) {
|
public <BUNDLE extends IBaseBundle> BUNDLE transaction(RequestDetails theRequestDetails, BUNDLE theRequest, boolean theNestedMode) {
|
||||||
if (theRequestDetails != null && theRequestDetails.getServer() != null && myDao != null) {
|
|
||||||
IServerInterceptor.ActionRequestDetails requestDetails = new IServerInterceptor.ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
|
|
||||||
myDao.notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
String actionName = "Transaction";
|
String actionName = "Transaction";
|
||||||
IBaseBundle response = processTransactionAsSubRequest(theRequestDetails, theRequest, actionName, theNestedMode);
|
IBaseBundle response = processTransactionAsSubRequest(theRequestDetails, theRequest, actionName, theNestedMode);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
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.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
@ -132,7 +131,7 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
||||||
public void incomingRequestPreHandled(ActionRequestDetails theRequestDetails) {
|
public void incomingRequestPreHandled(RequestDetails theRequestDetails) {
|
||||||
updateMapUsing(theRequestDetails.getUserData(), "incomingRequestPreHandled");
|
updateMapUsing(theRequestDetails.getUserData(), "incomingRequestPreHandled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +184,7 @@ public class InterceptorUserDataMapDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Patient> getIdToPatient() {
|
public Map<String, Patient> getIdToPatient() {
|
||||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
Map<String, Patient> idToPatient = new HashMap<>();
|
||||||
{
|
{
|
||||||
Patient patient = createPatient1();
|
Patient patient = createPatient1();
|
||||||
idToPatient.put("1", patient);
|
idToPatient.put("1", patient);
|
||||||
|
|
|
@ -20,7 +20,6 @@ import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||||
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.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
@ -62,13 +61,6 @@ public class ServerActionInterceptorTest {
|
||||||
private static IServerInterceptor ourInterceptor;
|
private static IServerInterceptor ourInterceptor;
|
||||||
private static IGenericClient ourFhirClient;
|
private static IGenericClient ourFhirClient;
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRead() throws Exception {
|
public void testRead() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123");
|
||||||
|
@ -77,10 +69,10 @@ public class ServerActionInterceptorTest {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.READ), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.READ), detailsCapt.capture());
|
||||||
|
|
||||||
ActionRequestDetails details = detailsCapt.getValue();
|
RequestDetails details = detailsCapt.getValue();
|
||||||
assertEquals("Patient/123", details.getId().getValue());
|
assertEquals("Patient/123", details.getId().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,10 +84,10 @@ public class ServerActionInterceptorTest {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.VREAD), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.VREAD), detailsCapt.capture());
|
||||||
|
|
||||||
ActionRequestDetails details = detailsCapt.getValue();
|
RequestDetails details = detailsCapt.getValue();
|
||||||
assertEquals("Patient/123/_history/456", details.getId().getValue());
|
assertEquals("Patient/123/_history/456", details.getId().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,11 +97,11 @@ public class ServerActionInterceptorTest {
|
||||||
patient.addName().addFamily("FAMILY");
|
patient.addName().addFamily("FAMILY");
|
||||||
ourFhirClient.create().resource(patient).execute();
|
ourFhirClient.create().resource(patient).execute();
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||||
|
|
||||||
ActionRequestDetails details = detailsCapt.getValue();
|
RequestDetails details = detailsCapt.getValue();
|
||||||
assertEquals("Patient", details.getResourceType());
|
assertEquals("Patient", details.getResourceName());
|
||||||
assertEquals(Patient.class, details.getResource().getClass());
|
assertEquals(Patient.class, details.getResource().getClass());
|
||||||
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
||||||
}
|
}
|
||||||
|
@ -120,11 +112,11 @@ public class ServerActionInterceptorTest {
|
||||||
observation.getCode().setText("OBSCODE");
|
observation.getCode().setText("OBSCODE");
|
||||||
ourFhirClient.create().resource(observation).execute();
|
ourFhirClient.create().resource(observation).execute();
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
|
||||||
|
|
||||||
ActionRequestDetails details = detailsCapt.getValue();
|
RequestDetails details = detailsCapt.getValue();
|
||||||
assertEquals("Observation", details.getResourceType());
|
assertEquals("Observation", details.getResourceName());
|
||||||
assertEquals(Observation.class, details.getResource().getClass());
|
assertEquals(Observation.class, details.getResource().getClass());
|
||||||
assertEquals("OBSCODE", ((Observation) details.getResource()).getCode().getText());
|
assertEquals("OBSCODE", ((Observation) details.getResource()).getCode().getText());
|
||||||
}
|
}
|
||||||
|
@ -136,11 +128,11 @@ public class ServerActionInterceptorTest {
|
||||||
patient.setId("Patient/123");
|
patient.setId("Patient/123");
|
||||||
ourFhirClient.update().resource(patient).execute();
|
ourFhirClient.update().resource(patient).execute();
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.UPDATE), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.UPDATE), detailsCapt.capture());
|
||||||
|
|
||||||
ActionRequestDetails details = detailsCapt.getValue();
|
RequestDetails details = detailsCapt.getValue();
|
||||||
assertEquals("Patient", details.getResourceType());
|
assertEquals("Patient", details.getResourceName());
|
||||||
assertEquals("Patient/123", details.getId().getValue());
|
assertEquals("Patient/123", details.getId().getValue());
|
||||||
assertEquals(Patient.class, details.getResource().getClass());
|
assertEquals(Patient.class, details.getResource().getClass());
|
||||||
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
||||||
|
@ -155,7 +147,7 @@ public class ServerActionInterceptorTest {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_SYSTEM), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_SYSTEM), detailsCapt.capture());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +159,9 @@ public class ServerActionInterceptorTest {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_TYPE), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_TYPE), detailsCapt.capture());
|
||||||
assertEquals("Patient", detailsCapt.getValue().getResourceType());
|
assertEquals("Patient", detailsCapt.getValue().getResourceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -180,12 +172,29 @@ public class ServerActionInterceptorTest {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> detailsCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_INSTANCE), detailsCapt.capture());
|
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.HISTORY_INSTANCE), detailsCapt.capture());
|
||||||
assertEquals("Patient", detailsCapt.getValue().getResourceType());
|
assertEquals("Patient", detailsCapt.getValue().getResourceName());
|
||||||
assertEquals("Patient/123", detailsCapt.getValue().getId().getValue());
|
assertEquals("Patient/123", detailsCapt.getValue().getId().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
reset(ourInterceptor);
|
||||||
|
|
||||||
|
when(ourInterceptor.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(ourInterceptor.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(IBaseResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(ResponseDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
JettyUtil.closeServer(ourServer);
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void beforeClass() throws Exception {
|
public static void beforeClass() throws Exception {
|
||||||
ourServer = new Server(0);
|
ourServer = new Server(0);
|
||||||
|
@ -202,7 +211,7 @@ public class ServerActionInterceptorTest {
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
ourServer.setHandler(proxyHandler);
|
ourServer.setHandler(proxyHandler);
|
||||||
JettyUtil.startServer(ourServer);
|
JettyUtil.startServer(ourServer);
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
@ -212,23 +221,12 @@ public class ServerActionInterceptorTest {
|
||||||
ourInterceptor = mock(InterceptorAdapter.class);
|
ourInterceptor = mock(InterceptorAdapter.class);
|
||||||
servlet.registerInterceptor(ourInterceptor);
|
servlet.registerInterceptor(ourInterceptor);
|
||||||
|
|
||||||
ourCtx.getRestfulClientFactory().setSocketTimeout(240*1000);
|
ourCtx.getRestfulClientFactory().setSocketTimeout(240 * 1000);
|
||||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
ourFhirClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort);
|
ourFhirClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void before() {
|
|
||||||
reset(ourInterceptor);
|
|
||||||
|
|
||||||
when(ourInterceptor.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(ourInterceptor.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(IBaseResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(ourInterceptor.outgoingResponse(any(RequestDetails.class), any(ResponseDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PlainProvider {
|
public static class PlainProvider {
|
||||||
|
|
||||||
@History()
|
@History()
|
||||||
|
@ -300,6 +298,6 @@ public class ServerActionInterceptorTest {
|
||||||
return new MethodOutcome(retVal.getId());
|
return new MethodOutcome(retVal.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,12 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
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.rest.server.interceptor.InterceptorAdapter;
|
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
@ -186,9 +184,9 @@ public class InterceptorDstu3Test {
|
||||||
when(myInterceptor2.outgoingResponse(nullable(RequestDetails.class), nullable(IBaseResource.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true);
|
when(myInterceptor2.outgoingResponse(nullable(RequestDetails.class), nullable(IBaseResource.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true);
|
||||||
when(myInterceptor2.outgoingResponse(nullable(RequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true);
|
when(myInterceptor2.outgoingResponse(nullable(RequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
|
||||||
doAnswer(t->{
|
doAnswer(t -> {
|
||||||
RestOperationTypeEnum type = (RestOperationTypeEnum) t.getArguments()[0];
|
RestOperationTypeEnum type = (RestOperationTypeEnum) t.getArguments()[0];
|
||||||
ActionRequestDetails det = (ActionRequestDetails) t.getArguments()[1];
|
RequestDetails det = (RequestDetails) t.getArguments()[1];
|
||||||
return null;
|
return null;
|
||||||
}).when(myInterceptor1).incomingRequestPreHandled(any(), any());
|
}).when(myInterceptor1).incomingRequestPreHandled(any(), any());
|
||||||
|
|
||||||
|
@ -206,9 +204,9 @@ public class InterceptorDstu3Test {
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
order.verify(myInterceptor2, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
order.verify(myInterceptor2, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
||||||
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> arTypeCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||||
order.verify(myInterceptor2, times(1)).incomingRequestPreHandled(nullable(RestOperationTypeEnum.class), nullable(ActionRequestDetails.class));
|
order.verify(myInterceptor2, times(1)).incomingRequestPreHandled(nullable(RestOperationTypeEnum.class), nullable(RequestDetails.class));
|
||||||
|
|
||||||
assertEquals(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, opTypeCapt.getValue());
|
assertEquals(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, opTypeCapt.getValue());
|
||||||
assertNotNull(arTypeCapt.getValue().getResource());
|
assertNotNull(arTypeCapt.getValue().getResource());
|
||||||
|
@ -261,7 +259,7 @@ public class InterceptorDstu3Test {
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPreProcessed(nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
verify(myInterceptor1, times(1)).incomingRequestPreProcessed(nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
||||||
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> arTypeCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
ArgumentCaptor<ServletRequestDetails> rdCapt = ArgumentCaptor.forClass(ServletRequestDetails.class);
|
ArgumentCaptor<ServletRequestDetails> rdCapt = ArgumentCaptor.forClass(ServletRequestDetails.class);
|
||||||
ArgumentCaptor<OperationOutcome> resourceCapt = ArgumentCaptor.forClass(OperationOutcome.class);
|
ArgumentCaptor<OperationOutcome> resourceCapt = ArgumentCaptor.forClass(OperationOutcome.class);
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||||
|
@ -296,7 +294,7 @@ public class InterceptorDstu3Test {
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPreProcessed(nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
order.verify(myInterceptor1, times(1)).incomingRequestPreProcessed(nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class));
|
||||||
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
||||||
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
ArgumentCaptor<RequestDetails> arTypeCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
ArgumentCaptor<OperationOutcome> resourceCapt = ArgumentCaptor.forClass(OperationOutcome.class);
|
ArgumentCaptor<OperationOutcome> resourceCapt = ArgumentCaptor.forClass(OperationOutcome.class);
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||||
order.verify(myInterceptor1, times(1)).outgoingResponse(nullable(ServletRequestDetails.class), resourceCapt.capture());
|
order.verify(myInterceptor1, times(1)).outgoingResponse(nullable(ServletRequestDetails.class), resourceCapt.capture());
|
||||||
|
@ -315,6 +313,35 @@ public class InterceptorDstu3Test {
|
||||||
i.resourceUpdated(null, null, null);
|
i.resourceUpdated(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
JettyUtil.closeServer(ourServer);
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourServer = new Server(0);
|
||||||
|
|
||||||
|
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
|
ourServlet.setResourceProviders(patientProvider);
|
||||||
|
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
|
||||||
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
JettyUtil.startServer(ourServer);
|
||||||
|
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
@Create()
|
@Create()
|
||||||
|
@ -323,10 +350,10 @@ public class InterceptorDstu3Test {
|
||||||
return new MethodOutcome().setCreated(true);
|
return new MethodOutcome().setCreated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name="$postOperation")
|
@Operation(name = "$postOperation")
|
||||||
public Parameters postOperation(
|
public Parameters postOperation(
|
||||||
@OperationParam(name = "limit") IntegerType theLimit
|
@OperationParam(name = "limit") IntegerType theLimit
|
||||||
) {
|
) {
|
||||||
return new Parameters();
|
return new Parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,33 +377,4 @@ public class InterceptorDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
|
||||||
ourServlet.setResourceProviders(patientProvider);
|
|
||||||
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
|
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
|
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||||
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.ConditionalUrlParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
|
@ -31,7 +32,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||||
|
@ -39,7 +42,6 @@ import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
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.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
|
@ -112,15 +114,14 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
public class AuthorizationInterceptorR4Test {
|
public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\""+ Msg.code(334) + "Access denied by default policy (no applicable rules)\"}]}";
|
private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\"" + Msg.code(334) + "Access denied by default policy (no applicable rules)\"}]}";
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AuthorizationInterceptorR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AuthorizationInterceptorR4Test.class);
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
private static String ourConditionalCreateId;
|
private static String ourConditionalCreateId;
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
private static final FhirContext ourCtx = FhirContext.forR4();
|
||||||
private static boolean ourHitMethod;
|
private static boolean ourHitMethod;
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static List<Resource> ourReturn;
|
private static List<Resource> ourReturn;
|
||||||
|
@ -1173,7 +1174,7 @@ public class AuthorizationInterceptorR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCodeIn_TransactionCreate() throws IOException {
|
public void testCodeIn_TransactionCreate() throws IOException {
|
||||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -2540,7 +2541,7 @@ public class AuthorizationInterceptorR4Test {
|
||||||
@Override
|
@Override
|
||||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||||
return new RuleBuilder()
|
return new RuleBuilder()
|
||||||
.allow("Rule 1").operation().named("everything").onInstancesOfType(Patient.class).andRequireExplicitResponseAuthorization().withTester(null /* null should be ignored */ ).withTester(new IAuthRuleTester() {
|
.allow("Rule 1").operation().named("everything").onInstancesOfType(Patient.class).andRequireExplicitResponseAuthorization().withTester(null /* null should be ignored */).withTester(new IAuthRuleTester() {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IIdType theInputResourceId, IBaseResource theInputResource) {
|
public boolean matches(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IIdType theInputResourceId, IBaseResource theInputResource) {
|
||||||
return theInputResourceId.getIdPart().equals("1");
|
return theInputResourceId.getIdPart().equals("1");
|
||||||
|
@ -4202,6 +4203,47 @@ public class AuthorizationInterceptorR4Test {
|
||||||
assertTrue(ourHitMethod);
|
assertTrue(ourHitMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
JettyUtil.closeServer(ourServer);
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourServer = new Server(0);
|
||||||
|
|
||||||
|
DummyPatientResourceProvider patProvider = new DummyPatientResourceProvider();
|
||||||
|
DummyObservationResourceProvider obsProv = new DummyObservationResourceProvider();
|
||||||
|
DummyOrganizationResourceProvider orgProv = new DummyOrganizationResourceProvider();
|
||||||
|
DummyEncounterResourceProvider encProv = new DummyEncounterResourceProvider();
|
||||||
|
DummyCarePlanResourceProvider cpProv = new DummyCarePlanResourceProvider();
|
||||||
|
DummyDiagnosticReportResourceProvider drProv = new DummyDiagnosticReportResourceProvider();
|
||||||
|
DummyDeviceResourceProvider devProv = new DummyDeviceResourceProvider();
|
||||||
|
PlainProvider plainProvider = new PlainProvider();
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
|
ourServlet.setFhirContext(ourCtx);
|
||||||
|
ourServlet.registerProviders(patProvider, obsProv, encProv, cpProv, orgProv, drProv, devProv);
|
||||||
|
ourServlet.registerProvider(new DummyServiceRequestResourceProvider());
|
||||||
|
ourServlet.registerProvider(new DummyConsentResourceProvider());
|
||||||
|
ourServlet.setPlainProviders(plainProvider);
|
||||||
|
ourServlet.setPagingProvider(new FifoMemoryPagingProvider(100));
|
||||||
|
ourServlet.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||||
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
JettyUtil.startServer(ourServer);
|
||||||
|
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class DummyCarePlanResourceProvider implements IResourceProvider {
|
public static class DummyCarePlanResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4263,7 +4305,6 @@ public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class DummyDiagnosticReportResourceProvider implements IResourceProvider {
|
public static class DummyDiagnosticReportResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
|
||||||
|
@ -4297,6 +4338,7 @@ public class AuthorizationInterceptorR4Test {
|
||||||
}
|
}
|
||||||
return (Device) ourReturn.get(0);
|
return (Device) ourReturn.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search()
|
@Search()
|
||||||
public List<Resource> search(
|
public List<Resource> search(
|
||||||
@OptionalParam(name = "patient") ReferenceParam thePatient
|
@OptionalParam(name = "patient") ReferenceParam thePatient
|
||||||
|
@ -4377,15 +4419,29 @@ public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
if (isNotBlank(theConditionalUrl)) {
|
if (isNotBlank(theConditionalUrl)) {
|
||||||
IdType actual = new IdType("Observation", ourConditionalCreateId);
|
IdType actual = new IdType("Observation", ourConditionalCreateId);
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
|
||||||
theResource.setId(actual);
|
theResource.setId(actual);
|
||||||
} else {
|
} else {
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
|
||||||
theResource.setId(theId.withVersion("2"));
|
theResource.setId(theId.withVersion("2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HookParams params = new HookParams();
|
||||||
|
params.add(IBaseResource.class, theResource);
|
||||||
|
params.add(RequestDetails.class, theRequestDetails);
|
||||||
|
params.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
params.add(TransactionDetails.class, new TransactionDetails());
|
||||||
|
params.add(RequestPartitionId.class, RequestPartitionId.defaultPartition());
|
||||||
|
ourServlet.getInterceptorService().callHooks(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HookParams params = new HookParams();
|
||||||
|
params.add(RequestDetails.class, theRequestDetails);
|
||||||
|
params.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
params.add(IPreResourceShowDetails.class, new SimplePreResourceShowDetails(theResource));
|
||||||
|
ourServlet.getInterceptorService().callHooks(Pointcut.STORAGE_PRESHOW_RESOURCES, params);
|
||||||
|
}
|
||||||
|
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
MethodOutcome retVal = new MethodOutcome();
|
||||||
retVal.setResource(theResource);
|
retVal.setResource(theResource);
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -4431,20 +4487,18 @@ public class AuthorizationInterceptorR4Test {
|
||||||
@Create()
|
@Create()
|
||||||
public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
|
public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
|
||||||
|
|
||||||
if (isNotBlank(theConditionalUrl)) {
|
|
||||||
IdType actual = new IdType("Patient", ourConditionalCreateId);
|
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.CREATE);
|
|
||||||
} else {
|
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ourHitMethod = true;
|
ourHitMethod = true;
|
||||||
theResource.setId("Patient/1/_history/1");
|
theResource.setId("Patient/1/_history/1");
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
MethodOutcome retVal = new MethodOutcome();
|
||||||
retVal.setCreated(true);
|
retVal.setCreated(true);
|
||||||
retVal.setResource(theResource);
|
retVal.setResource(theResource);
|
||||||
|
|
||||||
|
HookParams params = new HookParams();
|
||||||
|
params.add(RequestDetails.class, theRequestDetails);
|
||||||
|
params.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
params.add(IPreResourceShowDetails.class, new SimplePreResourceShowDetails(theResource));
|
||||||
|
ourServlet.getInterceptorService().callHooks(Pointcut.STORAGE_PRESHOW_RESOURCES, params);
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4521,8 +4575,7 @@ public class AuthorizationInterceptorR4Test {
|
||||||
public MethodOutcome patch(@IdParam IdType theId, @ResourceParam String theResource, PatchTypeEnum thePatchType) {
|
public MethodOutcome patch(@IdParam IdType theId, @ResourceParam String theResource, PatchTypeEnum thePatchType) {
|
||||||
ourHitMethod = true;
|
ourHitMethod = true;
|
||||||
|
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
return new MethodOutcome();
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Read(version = true)
|
@Read(version = true)
|
||||||
|
@ -4546,15 +4599,28 @@ public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
if (isNotBlank(theConditionalUrl)) {
|
if (isNotBlank(theConditionalUrl)) {
|
||||||
IdType actual = new IdType("Patient", ourConditionalCreateId);
|
IdType actual = new IdType("Patient", ourConditionalCreateId);
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
|
||||||
theResource.setId(actual);
|
theResource.setId(actual);
|
||||||
} else {
|
} else {
|
||||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
|
|
||||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
|
||||||
theResource.setId(theId.withVersion("2"));
|
theResource.setId(theId.withVersion("2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HookParams params = new HookParams();
|
||||||
|
params.add(IBaseResource.class, theResource);
|
||||||
|
params.add(RequestDetails.class, theRequestDetails);
|
||||||
|
params.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
params.add(TransactionDetails.class, new TransactionDetails());
|
||||||
|
params.add(RequestPartitionId.class, RequestPartitionId.defaultPartition());
|
||||||
|
ourServlet.getInterceptorService().callHooks(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED, params);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HookParams params = new HookParams();
|
||||||
|
params.add(RequestDetails.class, theRequestDetails);
|
||||||
|
params.addIfMatchesType(ServletRequestDetails.class, theRequestDetails);
|
||||||
|
params.add(IPreResourceShowDetails.class, new SimplePreResourceShowDetails(theResource));
|
||||||
|
ourServlet.getInterceptorService().callHooks(Pointcut.STORAGE_PRESHOW_RESOURCES, params);
|
||||||
|
}
|
||||||
|
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
MethodOutcome retVal = new MethodOutcome();
|
||||||
retVal.setResource(theResource);
|
retVal.setResource(theResource);
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -4624,46 +4690,5 @@ public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
DummyPatientResourceProvider patProvider = new DummyPatientResourceProvider();
|
|
||||||
DummyObservationResourceProvider obsProv = new DummyObservationResourceProvider();
|
|
||||||
DummyOrganizationResourceProvider orgProv = new DummyOrganizationResourceProvider();
|
|
||||||
DummyEncounterResourceProvider encProv = new DummyEncounterResourceProvider();
|
|
||||||
DummyCarePlanResourceProvider cpProv = new DummyCarePlanResourceProvider();
|
|
||||||
DummyDiagnosticReportResourceProvider drProv = new DummyDiagnosticReportResourceProvider();
|
|
||||||
DummyDeviceResourceProvider devProv = new DummyDeviceResourceProvider();
|
|
||||||
PlainProvider plainProvider = new PlainProvider();
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
|
||||||
ourServlet.setFhirContext(ourCtx);
|
|
||||||
ourServlet.registerProviders(patProvider, obsProv, encProv, cpProv, orgProv, drProv, devProv);
|
|
||||||
ourServlet.registerProvider(new DummyServiceRequestResourceProvider());
|
|
||||||
ourServlet.registerProvider(new DummyConsentResourceProvider());
|
|
||||||
ourServlet.setPlainProviders(plainProvider);
|
|
||||||
ourServlet.setPagingProvider(new FifoMemoryPagingProvider(100));
|
|
||||||
ourServlet.setDefaultResponseEncoding(EncodingEnum.JSON);
|
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue