use of com.evolveum.midpoint.model.impl.lens.LensProjectionContext in project midpoint by Evolveum.
the class ContextLoader method loadLinkRefsFromDelta.
private <F extends FocusType> void loadLinkRefsFromDelta(LensContext<F> context, PrismObject<F> focus, ObjectDelta<F> focusPrimaryDelta, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
if (focusPrimaryDelta == null) {
return;
}
ReferenceDelta linkRefDelta;
if (focusPrimaryDelta.getChangeType() == ChangeType.ADD) {
PrismReference linkRef = focusPrimaryDelta.getObjectToAdd().findReference(FocusType.F_LINK_REF);
if (linkRef == null) {
// Adding new focus with no linkRef -> nothing to do
return;
}
linkRefDelta = linkRef.createDelta(new ItemPath(FocusType.F_LINK_REF));
linkRefDelta.addValuesToAdd(PrismValue.cloneValues(linkRef.getValues()));
} else if (focusPrimaryDelta.getChangeType() == ChangeType.MODIFY) {
linkRefDelta = focusPrimaryDelta.findReferenceModification(FocusType.F_LINK_REF);
if (linkRefDelta == null) {
return;
}
} else {
// delete, all existing account are already marked for delete
return;
}
if (linkRefDelta.isReplace()) {
// process "replace" by distributing values to delete and add
linkRefDelta = (ReferenceDelta) linkRefDelta.clone();
PrismReference linkRef = focus.findReference(FocusType.F_LINK_REF);
linkRefDelta.distributeReplace(linkRef == null ? null : linkRef.getValues());
}
if (linkRefDelta.getValuesToAdd() != null) {
for (PrismReferenceValue refVal : linkRefDelta.getValuesToAdd()) {
String oid = refVal.getOid();
LensProjectionContext accountContext = null;
PrismObject<ShadowType> shadow = null;
boolean isCombinedAdd = false;
if (oid == null) {
// Adding new account
shadow = refVal.getObject();
if (shadow == null) {
throw new SchemaException("Null or empty OID in account reference " + refVal + " in " + focus);
}
provisioningService.applyDefinition(shadow, task, result);
if (consistencyChecks)
ShadowUtil.checkConsistence(shadow, "account from " + linkRefDelta);
// Check for conflicting change
accountContext = LensUtil.getProjectionContext(context, shadow, provisioningService, prismContext, task, result);
if (accountContext != null) {
// There is already existing context for the same discriminator. Tolerate this only if
// the deltas match. It is an error otherwise.
ObjectDelta<ShadowType> primaryDelta = accountContext.getPrimaryDelta();
if (primaryDelta == null) {
throw new SchemaException("Attempt to add " + shadow + " to a user that already contains " + accountContext.getHumanReadableKind() + " of type '" + accountContext.getResourceShadowDiscriminator().getIntent() + "' on " + accountContext.getResource());
}
if (!primaryDelta.isAdd()) {
throw new SchemaException("Conflicting changes in the context. " + "Add of accountRef in the user delta with embedded object conflicts with explicit delta " + primaryDelta);
}
if (!shadow.equals(primaryDelta.getObjectToAdd())) {
throw new SchemaException("Conflicting changes in the context. " + "Add of accountRef in the user delta with embedded object is not adding the same object as explicit delta " + primaryDelta);
}
} else {
// Create account context from embedded object
accountContext = createProjectionContext(context, shadow, task, result);
}
// This is a new account that is to be added. So it should
// go to account primary delta
ObjectDelta<ShadowType> accountPrimaryDelta = shadow.createAddDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
accountContext.setFullShadow(true);
accountContext.setExists(false);
isCombinedAdd = true;
} else {
// therefore check for account existence to decide
try {
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
GetOperationOptions rootOpts = GetOperationOptions.createNoFetch();
rootOpts.setPointInTimeType(PointInTimeType.FUTURE);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(rootOpts);
shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
// Create account context from retrieved object
accountContext = getOrCreateAccountContext(context, shadow, task, result);
accountContext.setLoadedObject(shadow);
accountContext.setExists(true);
} catch (ObjectNotFoundException e) {
if (refVal.getObject() == null) {
// ref -> this is really an error
throw e;
} else {
// New account (with OID)
result.muteLastSubresultError();
shadow = refVal.getObject();
if (!shadow.hasCompleteDefinition()) {
provisioningService.applyDefinition(shadow, task, result);
}
// Create account context from embedded object
accountContext = createProjectionContext(context, shadow, task, result);
ObjectDelta<ShadowType> accountPrimaryDelta = shadow.createAddDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
accountContext.setFullShadow(true);
accountContext.setExists(false);
isCombinedAdd = true;
}
}
}
if (context.isDoReconciliationForAllProjections() && !isCombinedAdd) {
accountContext.setDoReconciliation(true);
}
accountContext.setFresh(true);
}
}
if (linkRefDelta.getValuesToDelete() != null) {
for (PrismReferenceValue refVal : linkRefDelta.getValuesToDelete()) {
String oid = refVal.getOid();
LensProjectionContext accountContext = null;
PrismObject<ShadowType> account = null;
if (oid == null) {
throw new SchemaException("Cannot delete account ref without an oid in " + focus);
} else {
try {
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch());
account = provisioningService.getObject(ShadowType.class, oid, options, task, result);
// Create account context from retrieved object
accountContext = getOrCreateAccountContext(context, account, task, result);
accountContext.setLoadedObject(account);
accountContext.setExists(true);
} catch (ObjectNotFoundException e) {
try {
// Broken accountRef. We need to try again with raw options, because the error should be thrown because of non-existent resource
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createRaw());
account = provisioningService.getObject(ShadowType.class, oid, options, task, result);
accountContext = getOrCreateEmptyThombstoneProjectionContext(context, oid);
accountContext.setFresh(true);
accountContext.setExists(false);
OperationResult getObjectSubresult = result.getLastSubresult();
getObjectSubresult.setErrorsHandled();
} catch (ObjectNotFoundException ex) {
// This is still OK. It means deleting an accountRef
// that points to non-existing object
// just log a warning
LOGGER.warn("Deleting accountRef of " + focus + " that points to non-existing OID " + oid);
}
}
}
if (accountContext != null) {
if (refVal.getObject() == null) {
accountContext.setSynchronizationIntent(SynchronizationIntent.UNLINK);
} else {
accountContext.setSynchronizationIntent(SynchronizationIntent.DELETE);
ObjectDelta<ShadowType> accountPrimaryDelta = account.createDeleteDelta();
accountContext.setPrimaryDelta(accountPrimaryDelta);
}
accountContext.setFresh(true);
}
}
}
if (focusPrimaryDelta.getChangeType() == ChangeType.ADD) {
focusPrimaryDelta.getObjectToAdd().removeReference(FocusType.F_LINK_REF);
} else if (focusPrimaryDelta.getChangeType() == ChangeType.MODIFY) {
focusPrimaryDelta.removeReferenceModification(FocusType.F_LINK_REF);
}
}
use of com.evolveum.midpoint.model.impl.lens.LensProjectionContext in project midpoint by Evolveum.
the class ContextLoader method loadProjectionContextsSync.
private <F extends ObjectType> void loadProjectionContextsSync(LensContext<F> context, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
for (LensProjectionContext projCtx : context.getProjectionContexts()) {
if (projCtx.isFresh() && projCtx.getObjectCurrent() != null) {
// already loaded
continue;
}
ObjectDelta<ShadowType> syncDelta = projCtx.getSyncDelta();
if (syncDelta != null) {
if (projCtx.isDoReconciliation()) {
// Do not load old account now. It will get loaded later in the
// reconciliation step. Just mark it as fresh.
projCtx.setFresh(true);
continue;
}
String oid = syncDelta.getOid();
PrismObject<ShadowType> shadow = null;
if (syncDelta.getChangeType() == ChangeType.ADD) {
shadow = syncDelta.getObjectToAdd().clone();
projCtx.setLoadedObject(shadow);
projCtx.setExists(true);
} else {
if (oid == null) {
throw new IllegalArgumentException("No OID in sync delta in " + projCtx);
}
// Using NO_FETCH so we avoid reading in a full account. This is more efficient as we don't need full account here.
// We need to fetch from provisioning and not repository so the correct definition will be set.
GetOperationOptions option = GetOperationOptions.createNoFetch();
option.setDoNotDiscovery(true);
option.setPointInTimeType(PointInTimeType.FUTURE);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(option);
try {
shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
} catch (ObjectNotFoundException e) {
LOGGER.trace("Loading shadow {} from sync delta failed: not found", oid);
projCtx.setExists(false);
projCtx.setObjectCurrent(null);
}
// shadow)
if (syncDelta.getChangeType() == ChangeType.DELETE) {
projCtx.setExists(false);
projCtx.getResourceShadowDiscriminator().setThombstone(true);
} else if (shadow != null) {
syncDelta.applyTo(shadow);
projCtx.setLoadedObject(shadow);
projCtx.setExists(true);
}
}
// Make sure OID is set correctly
projCtx.setOid(oid);
// Make sure that resource is also resolved
if (projCtx.getResource() == null && shadow != null) {
String resourceOid = ShadowUtil.getResourceOid(shadow.asObjectable());
if (resourceOid == null) {
throw new IllegalArgumentException("No resource OID in " + shadow);
}
ResourceType resourceType = LensUtil.getResourceReadOnly(context, resourceOid, provisioningService, task, result);
projCtx.setResource(resourceType);
}
projCtx.setFresh(true);
}
}
}
use of com.evolveum.midpoint.model.impl.lens.LensProjectionContext in project midpoint by Evolveum.
the class ContextLoader method removeRottenContexts.
/**
* Removes projection contexts that are not fresh.
* These are usually artifacts left after the context reload. E.g. an account that used to be linked to a user before
* but was removed in the meantime.
*/
private <F extends ObjectType> void removeRottenContexts(LensContext<F> context) {
Iterator<LensProjectionContext> projectionIterator = context.getProjectionContextsIterator();
while (projectionIterator.hasNext()) {
LensProjectionContext projectionContext = projectionIterator.next();
if (projectionContext.getPrimaryDelta() != null && !projectionContext.getPrimaryDelta().isEmpty()) {
// Vox populi vox dei
continue;
}
if (projectionContext.getWave() >= context.getExecutionWave()) {
// chance to be executed yet
continue;
}
ResourceShadowDiscriminator discr = projectionContext.getResourceShadowDiscriminator();
if (discr != null && discr.getOrder() > 0) {
// HACK never rot higher-order context. TODO: check if lower-order context is rotten, the also rot this one
continue;
}
if (!projectionContext.isFresh()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Removing rotten context {}", projectionContext.getHumanReadableName());
}
if (projectionContext.isToBeArchived()) {
context.getHistoricResourceObjects().add(projectionContext.getResourceShadowDiscriminator());
}
List<LensObjectDeltaOperation<ShadowType>> executedDeltas = projectionContext.getExecutedDeltas();
context.getRottenExecutedDeltas().addAll(executedDeltas);
projectionIterator.remove();
}
}
}
use of com.evolveum.midpoint.model.impl.lens.LensProjectionContext in project midpoint by Evolveum.
the class ContextLoader method load.
public <F extends ObjectType> void load(LensContext<F> context, String activityDescription, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
context.checkAbortRequested();
context.recompute();
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
preprocessProjectionContext(context, projectionContext, task, result);
}
if (consistencyChecks)
context.checkConsistence();
determineFocusContext((LensContext<? extends FocusType>) context, result);
LensFocusContext<F> focusContext = context.getFocusContext();
if (focusContext != null) {
loadObjectCurrent(context, result);
context.recomputeFocus();
loadFromSystemConfig(context, result);
if (FocusType.class.isAssignableFrom(context.getFocusClass())) {
// this also removes the accountRef deltas
loadLinkRefs((LensContext<? extends FocusType>) context, task, result);
LOGGER.trace("loadLinkRefs done");
}
// Some cleanup
if (focusContext.getPrimaryDelta() != null && focusContext.getPrimaryDelta().isModify() && focusContext.getPrimaryDelta().isEmpty()) {
focusContext.setPrimaryDelta(null);
}
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
if (projectionContext.getSynchronizationIntent() != null) {
// Accounts with explicitly set intent are never rotten. These are explicitly requested actions
// if they fail then they really should fail.
projectionContext.setFresh(true);
}
}
setPrimaryDeltaOldValue(focusContext);
} else {
// Projection contexts are not rotten in this case. There is no focus so there is no way to refresh them.
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
projectionContext.setFresh(true);
}
}
removeRottenContexts(context);
if (consistencyChecks)
context.checkConsistence();
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
context.checkAbortRequested();
finishLoadOfProjectionContext(context, projectionContext, task, result);
}
if (consistencyChecks)
context.checkConsistence();
context.recompute();
if (consistencyChecks) {
fullCheckConsistence(context);
}
LensUtil.traceContext(LOGGER, activityDescription, "after load", false, context, false);
}
use of com.evolveum.midpoint.model.impl.lens.LensProjectionContext in project midpoint by Evolveum.
the class DependencyProcessor method findReverseDependecies.
private <F extends ObjectType> Collection<DependencyAndSource> findReverseDependecies(LensContext<F> context, LensProjectionContext targetProjectionContext) throws PolicyViolationException {
Collection<DependencyAndSource> deps = new ArrayList<>();
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
for (ResourceObjectTypeDependencyType dependency : projectionContext.getDependencies()) {
if (LensUtil.isDependencyTargetContext(projectionContext, targetProjectionContext, dependency)) {
DependencyAndSource ds = new DependencyAndSource();
ds.dependency = dependency;
ds.sourceProjectionContext = projectionContext;
deps.add(ds);
}
}
}
return deps;
}
Aggregations