Search in sources :

Example 1 with SynchronizationPolicyDecision

use of com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision in project midpoint by Evolveum.

the class ActivationProcessor method processActivationUserFuture.

public <F extends FocusType> void processActivationUserFuture(LensContext<F> context, LensProjectionContext accCtx, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
    String accCtxDesc = accCtx.toHumanReadableString();
    SynchronizationPolicyDecision decision = accCtx.getSynchronizationPolicyDecision();
    SynchronizationIntent synchronizationIntent = accCtx.getSynchronizationIntent();
    if (accCtx.isThombstone() || decision == SynchronizationPolicyDecision.BROKEN || decision == SynchronizationPolicyDecision.IGNORE || decision == SynchronizationPolicyDecision.UNLINK || decision == SynchronizationPolicyDecision.DELETE) {
        return;
    }
    accCtx.recompute();
    evaluateExistenceMapping(context, accCtx, now, false, task, result);
    PrismObject<F> focusNew = context.getFocusContext().getObjectNew();
    if (focusNew == null) {
        // This must be a user delete or something similar. No point in proceeding
        LOGGER.trace("focusNew is null, skipping activation processing of {}", accCtxDesc);
        return;
    }
    ResourceObjectTypeDefinitionType resourceAccountDefType = accCtx.getResourceObjectTypeDefinitionType();
    if (resourceAccountDefType == null) {
        return;
    }
    ResourceActivationDefinitionType activationType = resourceAccountDefType.getActivation();
    if (activationType == null) {
        return;
    }
    ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(accCtx.getResource(), ActivationCapabilityType.class);
    if (capActivation == null) {
        return;
    }
    ActivationStatusCapabilityType capStatus = CapabilityUtil.getEffectiveActivationStatus(capActivation);
    ActivationValidityCapabilityType capValidFrom = CapabilityUtil.getEffectiveActivationValidFrom(capActivation);
    ActivationValidityCapabilityType capValidTo = CapabilityUtil.getEffectiveActivationValidTo(capActivation);
    if (capStatus != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, capActivation, now, false, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result);
    }
    if (capValidFrom != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, null, now, false, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
    }
    if (capValidTo != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, null, now, false, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
    }
}
Also used : ResourceActivationDefinitionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceActivationDefinitionType) ResourceObjectTypeDefinitionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDefinitionType) ActivationValidityCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationValidityCapabilityType) SynchronizationIntent(com.evolveum.midpoint.model.impl.lens.SynchronizationIntent) ActivationCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) ActivationStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType)

Example 2 with SynchronizationPolicyDecision

use of com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision in project midpoint by Evolveum.

the class ActivationProcessor method processActivationUserCurrent.

