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>
|
||||
* 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>
|
||||
* 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>
|
||||
* </p>
|
||||
* <p>
|
||||
|
@ -360,8 +357,7 @@ public enum Pointcut implements IPointcut {
|
|||
SERVER_INCOMING_REQUEST_PRE_HANDLED(void.class,
|
||||
"ca.uhn.fhir.rest.api.server.RequestDetails",
|
||||
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
|
||||
"ca.uhn.fhir.rest.api.RestOperationTypeEnum",
|
||||
"ca.uhn.fhir.rest.server.interceptor.IServerInterceptor$ActionRequestDetails"
|
||||
"ca.uhn.fhir.rest.api.RestOperationTypeEnum"
|
||||
),
|
||||
|
||||
|
||||
|
|
|
@ -62,47 +62,25 @@ public class UrlUtil {
|
|||
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);
|
||||
|
||||
public static String sanitizeBaseUrl(String theBaseUrl) {
|
||||
return theBaseUrl.replaceAll("[^a-zA-Z0-9:/._-]", "");
|
||||
/**
|
||||
* Non instantiable
|
||||
*/
|
||||
private UrlUtil() {
|
||||
}
|
||||
|
||||
public static class UrlParts {
|
||||
private String myParams;
|
||||
private String myResourceId;
|
||||
private String myResourceType;
|
||||
private String myVersionId;
|
||||
/**
|
||||
* Cleans up a value that will be serialized as an HTTP header. This method:
|
||||
* <p>
|
||||
* - Strips any newline (\r or \n) characters
|
||||
*
|
||||
* @since 6.2.0
|
||||
*/
|
||||
public static String sanitizeHeaderValue(String theHeader) {
|
||||
return theHeader.replace("\n", "").replace("\r", "");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public static String sanitizeBaseUrl(String theBaseUrl) {
|
||||
return theBaseUrl.replaceAll("[^a-zA-Z0-9:/._-]", "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,7 +164,6 @@ public class UrlUtil {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAbsolute(String theValue) {
|
||||
String value = theValue.toLowerCase();
|
||||
return value.startsWith("http://") || value.startsWith("https://");
|
||||
|
@ -570,4 +547,43 @@ public class UrlUtil {
|
|||
|
||||
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.ResourceNotFoundException;
|
||||
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.util.CompositeInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.rest.server.util.ResourceSearchParams;
|
||||
|
@ -224,28 +223,18 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
@Autowired
|
||||
ExpungeService myExpungeService;
|
||||
@Autowired
|
||||
private HistoryBuilderFactory myHistoryBuilderFactory;
|
||||
@Autowired
|
||||
private DaoConfig myConfig;
|
||||
@Autowired
|
||||
private PlatformTransactionManager myPlatformTransactionManager;
|
||||
@Autowired
|
||||
private ISearchCacheSvc mySearchCacheSvc;
|
||||
@Autowired
|
||||
private ISearchParamPresenceSvc mySearchParamPresenceSvc;
|
||||
@Autowired
|
||||
private SearchParamWithInlineReferencesExtractor mySearchParamWithInlineReferencesExtractor;
|
||||
@Autowired
|
||||
private DaoSearchParamSynchronizer myDaoSearchParamSynchronizer;
|
||||
@Autowired
|
||||
private SearchBuilderFactory mySearchBuilderFactory;
|
||||
private FhirContext myContext;
|
||||
private ApplicationContext myApplicationContext;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
@Autowired
|
||||
private RequestPartitionHelperSvc myRequestPartitionHelperSvc;
|
||||
@Autowired
|
||||
private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory;
|
||||
@Autowired
|
||||
private IPartitionLookupSvc myPartitionLookupSvc;
|
||||
|
@ -272,7 +261,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
|
||||
@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
|
||||
* 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) {
|
||||
HashSet<ResourceTag> retVal = Sets.newHashSet();
|
||||
if (theEntity.isHasTags()) {
|
||||
for (ResourceTag next : theEntity.getTags()) {
|
||||
retVal.add(next);
|
||||
}
|
||||
retVal.addAll(theEntity.getTags());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
@ -1505,9 +1492,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
oldResource = toResource(entity, false);
|
||||
}
|
||||
|
||||
if (theRequest.getServer() != null) {
|
||||
ActionRequestDetails actionRequestDetails = new ActionRequestDetails(theRequest, theResource, theResourceId.getResourceType(), theResourceId);
|
||||
}
|
||||
notifyInterceptors(theRequest, theResource, oldResource, theTransactionDetails, true);
|
||||
|
||||
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
|
||||
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
|
||||
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.ResourceVersionConflictException;
|
||||
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.util.CompositeInterceptorBroadcaster;
|
||||
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.annotation.Propagation;
|
||||
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.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> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class);
|
||||
public static final String BASE_RESOURCE_NAME = "resource";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class);
|
||||
@Autowired
|
||||
protected PlatformTransactionManager myPlatformTransactionManager;
|
||||
@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();
|
||||
boolean resourceHadIdBeforeStorage = isNotBlank(resourceIdBeforeStorage);
|
||||
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);
|
||||
|
||||
// Notify interceptors
|
||||
if (theRequestDetails != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
|
||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
||||
}
|
||||
|
||||
ResourceTable savedEntity = updateEntityForDelete(theRequestDetails, theTransactionDetails, entity);
|
||||
resourceToDelete.setId(entity.getIdDt());
|
||||
|
||||
|
@ -704,20 +690,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
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
|
||||
|
||||
updateEntityForDelete(theRequest, transactionDetails, entity);
|
||||
resourceToDelete.setId(entity.getIdDt());
|
||||
|
||||
// Notify JPA interceptors
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@Override
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
HookParams hookParams = new HookParams()
|
||||
|
@ -937,10 +916,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
@Transactional
|
||||
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();
|
||||
IBundleProvider retVal = super.history(theRequestDetails, myResourceName, null, theSince, theUntil, theOffset);
|
||||
ourLog.debug("Processed history on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
||||
|
@ -950,12 +925,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
@Transactional
|
||||
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();
|
||||
|
||||
IIdType id = theId.withResourceType(myResourceName).toUnqualifiedVersionless();
|
||||
|
@ -990,7 +959,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
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);
|
||||
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) {
|
||||
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();
|
||||
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
||||
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) {
|
||||
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();
|
||||
BaseHasResource entity = readEntity(theResourceId, theRequest);
|
||||
if (entity == null) {
|
||||
|
@ -1102,12 +1059,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
@Transactional
|
||||
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<>();
|
||||
BaseHasResource entity = readEntity(theId, theRequest);
|
||||
for (BaseTag next : entity.getTags()) {
|
||||
|
@ -1124,12 +1075,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
@Transactional
|
||||
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)";
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||
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) {
|
||||
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();
|
||||
BaseHasResource entity = readEntity(theId, theRequest);
|
||||
validateResourceType(entity);
|
||||
|
@ -1485,12 +1423,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Transactional
|
||||
@Override
|
||||
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();
|
||||
BaseHasResource entity = readEntity(theId, theRequest);
|
||||
if (entity == null) {
|
||||
|
@ -1587,8 +1519,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
private void notifySearchInterceptors(SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
if (theRequest != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), getResourceName(), null);
|
||||
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
||||
|
||||
if (theRequest.isSubRequest()) {
|
||||
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) {
|
||||
TransactionDetails transactionDetails = new TransactionDetails();
|
||||
|
||||
if (theRequest != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, theResource, null, theId);
|
||||
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
|
||||
}
|
||||
|
||||
if (theMode == ValidationModeEnum.DELETE) {
|
||||
if (theId == null || theId.hasIdPart() == false) {
|
||||
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.util.QueryChunker;
|
||||
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.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
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> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirSystemDao.class);
|
||||
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;
|
||||
@Autowired
|
||||
private TransactionProcessor myTransactionProcessor;
|
||||
|
@ -125,12 +123,6 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
|
||||
@Override
|
||||
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();
|
||||
IBundleProvider retVal = super.history(theRequestDetails, null, null, theSince, theUntil, theOffset);
|
||||
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.rest.api.CacheControlDirective;
|
||||
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.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.*;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
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.IPrimitiveType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -91,9 +92,6 @@ public class FhirResourceDaoPatientDstu2 extends BaseHapiFhirResourceDao<Patient
|
|||
@Override
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
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()));
|
||||
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
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
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.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
||||
import javax.persistence.TypedQuery;
|
||||
|
@ -36,10 +34,6 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
|
||||
@Override
|
||||
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)";
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||
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.rest.api.RestOperationTypeEnum;
|
||||
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.Meta;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
@ -45,10 +44,6 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
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)";
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||
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.FhirResourceDaoMessageHeaderDstu2;
|
||||
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.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Meta;
|
||||
|
@ -38,10 +36,6 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
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)";
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||
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.FhirResourceDaoMessageHeaderDstu2;
|
||||
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.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Meta;
|
||||
|
@ -40,10 +38,6 @@ public class FhirSystemDaoR5 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
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)";
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||
|
|
|
@ -224,8 +224,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
|
|||
|
||||
transaction(bundle);
|
||||
|
||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(2)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
||||
assertEquals(RestOperationTypeEnum.CREATE, myParamsCaptor.getValue().get(RestOperationTypeEnum.class));
|
||||
verify(interceptor, timeout(10 * MILLIS_PER_SECOND).times(1)).invoke(eq(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED), myParamsCaptor.capture());
|
||||
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.STORAGE_PRECOMMIT_RESOURCE_CREATED), myParamsCaptor.capture());
|
||||
|
@ -326,9 +326,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
|
|||
entry.getRequest().setIfNoneExist("Patient?name=" + methodName);
|
||||
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.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_UPDATED), any());
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import ca.uhn.fhir.batch2.jobs.expunge.DeleteExpungeProvider;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
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.jpa.api.config.DaoConfig;
|
||||
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.PatientResourceProvider;
|
||||
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.searchparam.SearchParameterMap;
|
||||
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.MethodOutcome;
|
||||
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.api.IGenericClient;
|
||||
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.interceptor.RequestValidatingInterceptor;
|
||||
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.test.utilities.BatchJobHelper;
|
||||
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.BundleType;
|
||||
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.DecimalType;
|
||||
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.Parameters;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Practitioner;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -83,6 +94,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -117,6 +129,8 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
|||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
||||
myDaoConfig.setDeleteExpungeEnabled(new DaoConfig().isDeleteExpungeEnabled());
|
||||
myDaoConfig.setAutoCreatePlaceholderReferenceTargets(new DaoConfig().isAutoCreatePlaceholderReferenceTargets());
|
||||
myDaoConfig.setPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets(new DaoConfig().isPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
|
@ -144,11 +158,15 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
|
|||
diagnosticReportRp.setDao(myDiagnosticReportDao);
|
||||
ServiceRequestResourceProvider diagnosticOrderRp = new ServiceRequestResourceProvider();
|
||||
diagnosticOrderRp.setDao(myServiceRequestDao);
|
||||
|
||||
PractitionerResourceProvider practitionerRp = new PractitionerResourceProvider();
|
||||
practitionerRp.setDao(myPractitionerDao);
|
||||
|
||||
PractitionerRoleResourceProvider practitionerRoleRp = new PractitionerRoleResourceProvider();
|
||||
practitionerRoleRp.setDao(myPractitionerRoleDao);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
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.ScheduledJobDefinition;
|
||||
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.server.interceptor.InterceptorAdapter;
|
||||
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 {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AnalyticsInterceptor.class);
|
||||
|
||||
private final LinkedList<AnalyticsEvent> myEventBuffer = new LinkedList<>();
|
||||
private String myAnalyticsTid;
|
||||
private int myCollectThreshold = 100000;
|
||||
private final LinkedList<AnalyticsEvent> myEventBuffer = new LinkedList<>();
|
||||
private String myHostname;
|
||||
private HttpClient myHttpClient;
|
||||
private long mySubmitPeriod = 60000;
|
||||
|
@ -63,16 +63,6 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
|||
mySchedulerService.scheduleLocalJob(5000, jobDetail);
|
||||
}
|
||||
|
||||
public static class Job implements HapiJob {
|
||||
@Autowired
|
||||
private AnalyticsInterceptor myAnalyticsInterceptor;
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext theContext) {
|
||||
myAnalyticsInterceptor.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stop() throws IOException {
|
||||
if (myHttpClient instanceof CloseableHttpClient) {
|
||||
|
@ -145,8 +135,8 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theRequest) {
|
||||
ServletRequestDetails details = (ServletRequestDetails) theRequest.getRequestDetails();
|
||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, RequestDetails theRequest) {
|
||||
ServletRequestDetails details = (ServletRequestDetails) theRequest;
|
||||
|
||||
// Make sure we only send one event per request
|
||||
if (details.getUserData().containsKey(getClass().getName())) {
|
||||
|
@ -183,6 +173,16 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
|||
myAnalyticsTid = theAnalyticsTid;
|
||||
}
|
||||
|
||||
public static class Job implements HapiJob {
|
||||
@Autowired
|
||||
private AnalyticsInterceptor myAnalyticsInterceptor;
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext theContext) {
|
||||
myAnalyticsInterceptor.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AnalyticsEvent {
|
||||
private String myApplicationName;
|
||||
private String myClientId;
|
||||
|
@ -196,46 +196,46 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
|
|||
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) {
|
||||
myApplicationName = theApplicationName;
|
||||
}
|
||||
|
||||
String getClientId() {
|
||||
return myClientId;
|
||||
}
|
||||
|
||||
void setClientId(String theClientId) {
|
||||
myClientId = theClientId;
|
||||
}
|
||||
|
||||
String getResourceName() {
|
||||
return myResourceName;
|
||||
}
|
||||
|
||||
void setResourceName(String theResourceName) {
|
||||
myResourceName = theResourceName;
|
||||
}
|
||||
|
||||
RestOperationTypeEnum getRestOperation() {
|
||||
return myRestOperation;
|
||||
}
|
||||
|
||||
void setRestOperation(RestOperationTypeEnum theRestOperation) {
|
||||
myRestOperation = theRestOperation;
|
||||
}
|
||||
|
||||
String getSourceIp() {
|
||||
return mySourceIp;
|
||||
}
|
||||
|
||||
void setSourceIp(String theSourceIp) {
|
||||
mySourceIp = theSourceIp;
|
||||
}
|
||||
|
||||
String getUserAgent() {
|
||||
return myUserAgent;
|
||||
}
|
||||
|
||||
void setUserAgent(String theUserAgent) {
|
||||
myUserAgent = theUserAgent;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,6 @@ public interface IServerInterceptor {
|
|||
* 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.
|
||||
* 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)}
|
||||
* are.
|
||||
* <p>
|
||||
|
@ -132,7 +131,7 @@ public interface IServerInterceptor {
|
|||
* server, e.g. the FHIR operation type and the parsed resource body (if any).
|
||||
*/
|
||||
@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
|
||||
|
@ -291,168 +290,4 @@ public interface IServerInterceptor {
|
|||
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED_NORMALLY)
|
||||
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%
|
||||
*/
|
||||
|
||||
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.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
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;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
||||
|
@ -44,7 +42,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
|||
|
||||
@Override
|
||||
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws ServletException, IOException {
|
||||
throws ServletException, IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -54,7 +52,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theProcessedRequest) {
|
||||
public void incomingRequestPreHandled(RestOperationTypeEnum theOperation, RequestDetails theProcessedRequest) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
@ -82,7 +80,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
|||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws AuthenticationException {
|
||||
throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -99,7 +97,7 @@ public class InterceptorAdapter implements IServerInterceptor {
|
|||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws AuthenticationException {
|
||||
throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,8 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation, IBaseResource theRequestResource) {
|
||||
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation) {
|
||||
|
||||
switch (theOperation) {
|
||||
case ADD_TAGS:
|
||||
case DELETE_TAGS:
|
||||
|
@ -232,13 +233,6 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
|||
case CREATE:
|
||||
case UPDATE:
|
||||
case PATCH:
|
||||
// if (theRequestResource != null) {
|
||||
// if (theRequestResource.getIdElement() != null) {
|
||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return OperationExamineDirection.IN;
|
||||
|
||||
case META:
|
||||
|
@ -363,7 +357,7 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
|||
IBaseResource inputResource = null;
|
||||
IIdType inputResourceId = null;
|
||||
|
||||
switch (determineOperationDirection(theRequest.getRestOperationType(), theRequest.getResource())) {
|
||||
switch (determineOperationDirection(theRequest.getRestOperationType())) {
|
||||
case IN:
|
||||
case BOTH:
|
||||
inputResource = theRequest.getResource();
|
||||
|
@ -422,7 +416,8 @@ public class AuthorizationInterceptor implements IRuleApplier {
|
|||
}
|
||||
|
||||
private void checkOutgoingResourceAndFailIfDeny(RequestDetails theRequestDetails, IBaseResource theResponseObject, Pointcut thePointcut) {
|
||||
switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) {
|
||||
|
||||
switch (determineOperationDirection(theRequestDetails.getRestOperationType())) {
|
||||
case IN:
|
||||
case NONE:
|
||||
return;
|
||||
|
|
|
@ -52,6 +52,9 @@ public class RuleImplConditional extends BaseRule implements IAuthRule {
|
|||
if (theRequestDetails.getConditionalUrl(myOperationType) == null) {
|
||||
return null;
|
||||
}
|
||||
if (theInputResource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (myAppliesTo) {
|
||||
case ALL_RESOURCES:
|
||||
|
@ -65,7 +68,7 @@ public class RuleImplConditional extends BaseRule implements IAuthRule {
|
|||
}
|
||||
} else {
|
||||
String inputResourceName = theRequestDetails.getFhirContext().getResourceType(theInputResource);
|
||||
if (theInputResource == null || !myAppliesToTypes.contains(inputResourceName)) {
|
||||
if (!myAppliesToTypes.contains(inputResourceName)) {
|
||||
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.exceptions.BaseServerResponseException;
|
||||
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.util.ReflectionUtil;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -242,15 +241,13 @@ public abstract class BaseMethodBinding {
|
|||
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
||||
if (operationType != null) {
|
||||
|
||||
ActionRequestDetails details = new ActionRequestDetails(theRequest);
|
||||
populateActionRequestDetailsForInterceptor(theRequest, details, theMethodParams);
|
||||
populateRequestDetailsForInterceptor(theRequest, theMethodParams);
|
||||
|
||||
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||
HookParams preHandledParams = new HookParams();
|
||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||
preHandledParams.add(RequestDetails.class, theRequest);
|
||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||
preHandledParams.add(ActionRequestDetails.class, details);
|
||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||
theRequest
|
||||
.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
|
||||
* interceptors.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
||||
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||
// 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.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private Integer myIdParamIndex;
|
||||
private String myResourceName;
|
||||
private final Integer myIdParamIndex;
|
||||
private final String myResourceName;
|
||||
private int myResourceParameterIndex = -1;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
private Class<? extends IIdType> myIdParamType;
|
||||
|
@ -122,8 +121,8 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
||||
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (theDetails != null) {
|
||||
theDetails.setResource(resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.rest.server.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
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.Pointcut;
|
||||
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.exceptions.BaseServerResponseException;
|
||||
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 org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||
|
||||
|
@ -152,15 +151,15 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
// Handle server action interceptors
|
||||
RestOperationTypeEnum operationType = getRestOperationType(theRequest);
|
||||
if (operationType != null) {
|
||||
IServerInterceptor.ActionRequestDetails details = new IServerInterceptor.ActionRequestDetails(theRequest);
|
||||
populateActionRequestDetailsForInterceptor(theRequest, details, theMethodParams);
|
||||
|
||||
populateRequestDetailsForInterceptor(theRequest, theMethodParams);
|
||||
|
||||
// Interceptor hook: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||
HookParams preHandledParams = new HookParams();
|
||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||
preHandledParams.add(RequestDetails.class, theRequest);
|
||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||
preHandledParams.add(IServerInterceptor.ActionRequestDetails.class, details);
|
||||
theRequest
|
||||
.getInterceptorBroadcaster()
|
||||
.callHooks(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, preHandledParams);
|
||||
|
@ -239,7 +238,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
public IBaseConformance provideCapabilityStatement(RestfulServer theServer, RequestDetails theRequest) {
|
||||
Object[] params = createMethodParams(theRequest);
|
||||
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.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
@ -373,14 +372,10 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails
|
||||
theDetails, Object[] theMethodParams) {
|
||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
||||
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||
IBaseResource resource = (IBaseResource) theRequestDetails.getUserData().get(OperationParameter.REQUEST_CONTENTS_USERDATA_KEY);
|
||||
theRequestDetails.setResource(resource);
|
||||
if (theDetails != null) {
|
||||
theDetails.setResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isManualRequestMode() {
|
||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.rest.server.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
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.Pointcut;
|
||||
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.InvalidRequestException;
|
||||
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.util.ReflectionUtil;
|
||||
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 {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PageMethodBinding.class);
|
||||
|
||||
public PageMethodBinding(FhirContext theContext, Method theMethod) {
|
||||
super(null, theMethod, theContext, null);
|
||||
}
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PageMethodBinding.class);
|
||||
|
||||
public IBaseResource provider() {
|
||||
return null;
|
||||
}
|
||||
|
@ -91,13 +90,11 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
// Interceptor invoke: SERVER_INCOMING_REQUEST_PRE_HANDLED
|
||||
IServerInterceptor.ActionRequestDetails details = new IServerInterceptor.ActionRequestDetails(theRequest);
|
||||
populateActionRequestDetailsForInterceptor(theRequest, details, ReflectionUtil.EMPTY_OBJECT_ARRAY);
|
||||
populateRequestDetailsForInterceptor(theRequest, ReflectionUtil.EMPTY_OBJECT_ARRAY);
|
||||
HookParams preHandledParams = new HookParams();
|
||||
preHandledParams.add(RestOperationTypeEnum.class, theRequest.getRestOperationType());
|
||||
preHandledParams.add(RequestDetails.class, theRequest);
|
||||
preHandledParams.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||
preHandledParams.add(IServerInterceptor.ActionRequestDetails.class, details);
|
||||
if (theRequest.getInterceptorBroadcaster() != null) {
|
||||
theRequest
|
||||
.getInterceptorBroadcaster()
|
||||
|
@ -152,8 +149,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
}
|
||||
|
||||
String linkSelfBase = theRequest.getFhirServerBase(); // myServerAddressStrategy.determineServerBase(getServletContext(),
|
||||
// theRequest.getServletRequest());
|
||||
String linkSelfBase = theRequest.getFhirServerBase();
|
||||
String completeUrl = theRequest.getCompleteUrl();
|
||||
String linkSelf = linkSelfBase + completeUrl.substring(theRequest.getCompleteUrl().indexOf('?'));
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.rest.server.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
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.valueset.BundleTypeEnum;
|
||||
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.server.exceptions.InternalErrorException;
|
||||
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 org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -58,8 +57,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
if (next instanceof TransactionParameter) {
|
||||
if (myTransactionParamIndex != -1) {
|
||||
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
|
||||
+ " methods");
|
||||
+ TransactionParam.class + " annotation, exactly one is required for @" + Transaction.class
|
||||
+ " methods");
|
||||
}
|
||||
myTransactionParamIndex = index;
|
||||
myTransactionParamStyle = ((TransactionParameter) next).getParamStyle();
|
||||
|
@ -69,7 +68,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
|
||||
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 @"
|
||||
+ TransactionParam.class + " annotation");
|
||||
+ TransactionParam.class + " annotation");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,8 +142,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
||||
protected void populateRequestDetailsForInterceptor(RequestDetails theRequestDetails, Object[] theMethodParams) {
|
||||
super.populateRequestDetailsForInterceptor(theRequestDetails, theMethodParams);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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.util.OperationOutcomeUtil;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
@ -262,6 +263,8 @@ public class BulkDataImportProvider {
|
|||
|
||||
public void writePollingLocationToResponseHeaders(ServletRequestDetails theRequestDetails, String theJobId) {
|
||||
String pollLocation = createPollLocationLink(theRequestDetails, theJobId);
|
||||
pollLocation = UrlUtil.sanitizeHeaderValue(pollLocation);
|
||||
|
||||
HttpServletResponse response = theRequestDetails.getServletResponse();
|
||||
// Add standard headers
|
||||
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.OperationOutcomeUtil;
|
||||
import ca.uhn.fhir.util.SearchParameterUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -113,7 +114,7 @@ public class BulkDataExportProvider {
|
|||
}
|
||||
|
||||
private void startJob(ServletRequestDetails theRequestDetails,
|
||||
BulkDataExportOptions theOptions){
|
||||
BulkDataExportOptions theOptions) {
|
||||
// permission check
|
||||
HookParams params = (new HookParams()).add(BulkDataExportOptions.class, theOptions)
|
||||
.add(RequestDetails.class, theRequestDetails)
|
||||
|
@ -124,7 +125,6 @@ public class BulkDataExportProvider {
|
|||
boolean useCache = shouldUseCache(theRequestDetails);
|
||||
|
||||
|
||||
|
||||
BulkExportParameters parameters = BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions);
|
||||
parameters.setUseExistingJobsFirst(useCache);
|
||||
|
||||
|
@ -434,6 +434,7 @@ public class BulkDataExportProvider {
|
|||
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();
|
||||
pollLocation = UrlUtil.sanitizeHeaderValue(pollLocation);
|
||||
|
||||
HttpServletResponse response = theRequestDetails.getServletResponse();
|
||||
|
||||
|
@ -445,14 +446,6 @@ public class BulkDataExportProvider {
|
|||
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) {
|
||||
if (theTypeFilter == null) {
|
||||
return null;
|
||||
|
@ -470,4 +463,12 @@ public class BulkDataExportProvider {
|
|||
|
||||
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.model.api.IQueryParameterAnd;
|
||||
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.IPreResourceShowDetails;
|
||||
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.TransactionDetails;
|
||||
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.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
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.util.CompositeInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
|
@ -106,42 +103,6 @@ public abstract class BaseStorageDao {
|
|||
@Autowired
|
||||
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
|
||||
public void setSearchParamRegistry(ISearchParamRegistry theSearchParamRegistry) {
|
||||
mySearchParamRegistry = theSearchParamRegistry;
|
||||
|
@ -171,7 +132,7 @@ public abstract class BaseStorageDao {
|
|||
|
||||
verifyBundleTypeIsAppropriateForStorage(theResource);
|
||||
|
||||
if(!getConfig().getTreatBaseUrlsAsLocal().isEmpty()) {
|
||||
if (!getConfig().getTreatBaseUrlsAsLocal().isEmpty()) {
|
||||
replaceAbsoluteReferencesWithRelative(theResource, myFhirContext.newTerser());
|
||||
}
|
||||
|
||||
|
@ -219,16 +180,16 @@ public abstract class BaseStorageDao {
|
|||
* Replace absolute references with relative ones if configured to do so
|
||||
*/
|
||||
private void replaceAbsoluteReferencesWithRelative(IBaseResource theResource, FhirTerser theTerser) {
|
||||
List<ResourceReferenceInfo> refs = theTerser.getAllResourceReferences(theResource);
|
||||
for (ResourceReferenceInfo nextRef : refs) {
|
||||
IIdType refId = nextRef.getResourceReference().getReferenceElement();
|
||||
if (refId != null && refId.hasBaseUrl()) {
|
||||
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
|
||||
IIdType newRefId = refId.toUnqualified();
|
||||
nextRef.getResourceReference().setReference(newRefId.getValue());
|
||||
}
|
||||
List<ResourceReferenceInfo> refs = theTerser.getAllResourceReferences(theResource);
|
||||
for (ResourceReferenceInfo nextRef : refs) {
|
||||
IIdType refId = nextRef.getResourceReference().getReferenceElement();
|
||||
if (refId != null && refId.hasBaseUrl()) {
|
||||
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
|
||||
IIdType newRefId = refId.toUnqualified();
|
||||
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())) {
|
||||
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());
|
||||
/**
|
||||
* @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();
|
||||
}
|
||||
|
||||
if (theRequestDetails.getUserData().get(PROCESSING_SUB_REQUEST) == Boolean.TRUE) {
|
||||
theRequestDetails.notifyIncomingRequestPreHandled(theOperationType);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -203,11 +203,6 @@ public abstract class BaseTransactionProcessor {
|
|||
}
|
||||
|
||||
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";
|
||||
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.RestfulServer;
|
||||
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.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
@ -132,7 +131,7 @@ public class InterceptorUserDataMapDstu2Test {
|
|||
}
|
||||
|
||||
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
||||
public void incomingRequestPreHandled(ActionRequestDetails theRequestDetails) {
|
||||
public void incomingRequestPreHandled(RequestDetails theRequestDetails) {
|
||||
updateMapUsing(theRequestDetails.getUserData(), "incomingRequestPreHandled");
|
||||
}
|
||||
|
||||
|
@ -185,7 +184,7 @@ public class InterceptorUserDataMapDstu2Test {
|
|||
}
|
||||
|
||||
public Map<String, Patient> getIdToPatient() {
|
||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
||||
Map<String, Patient> idToPatient = new HashMap<>();
|
||||
{
|
||||
Patient patient = createPatient1();
|
||||
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.server.IResourceProvider;
|
||||
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.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -62,13 +61,6 @@ public class ServerActionInterceptorTest {
|
|||
private static IServerInterceptor ourInterceptor;
|
||||
private static IGenericClient ourFhirClient;
|
||||
|
||||
@AfterAll
|
||||
public static void afterClassClearContext() throws Exception {
|
||||
JettyUtil.closeServer(ourServer);
|
||||
TestUtil.randomizeLocaleAndTimezone();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123");
|
||||
|
@ -77,10 +69,10 @@ public class ServerActionInterceptorTest {
|
|||
|
||||
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());
|
||||
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
RequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient/123", details.getId().getValue());
|
||||
}
|
||||
|
||||
|
@ -92,10 +84,10 @@ public class ServerActionInterceptorTest {
|
|||
|
||||
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());
|
||||
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
RequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient/123/_history/456", details.getId().getValue());
|
||||
}
|
||||
|
||||
|
@ -105,11 +97,11 @@ public class ServerActionInterceptorTest {
|
|||
patient.addName().addFamily("FAMILY");
|
||||
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());
|
||||
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
RequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient", details.getResourceName());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
||||
}
|
||||
|
@ -120,11 +112,11 @@ public class ServerActionInterceptorTest {
|
|||
observation.getCode().setText("OBSCODE");
|
||||
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());
|
||||
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Observation", details.getResourceType());
|
||||
RequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Observation", details.getResourceName());
|
||||
assertEquals(Observation.class, details.getResource().getClass());
|
||||
assertEquals("OBSCODE", ((Observation) details.getResource()).getCode().getText());
|
||||
}
|
||||
|
@ -136,11 +128,11 @@ public class ServerActionInterceptorTest {
|
|||
patient.setId("Patient/123");
|
||||
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());
|
||||
|
||||
ActionRequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient", details.getResourceType());
|
||||
RequestDetails details = detailsCapt.getValue();
|
||||
assertEquals("Patient", details.getResourceName());
|
||||
assertEquals("Patient/123", details.getId().getValue());
|
||||
assertEquals(Patient.class, details.getResource().getClass());
|
||||
assertEquals("FAMILY", ((Patient) details.getResource()).getName().get(0).getFamily().get(0).getValue());
|
||||
|
@ -155,7 +147,7 @@ public class ServerActionInterceptorTest {
|
|||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -167,9 +159,9 @@ public class ServerActionInterceptorTest {
|
|||
|
||||
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());
|
||||
assertEquals("Patient", detailsCapt.getValue().getResourceType());
|
||||
assertEquals("Patient", detailsCapt.getValue().getResourceName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -180,12 +172,29 @@ public class ServerActionInterceptorTest {
|
|||
|
||||
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());
|
||||
assertEquals("Patient", detailsCapt.getValue().getResourceType());
|
||||
assertEquals("Patient", detailsCapt.getValue().getResourceName());
|
||||
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
|
||||
public static void beforeClass() throws Exception {
|
||||
ourServer = new Server(0);
|
||||
|
@ -202,7 +211,7 @@ public class ServerActionInterceptorTest {
|
|||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
JettyUtil.startServer(ourServer);
|
||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
|
@ -212,23 +221,12 @@ public class ServerActionInterceptorTest {
|
|||
ourInterceptor = mock(InterceptorAdapter.class);
|
||||
servlet.registerInterceptor(ourInterceptor);
|
||||
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(240*1000);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(240 * 1000);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
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 {
|
||||
|
||||
@History()
|
||||
|
|
|
@ -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.server.exceptions.AuthenticationException;
|
||||
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.ServerOperationInterceptorAdapter;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
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(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true);
|
||||
|
||||
doAnswer(t->{
|
||||
doAnswer(t -> {
|
||||
RestOperationTypeEnum type = (RestOperationTypeEnum) t.getArguments()[0];
|
||||
ActionRequestDetails det = (ActionRequestDetails) t.getArguments()[1];
|
||||
RequestDetails det = (RequestDetails) t.getArguments()[1];
|
||||
return null;
|
||||
}).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(myInterceptor2, times(1)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.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(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());
|
||||
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)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.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<OperationOutcome> resourceCapt = ArgumentCaptor.forClass(OperationOutcome.class);
|
||||
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)).incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.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);
|
||||
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||
order.verify(myInterceptor1, times(1)).outgoingResponse(nullable(ServletRequestDetails.class), resourceCapt.capture());
|
||||
|
@ -315,6 +313,35 @@ public class InterceptorDstu3Test {
|
|||
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 {
|
||||
|
||||
@Create()
|
||||
|
@ -323,10 +350,10 @@ public class InterceptorDstu3Test {
|
|||
return new MethodOutcome().setCreated(true);
|
||||
}
|
||||
|
||||
@Operation(name="$postOperation")
|
||||
@Operation(name = "$postOperation")
|
||||
public Parameters postOperation(
|
||||
@OperationParam(name = "limit") IntegerType theLimit
|
||||
) {
|
||||
) {
|
||||
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.IInterceptorBroadcaster;
|
||||
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.rest.annotation.ConditionalUrlParam;
|
||||
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.RestOperationTypeEnum;
|
||||
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.SimplePreResourceShowDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
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.RestfulServer;
|
||||
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.tenant.UrlBaseTenantIdentificationStrategy;
|
||||
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.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
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 CloseableHttpClient ourClient;
|
||||
private static String ourConditionalCreateId;
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
private static final FhirContext ourCtx = FhirContext.forR4();
|
||||
private static boolean ourHitMethod;
|
||||
private static int ourPort;
|
||||
private static List<Resource> ourReturn;
|
||||
|
@ -1173,7 +1174,7 @@ public class AuthorizationInterceptorR4Test {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void testCodeIn_TransactionCreate() throws IOException {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
|
@ -2540,7 +2541,7 @@ public class AuthorizationInterceptorR4Test {
|
|||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
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
|
||||
public boolean matches(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IIdType theInputResourceId, IBaseResource theInputResource) {
|
||||
return theInputResourceId.getIdPart().equals("1");
|
||||
|
@ -4202,6 +4203,47 @@ public class AuthorizationInterceptorR4Test {
|
|||
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 {
|
||||
|
||||
@Override
|
||||
|
@ -4263,7 +4305,6 @@ public class AuthorizationInterceptorR4Test {
|
|||
|
||||
}
|
||||
|
||||
|
||||
public static class DummyDiagnosticReportResourceProvider implements IResourceProvider {
|
||||
|
||||
|
||||
|
@ -4297,6 +4338,7 @@ public class AuthorizationInterceptorR4Test {
|
|||
}
|
||||
return (Device) ourReturn.get(0);
|
||||
}
|
||||
|
||||
@Search()
|
||||
public List<Resource> search(
|
||||
@OptionalParam(name = "patient") ReferenceParam thePatient
|
||||
|
@ -4377,15 +4419,29 @@ public class AuthorizationInterceptorR4Test {
|
|||
|
||||
if (isNotBlank(theConditionalUrl)) {
|
||||
IdType actual = new IdType("Observation", ourConditionalCreateId);
|
||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
|
||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
||||
theResource.setId(actual);
|
||||
} else {
|
||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
|
||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
||||
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();
|
||||
retVal.setResource(theResource);
|
||||
return retVal;
|
||||
|
@ -4431,20 +4487,18 @@ public class AuthorizationInterceptorR4Test {
|
|||
@Create()
|
||||
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;
|
||||
theResource.setId("Patient/1/_history/1");
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
retVal.setCreated(true);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4521,8 +4575,7 @@ public class AuthorizationInterceptorR4Test {
|
|||
public MethodOutcome patch(@IdParam IdType theId, @ResourceParam String theResource, PatchTypeEnum thePatchType) {
|
||||
ourHitMethod = true;
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
return retVal;
|
||||
return new MethodOutcome();
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
|
@ -4546,15 +4599,28 @@ public class AuthorizationInterceptorR4Test {
|
|||
|
||||
if (isNotBlank(theConditionalUrl)) {
|
||||
IdType actual = new IdType("Patient", ourConditionalCreateId);
|
||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
|
||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
||||
theResource.setId(actual);
|
||||
} else {
|
||||
ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
|
||||
subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
|
||||
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();
|
||||
retVal.setResource(theResource);
|
||||
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