public <F extends FocusType> void processActivationUserCurrent(LensContext<F> context, LensProjectionContext projCtx, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
    String projCtxDesc = projCtx.toHumanReadableString();
    SynchronizationPolicyDecision decision = projCtx.getSynchronizationPolicyDecision();
    SynchronizationIntent synchronizationIntent = projCtx.getSynchronizationIntent();
    if (decision == SynchronizationPolicyDecision.BROKEN) {
        LOGGER.trace("Broken projection {}, skipping further activation processing", projCtxDesc);
        return;
    }
    if (decision != null) {
        throw new IllegalStateException("Decision " + decision + " already present for projection " + projCtxDesc);
    }
    if (synchronizationIntent == SynchronizationIntent.UNLINK) {
        projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.UNLINK);
        LOGGER.trace("Evaluated decision for {} to {} because of unlink synchronization intent, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.UNLINK);
        return;
    }
    if (projCtx.isThombstone()) {
        if (shouldKeepThombstone(projCtx)) {
            // Let's keep thombstones linked until they expire. So we do not have shadows without owners.
            // This is also needed for async delete operations.
            projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
            LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.KEEP);
        } else {
            projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.UNLINK);
            LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.UNLINK);
        }
        return;
    }
    if (synchronizationIntent == SynchronizationIntent.DELETE || projCtx.isDelete()) {
        // TODO: is this OK?
        projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.DELETE);
        LOGGER.trace("Evaluated decision for {} to {}, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.DELETE);
        return;
    }
    boolean shadowShouldExist = evaluateExistenceMapping(context, projCtx, now, true, task, result);
    LOGGER.trace("Evaluated intended existence of projection {} to {}", projCtxDesc, shadowShouldExist);
    // Let's reconcile the existence intent (shadowShouldExist) and the synchronization intent in the context
    LensProjectionContext lowerOrderContext = LensUtil.findLowerOrderContext(context, projCtx);
    if (synchronizationIntent == null || synchronizationIntent == SynchronizationIntent.SYNCHRONIZE) {
        if (shadowShouldExist) {
            projCtx.setActive(true);
            if (projCtx.isExists()) {
                if (lowerOrderContext != null && lowerOrderContext.isDelete()) {
                    // HACK HACK HACK
                    decision = SynchronizationPolicyDecision.DELETE;
                } else {
                    decision = SynchronizationPolicyDecision.KEEP;
                }
            } else {
                if (lowerOrderContext != null) {
                    if (lowerOrderContext.isDelete()) {
                        // HACK HACK HACK
                        decision = SynchronizationPolicyDecision.DELETE;
                    } else {
                        // If there is a lower-order context then that one will be ADD
                        // and this one is KEEP. When the execution comes to this context
                        // then the projection already exists
                        decision = SynchronizationPolicyDecision.KEEP;
                    }
                } else {
                    decision = SynchronizationPolicyDecision.ADD;
                }
            }
        } else {
            // Delete
            if (projCtx.isExists()) {
                decision = SynchronizationPolicyDecision.DELETE;
            } else {
                // we should delete the entire context, but then we will lost track of what
                // happened. So just ignore it.
                decision = SynchronizationPolicyDecision.IGNORE;
                // if there are any triggers then move them to focus. We may still need them.
                LensUtil.moveTriggers(projCtx, context.getFocusContext());
            }
        }
    } else if (synchronizationIntent == SynchronizationIntent.ADD) {
        if (shadowShouldExist) {
            projCtx.setActive(true);
            if (projCtx.isExists()) {
                // Attempt to add something that is already there, but should be OK
                decision = SynchronizationPolicyDecision.KEEP;
            } else {
                decision = SynchronizationPolicyDecision.ADD;
            }
        } else {
            throw new PolicyViolationException("Request to add projection " + projCtxDesc + " but the activation policy decided that it should not exist");
        }
    } else if (synchronizationIntent == SynchronizationIntent.KEEP) {
        if (shadowShouldExist) {
            projCtx.setActive(true);
            if (projCtx.isExists()) {
                decision = SynchronizationPolicyDecision.KEEP;
            } else {
                decision = SynchronizationPolicyDecision.ADD;
            }
        } else {
            throw new PolicyViolationException("Request to keep projection " + projCtxDesc + " but the activation policy decided that it should not exist");
        }
    } else {
        throw new IllegalStateException("Unknown sync intent " + synchronizationIntent);
    }
    LOGGER.trace("Evaluated decision for projection {} to {}", projCtxDesc, decision);
    projCtx.setSynchronizationPolicyDecision(decision);
    PrismObject<F> focusNew = context.getFocusContext().getObjectNew();
    if (focusNew == null) {
        // This must be a user delete or something similar. No point in proceeding
        LOGGER.trace("focusNew is null, skipping activation processing of {}", projCtxDesc);
        return;
    }
    if (decision == SynchronizationPolicyDecision.UNLINK || decision == SynchronizationPolicyDecision.DELETE) {
        LOGGER.trace("Decision is {}, skipping activation properties processing for {}", decision, projCtxDesc);
        return;
    }
    ResourceObjectTypeDefinitionType resourceAccountDefType = projCtx.getResourceObjectTypeDefinitionType();
    if (resourceAccountDefType == null) {
        LOGGER.trace("No refined object definition, therefore also no activation outbound definition, skipping activation processing for account " + projCtxDesc);
        return;
    }
    ResourceActivationDefinitionType activationType = resourceAccountDefType.getActivation();
    if (activationType == null) {
        LOGGER.trace("No activation definition in projection {}, skipping activation properties processing", projCtxDesc);
        return;
    }
    ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(projCtx.getResource(), ActivationCapabilityType.class);
    if (capActivation == null) {
        LOGGER.trace("Skipping activation status and validity processing because {} has no activation capability", projCtx.getResource());
        return;
    }
    ActivationStatusCapabilityType capStatus = CapabilityUtil.getEffectiveActivationStatus(capActivation);
    ActivationValidityCapabilityType capValidFrom = CapabilityUtil.getEffectiveActivationValidFrom(capActivation);
    ActivationValidityCapabilityType capValidTo = CapabilityUtil.getEffectiveActivationValidTo(capActivation);
    ActivationLockoutStatusCapabilityType capLockoutStatus = CapabilityUtil.getEffectiveActivationLockoutStatus(capActivation);
    if (capStatus != null) {
        evaluateActivationMapping(context, projCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, capActivation, now, true, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result);
    } else {
        LOGGER.trace("Skipping activation administrative status processing because {} does not have activation administrative status capability", projCtx.getResource());
    }
    ResourceBidirectionalMappingType validFromMappingType = activationType.getValidFrom();
    if (validFromMappingType == null || validFromMappingType.getOutbound() == null) {
        LOGGER.trace("Skipping activation validFrom processing because {} does not have appropriate outbound mapping", projCtx.getResource());
    } else if (capValidFrom == null && !ExpressionUtil.hasExplicitTarget(validFromMappingType.getOutbound())) {
        LOGGER.trace("Skipping activation validFrom processing because {} does not have activation validFrom capability nor outbound mapping with explicit target", projCtx.getResource());
    } else {
        evaluateActivationMapping(context, projCtx, activationType.getValidFrom(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, null, now, true, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
    }
    ResourceBidirectionalMappingType validToMappingType = activationType.getValidTo();
    if (validToMappingType == null || validToMappingType.getOutbound() == null) {
        LOGGER.trace("Skipping activation validTo processing because {} does not have appropriate outbound mapping", projCtx.getResource());
    } else if (capValidTo == null && !ExpressionUtil.hasExplicitTarget(validToMappingType.getOutbound())) {
        LOGGER.trace("Skipping activation validTo processing because {} does not have activation validTo capability nor outbound mapping with explicit target", projCtx.getResource());
    } else {
        evaluateActivationMapping(context, projCtx, activationType.getValidTo(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, null, now, true, ActivationType.F_VALID_TO.getLocalPart(), task, result);
    }
    if (capLockoutStatus != null) {
        evaluateActivationMapping(context, projCtx, activationType.getLockoutStatus(), SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, capActivation, now, true, ActivationType.F_LOCKOUT_STATUS.getLocalPart(), task, result);
    } else {
        LOGGER.trace("Skipping activation lockout status processing because {} does not have activation lockout status capability", projCtx.getResource());
    }
}
Also used : ActivationLockoutStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationLockoutStatusCapabilityType) ActivationCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) ResourceActivationDefinitionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceActivationDefinitionType) ResourceObjectTypeDefinitionType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDefinitionType) ActivationValidityCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationValidityCapabilityType) SynchronizationIntent(com.evolveum.midpoint.model.impl.lens.SynchronizationIntent) ResourceBidirectionalMappingType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceBidirectionalMappingType) PolicyViolationException(com.evolveum.midpoint.util.exception.PolicyViolationException) ActivationStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType)

Example 3 with SynchronizationPolicyDecision

use of com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision in project midpoint by Evolveum.

the class ProjectionValuesProcessor method processProjections.

private <F extends FocusType> void processProjections(LensContext<F> context, LensProjectionContext projContext, String activityDescription, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException {
    checkSchemaAndPolicies(context, projContext, activityDescription, result);
    SynchronizationPolicyDecision policyDecision = projContext.getSynchronizationPolicyDecision();
    if (policyDecision != null && policyDecision == SynchronizationPolicyDecision.UNLINK) {
        // we cannot skip deleted accounts here as the delete delta will be skipped as well
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Skipping processing of value for {} because the decision is {}", projContext.getHumanReadableName(), policyDecision);
        }
        return;
    }
    if (consistencyChecks)
        context.checkConsistence();
    if (!projContext.hasFullShadow() && hasIterationExpression(projContext)) {
        contextLoader.loadFullShadow(context, projContext, "iteration expression", task, result);
        if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
            return;
        }
    }
    int maxIterations = determineMaxIterations(projContext);
    int iteration = 0;
    String iterationToken = null;
    boolean wasResetIterationCounter = false;
    PrismObject<ShadowType> shadowCurrent = projContext.getObjectCurrent();
    if (shadowCurrent != null) {
        Integer shadowIteration = shadowCurrent.asObjectable().getIteration();
        if (shadowIteration != null) {
            iteration = shadowIteration;
        }
        iterationToken = shadowCurrent.asObjectable().getIterationToken();
    }
    boolean skipUniquenessCheck = false;
    while (true) {
        projContext.setIteration(iteration);
        if (iterationToken == null) {
            iterationToken = formatIterationToken(context, projContext, iteration, task, result);
        }
        projContext.setIterationToken(iterationToken);
        String conflictMessage;
        // These are normally null. But there may be leftover from the previous iteration.
        // While that should not affect the algorithm (it should overwrite it) it may confuse
        // people during debugging and unecessarily clutter the debug output.
        projContext.setOutboundConstruction(null);
        projContext.setSqueezedAttributes(null);
        projContext.setSqueezedAssociations(null);
        LOGGER.trace("Projection values iteration {}, token '{}' for {}", iteration, iterationToken, projContext.getHumanReadableName());
        if (!evaluateIterationCondition(context, projContext, iteration, iterationToken, true, task, result)) {
            conflictMessage = "pre-iteration condition was false";
            LOGGER.debug("Skipping iteration {}, token '{}' for {} because the pre-iteration condition was false", iteration, iterationToken, projContext.getHumanReadableName());
        } else {
            if (consistencyChecks)
                context.checkConsistence();
            // Re-evaluates the values in the account constructions (including roles)
            assignmentProcessor.processAssignmentsAccountValues(projContext, result);
            context.recompute();
            if (consistencyChecks)
                context.checkConsistence();
            //				LensUtil.traceContext(LOGGER, activityDescription, "values (assignment account values)", false, context, true);
            // Evaluates the values in outbound mappings
            outboundProcessor.processOutbound(context, projContext, task, result);
            context.recompute();
            if (consistencyChecks)
                context.checkConsistence();
            //				LensUtil.traceContext(LOGGER, activityDescription, "values (outbound)", false, context, true);
            // Merges the values together, processing exclusions and strong/weak mappings are needed
            consolidationProcessor.consolidateValues(context, projContext, task, result);
            if (consistencyChecks)
                context.checkConsistence();
            context.recompute();
            if (consistencyChecks)
                context.checkConsistence();
            // Aux object classes may have changed during consolidation. Make sure we have up-to-date definitions.
            context.refreshAuxiliaryObjectClassDefinitions();
            // but I don't see any easier way to do it now.
            if (iteration != 0 && !wasResetIterationCounter && willResetIterationCounter(projContext)) {
                wasResetIterationCounter = true;
                iteration = 0;
                iterationToken = null;
                cleanupContext(projContext);
                LOGGER.trace("Resetting iteration counter and token because we have rename");
                if (consistencyChecks)
                    context.checkConsistence();
                continue;
            }
            if (policyDecision != null && policyDecision == SynchronizationPolicyDecision.DELETE) {
                // No need to play the iterative game if the account is deleted
                break;
            }
            // Check constraints
            boolean conflict = true;
            ShadowConstraintsChecker<F> checker = new ShadowConstraintsChecker<F>(projContext);
            if (skipUniquenessCheck) {
                skipUniquenessCheck = false;
                conflict = false;
            } else {
                checker.setPrismContext(prismContext);
                checker.setContext(context);
                checker.setProvisioningService(provisioningService);
                checker.check(task, result);
                if (checker.isSatisfiesConstraints()) {
                    LOGGER.trace("Current shadow satisfies uniqueness constraints. Iteration {}, token '{}'", iteration, iterationToken);
                    conflict = false;
                } else {
                    LOGGER.trace("Current shadow does not satisfy constraints. Conflicting shadow exists. Needed to found out what's wrong.");
                    if (checker.getConflictingShadow() != null) {
                        PrismObject<ShadowType> fullConflictingShadow = null;
                        try {
                            Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE));
                            fullConflictingShadow = provisioningService.getObject(ShadowType.class, checker.getConflictingShadow().getOid(), options, task, result);
                        } catch (ObjectNotFoundException ex) {
                            //if object not found exception occurred, its ok..the account was deleted by the discovery, so there esits no more conflicting shadow
                            LOGGER.trace("Conflicting shadow was deleted by discovery. It does not exist anymore. Continue with adding current shadow.");
                            conflict = false;
                        }
                        result.computeStatus();
                        // the situation which happend
                        if (result.isError()) {
                            result.muteError();
                        }
                        if (conflict) {
                            PrismObject<F> focus = repositoryService.searchShadowOwner(checker.getConflictingShadow().getOid(), SelectorOptions.createCollection(GetOperationOptions.createAllowNotFound()), result);
                            //the owner of the shadow exist and it is a current user..so the shadow was successfully created, linked etc..no other recompute is needed..
                            if (focus != null && focus.getOid().equals(context.getFocusContext().getOid())) {
                                LOGGER.trace("Conflicting projection already linked to the current focus, no recompute needed, continue processing with conflicting projection.");
                                //	        			accountContext.setSecondaryDelta(null);
                                cleanupContext(projContext);
                                projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
                                projContext.setObjectOld(fullConflictingShadow.clone());
                                projContext.setObjectCurrent(fullConflictingShadow);
                                projContext.setFullShadow(true);
                                ObjectDelta<ShadowType> secondaryDelta = projContext.getSecondaryDelta();
                                if (secondaryDelta != null && projContext.getOid() != null) {
                                    secondaryDelta.setOid(projContext.getOid());
                                }
                                //				        			result.computeStatus();
                                //									// if the result is fatal error, it may mean that the
                                //									// already exists expection occures before..but in this
                                //									// scenario it means, the exception was handled and we
                                //									// can mute the result to give better understanding of
                                //									// the situation which happend
                                //				        			if (result.isError()){
                                //				        				result.muteError();
                                //				        			}
                                // Re-do this same iteration again (do not increase iteration count).
                                // It will recompute the values and therefore enforce the user deltas and enable reconciliation
                                // to avoid endless loop
                                skipUniquenessCheck = true;
                                continue;
                            }
                            if (focus == null) {
                                LOGGER.trace("There is no owner linked with the conflicting projection.");
                                ResourceType resourceType = projContext.getResource();
                                if (ResourceTypeUtil.isSynchronizationOpportunistic(resourceType)) {
                                    LOGGER.trace("Trying to find owner using correlation expression.");
                                    boolean match = synchronizationService.matchUserCorrelationRule(fullConflictingShadow, context.getFocusContext().getObjectNew(), resourceType, context.getSystemConfiguration(), task, result);
                                    if (match) {
                                        if (projContext.getPrimaryDelta() != null && projContext.getPrimaryDelta().isAdd()) {
                                            PrismObject<ShadowType> shadow = projContext.getPrimaryDelta().getObjectToAdd();
                                            LOGGER.trace("Found primary ADD delta of shadow {}.", shadow);
                                            LensProjectionContext conflictingAccountContext = context.findProjectionContext(projContext.getResourceShadowDiscriminator(), fullConflictingShadow.getOid());
                                            if (conflictingAccountContext == null) {
                                                conflictingAccountContext = LensUtil.createAccountContext(context, projContext.getResourceShadowDiscriminator());
                                                //													conflictingAccountContext = context.createProjectionContext(accountContext.getResourceShadowDiscriminator());
                                                conflictingAccountContext.setOid(fullConflictingShadow.getOid());
                                                conflictingAccountContext.setObjectOld(fullConflictingShadow.clone());
                                                conflictingAccountContext.setObjectCurrent(fullConflictingShadow);
                                                conflictingAccountContext.setFullShadow(true);
                                                conflictingAccountContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
                                                conflictingAccountContext.setResource(projContext.getResource());
                                                conflictingAccountContext.setDoReconciliation(true);
                                                conflictingAccountContext.getDependencies().clear();
                                                conflictingAccountContext.getDependencies().addAll(projContext.getDependencies());
                                                conflictingAccountContext.setWave(projContext.getWave());
                                                context.addConflictingProjectionContext(conflictingAccountContext);
                                            }
                                            projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
                                            result.recordFatalError("Could not add account " + projContext.getObjectNew() + ", because the account with the same identifier already exists on the resource. ");
                                            LOGGER.error("Could not add account {}, because the account with the same identifier already exists on the resource. ", projContext.getObjectNew());
                                            // to avoid endless loop
                                            skipUniquenessCheck = true;
                                            continue;
                                        }
                                        //found shadow belongs to the current user..need to link it and replace current shadow with the found shadow..
                                        cleanupContext(projContext);
                                        projContext.setObjectOld(fullConflictingShadow.clone());
                                        projContext.setObjectCurrent(fullConflictingShadow);
                                        projContext.setFullShadow(true);
                                        projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
                                        ObjectDelta<ShadowType> secondaryDelta = projContext.getSecondaryDelta();
                                        if (secondaryDelta != null && projContext.getOid() != null) {
                                            secondaryDelta.setOid(projContext.getOid());
                                        }
                                        LOGGER.trace("User {} satisfies correlation rules.", context.getFocusContext().getObjectNew());
                                        // Re-do this same iteration again (do not increase iteration count).
                                        // It will recompute the values and therefore enforce the user deltas and enable reconciliation
                                        // to avoid endless loop
                                        skipUniquenessCheck = true;
                                        continue;
                                    } else {
                                        LOGGER.trace("User {} does not satisfy correlation rules.", context.getFocusContext().getObjectNew());
                                    }
                                }
                            } else {
                                LOGGER.trace("Recomputing shadow identifier, because shadow with the some identifier exists and it belongs to other user.");
                            }
                        }
                    }
                }
            }
            if (!conflict) {
                if (evaluateIterationCondition(context, projContext, iteration, iterationToken, false, task, result)) {
                    // stop the iterations
                    break;
                } else {
                    conflictMessage = "post-iteration condition was false";
                    LOGGER.debug("Skipping iteration {}, token '{}' for {} because the post-iteration condition was false", new Object[] { iteration, iterationToken, projContext.getHumanReadableName() });
                }
            } else {
                conflictMessage = checker.getMessages();
            }
        }
        iteration++;
        iterationToken = null;
        LensUtil.checkMaxIterations(iteration, maxIterations, conflictMessage, projContext.getHumanReadableName());
        cleanupContext(projContext);
        if (consistencyChecks)
            context.checkConsistence();
    }
    addIterationTokenDeltas(projContext);
    result.cleanupResult();
    if (consistencyChecks)
        context.checkConsistence();
}
Also used : ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) ResourceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) SelectorOptions(com.evolveum.midpoint.schema.SelectorOptions) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException)

Example 4 with SynchronizationPolicyDecision

use of com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision in project midpoint by Evolveum.

the class ReconciliationProcessor method processReconciliationFocus.

private <F extends ObjectType> void processReconciliationFocus(LensContext<F> context, LensProjectionContext projCtx, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    OperationResult subResult = result.createMinorSubresult(PROCESS_RECONCILIATION);
    try {
        // reconciliation is cheap if the shadow is already fetched therefore just do it
        if (!projCtx.isDoReconciliation() && !projCtx.isFullShadow()) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Skipping reconciliation of {}: no doReconciliation and no full shadow", projCtx.getHumanReadableName());
            }
            return;
        }
        SynchronizationPolicyDecision policyDecision = projCtx.getSynchronizationPolicyDecision();
        if (policyDecision != null && (policyDecision == SynchronizationPolicyDecision.DELETE || policyDecision == SynchronizationPolicyDecision.UNLINK)) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Skipping reconciliation of {}: decision={}", projCtx.getHumanReadableName(), policyDecision);
            }
            return;
        }
        if (projCtx.getObjectCurrent() == null) {
            LOGGER.warn("Can't do reconciliation. Account context doesn't contain current version of account.");
            return;
        }
        if (!projCtx.isFullShadow()) {
            // We need to load the object
            GetOperationOptions rootOps = GetOperationOptions.createDoNotDiscovery();
            rootOps.setPointInTimeType(PointInTimeType.FUTURE);
            PrismObject<ShadowType> objectOld = provisioningService.getObject(ShadowType.class, projCtx.getOid(), SelectorOptions.createCollection(rootOps), task, result);
            ShadowType oldShadow = objectOld.asObjectable();
            projCtx.determineFullShadowFlag(oldShadow.getFetchResult());
            projCtx.setLoadedObject(objectOld);
            projCtx.recompute();
        }
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Starting reconciliation of {}", projCtx.getHumanReadableName());
        }
        reconcileAuxiliaryObjectClasses(projCtx);
        RefinedObjectClassDefinition rOcDef = projCtx.getCompositeObjectClassDefinition();
        Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes = projCtx.getSqueezedAttributes();
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Attribute reconciliation processing {}", projCtx.getHumanReadableName());
        }
        reconcileProjectionAttributes(projCtx, squeezedAttributes, rOcDef);
        Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations = projCtx.getSqueezedAssociations();
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Association reconciliation processing {}", projCtx.getHumanReadableName());
        }
        reconcileProjectionAssociations(projCtx, squeezedAssociations, rOcDef, task, result);
        reconcileMissingAuxiliaryObjectClassAttributes(projCtx);
    } catch (RuntimeException | SchemaException e) {
        subResult.recordFatalError(e);
        throw e;
    } finally {
        subResult.computeStatus();
    }
}
Also used : SchemaException(com.evolveum.midpoint.util.exception.SchemaException) DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) QName(javax.xml.namespace.QName) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) RefinedObjectClassDefinition(com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition) GetOperationOptions(com.evolveum.midpoint.schema.GetOperationOptions)

Example 5 with SynchronizationPolicyDecision

use of com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision in project midpoint by Evolveum.

the class ActivationProcessor method processActivationMappingsFuture.

/**
 * We'll evaluate the mappings just to create the triggers.
 */
private <F extends FocusType> void processActivationMappingsFuture(LensContext<F> context, LensProjectionContext accCtx, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException {
    String accCtxDesc = accCtx.toHumanReadableString();
    SynchronizationPolicyDecision decision = accCtx.getSynchronizationPolicyDecision();
    LOGGER.trace("processActivationUserFuture starting for {}. Existing decision = {}", accCtx, decision);
    if (accCtx.isGone() || decision == SynchronizationPolicyDecision.BROKEN || decision == SynchronizationPolicyDecision.IGNORE || decision == SynchronizationPolicyDecision.UNLINK || decision == SynchronizationPolicyDecision.DELETE) {
        return;
    }
    accCtx.recompute();
    evaluateExistenceMapping(context, accCtx, now, MappingTimeEval.FUTURE, task, result);
    PrismObject<F> focusNew = context.getFocusContext().getObjectNew();
    if (focusNew == null) {
        // This must be a user delete or something similar. No point in proceeding
        LOGGER.trace("focusNew is null, skipping activation processing of {}", accCtxDesc);
        return;
    }
    ResourceObjectTypeDefinitionType resourceAccountDefType = accCtx.getResourceObjectTypeDefinitionType();
    if (resourceAccountDefType == null) {
        return;
    }
    ResourceActivationDefinitionType activationType = resourceAccountDefType.getActivation();
    if (activationType == null) {
        return;
    }
    ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(accCtx.getResource(), ActivationCapabilityType.class);
    if (capActivation == null) {
        return;
    }
    ActivationStatusCapabilityType capStatus = CapabilityUtil.getEnabledActivationStatus(capActivation);
    ActivationValidityCapabilityType capValidFrom = CapabilityUtil.getEnabledActivationValidFrom(capActivation);
    ActivationValidityCapabilityType capValidTo = CapabilityUtil.getEnabledActivationValidTo(capActivation);
    if (capStatus != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, capActivation, now, MappingTimeEval.FUTURE, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result);
    }
    if (capValidFrom != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, null, now, MappingTimeEval.FUTURE, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
    }
    if (capValidTo != null) {
        evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, null, now, MappingTimeEval.FUTURE, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
    }
}
Also used : ActivationValidityCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationValidityCapabilityType) ActivationCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType) SynchronizationPolicyDecision(com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision) ActivationStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType)

Aggregations

SynchronizationPolicyDecision (com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision)14 ActivationCapabilityType (com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType)4 ActivationStatusCapabilityType (com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType)4 ActivationValidityCapabilityType (com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationValidityCapabilityType)4 SynchronizationIntent (com.evolveum.midpoint.model.api.context.SynchronizationIntent)3 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)3 LensProjectionContext (com.evolveum.midpoint.model.impl.lens.LensProjectionContext)2 SynchronizationIntent (com.evolveum.midpoint.model.impl.lens.SynchronizationIntent)2 ResourceActivationDefinitionType (com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceActivationDefinitionType)2 ResourceObjectTypeDefinitionType (com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDefinitionType)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2 ActivationLockoutStatusCapabilityType (com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationLockoutStatusCapabilityType)2 QName (javax.xml.namespace.QName)2 RefinedObjectClassDefinition (com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition)1 ProcessorMethod (com.evolveum.midpoint.model.impl.lens.projector.util.ProcessorMethod)1 DeltaSetTriple (com.evolveum.midpoint.prism.delta.DeltaSetTriple)1 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)1 GetOperationOptions (com.evolveum.midpoint.schema.GetOperationOptions)1 SelectorOptions (com.evolveum.midpoint.schema.SelectorOptions)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1