Search in sources :

Example 6 with HookOperationMode

use of com.evolveum.midpoint.model.api.hooks.HookOperationMode in project midpoint by Evolveum.

the class ClockworkClick method moveStateForward.

private HookOperationMode moveStateForward(OperationResult parentResult, OperationResult result, ModelState state) throws PolicyViolationException, ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, ConflictDetectedException {
    switch(state) {
        case INITIAL:
            processInitialToPrimary(result);
            break;
        case PRIMARY:
            processPrimaryToSecondary();
            break;
        case SECONDARY:
            processSecondary(result, parentResult);
            if (context.getExecutionWave() > context.getMaxWave() + 1) {
                processSecondaryToFinal(context, task, result);
            }
            break;
        case FINAL:
            HookOperationMode mode = processFinal(result, parentResult);
            beans.medic.clockworkFinish(context);
            return mode;
    }
    return beans.clockworkHookHelper.invokeHooks(context, task, result);
}
Also used : HookOperationMode(com.evolveum.midpoint.model.api.hooks.HookOperationMode)

Example 7 with HookOperationMode

use of com.evolveum.midpoint.model.api.hooks.HookOperationMode in project midpoint by Evolveum.

the class ClockworkConflictResolver method resolveFocusConflict.

private <F extends ObjectType> HookOperationMode resolveFocusConflict(LensContext<F> context, Context resolutionContext, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, ConfigurationException, CommunicationException, SecurityViolationException, PolicyViolationException, ObjectAlreadyExistsException {
    ConflictResolutionType resolutionPolicy = resolutionContext.resolutionPolicy;
    if (resolutionPolicy == null || resolutionPolicy.getAction() == ConflictResolutionActionType.NONE) {
        if (resolutionContext.conflictExceptionPresent) {
            throw new SystemException("Conflict exception present but resolution policy is null/NONE");
        }
        return HookOperationMode.FOREGROUND;
    }
    PrismObject<F> focusObject = context.getFocusContext() != null ? context.getFocusContext().getObjectAny() : null;
    ModelExecuteOptions options = new ModelExecuteOptions(prismContext);
    switch(resolutionPolicy.getAction()) {
        case FAIL:
            throw new SystemException("Conflict detected while updating " + focusObject);
        case LOG:
            LOGGER.warn("Conflict detected while updating {}", focusObject);
            return HookOperationMode.FOREGROUND;
        // TODO what to do with this?
        case ERROR:
        // TODO what to do with this?
        case RESTART:
        case RECOMPUTE:
            break;
        case RECONCILE:
            options.reconcile();
            break;
        case NONE:
            throw new AssertionError("Already treated");
        default:
            throw new IllegalStateException("Unsupported conflict resolution action: " + resolutionPolicy.getAction());
    }
    // so, recompute is the action
    LOGGER.debug("CONFLICT: Conflict detected while updating {}, recomputing (options={})", focusObject, options);
    String nonEligibilityReason = getNonEligibilityReason(context);
    if (nonEligibilityReason != null) {
        if (!nonEligibilityReason.isEmpty()) {
            LOGGER.warn("Not eligible for conflict resolution by repetition: {}", nonEligibilityReason);
        }
        return HookOperationMode.FOREGROUND;
    }
    ConflictResolutionType focusConflictResolution = new ConflictResolutionType();
    focusConflictResolution.setAction(ConflictResolutionActionType.ERROR);
    options.focusConflictResolution(focusConflictResolution);
    int preconditionAttempts = 0;
    while (true) {
        int attemptOld = context.getConflictResolutionAttemptNumber();
        int attemptNew = attemptOld + 1;
        boolean shouldExecuteAttempt = shouldExecuteAttempt(resolutionPolicy, attemptNew);
        if (!shouldExecuteAttempt) {
            LOGGER.warn("CONFLICT: Couldn't resolve conflict even after {} resolution attempt(s), giving up.", attemptOld);
            return HookOperationMode.FOREGROUND;
        }
        delay(context, resolutionPolicy, attemptNew + preconditionAttempts);
        Class<F> focusClass = context.getFocusContext().getObjectTypeClass();
        String oid = context.getFocusContext().getOid();
        // Not using read-only here because we are loading the focus (that will be worked with)
        PrismObject<F> focus = repositoryService.getObject(focusClass, oid, null, result);
        LensContext<FocusType> contextNew = contextFactory.createRecomputeContext(focus, options, task, result);
        contextNew.setProgressListeners(new ArrayList<>(emptyIfNull(context.getProgressListeners())));
        contextNew.setConflictResolutionAttemptNumber(attemptNew);
        LOGGER.debug("CONFLICT: Recomputing {} as reaction to conflict (options={}, attempts={},{}, readVersion={})", context.getFocusContext().getHumanReadableName(), options, attemptNew, preconditionAttempts, contextNew.getFocusContext().getObjectReadVersion());
        ClockworkConflictResolver.Context conflictResolutionContext = new ClockworkConflictResolver.Context();
        // this is a recursion; but limited to max attempts which should not be a large number
        HookOperationMode hookOperationMode = clockwork.runWithConflictDetection(contextNew, conflictResolutionContext, task, result);
        if (!conflictResolutionContext.focusConflictPresent) {
            LOGGER.debug("CONFLICT: Clean recompute of {} achieved (options={}, attempts={},{})", context.getFocusContext().getHumanReadableName(), options, attemptNew, preconditionAttempts);
            return hookOperationMode;
        }
        // Actually, we could stop distinguish precondition-based and "normal" retries...
        if (conflictResolutionContext.conflictExceptionPresent) {
            preconditionAttempts++;
            LOGGER.debug("CONFLICT: Recompute precondition failed (attempt {}, precondition attempt {}), trying again", attemptNew, preconditionAttempts);
            if (preconditionAttempts < MAX_PRECONDITION_CONFLICT_RESOLUTION_ATTEMPTS) {
                continue;
            }
            LOGGER.warn("CONFLICT: Couldn't resolve conflict even after {} resolution attempt(s) and {} precondition attempts, giving up.", attemptOld, preconditionAttempts);
            return HookOperationMode.FOREGROUND;
        }
    }
}
Also used : PrismContext(com.evolveum.midpoint.prism.PrismContext) ModelExecuteOptions(com.evolveum.midpoint.model.api.ModelExecuteOptions) HookOperationMode(com.evolveum.midpoint.model.api.hooks.HookOperationMode)

Example 8 with HookOperationMode

use of com.evolveum.midpoint.model.api.hooks.HookOperationMode in project midpoint by Evolveum.

the class ClockworkHookHelper method invokeHooks.

/**
 * Invokes hooks, if there are any.
 *
 * @return - ERROR, if any hook reported error; otherwise returns
 * - BACKGROUND, if any hook reported switching to background; otherwise
 * - FOREGROUND (if all hooks reported finishing on foreground)
 */
HookOperationMode invokeHooks(LensContext<?> context, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
    // TODO: following two parts should be merged together in later versions
    // Execute configured scripting hooks
    PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(result);
    // systemConfiguration may be null in some tests
    if (systemConfiguration != null) {
        ModelHooksType modelHooks = systemConfiguration.asObjectable().getModelHooks();
        if (modelHooks != null) {
            HookListType changeHooks = modelHooks.getChange();
            if (changeHooks != null) {
                for (HookType hookType : changeHooks.getHook()) {
                    String shortDesc;
                    if (hookType.getName() != null) {
                        shortDesc = "hook '" + hookType.getName() + "'";
                    } else {
                        shortDesc = "scripting hook in system configuration";
                    }
                    if (hookType.isEnabled() != null && !hookType.isEnabled()) {
                        // Disabled hook, skip
                        continue;
                    }
                    if (hookType.getState() != null) {
                        if (!context.getState().toModelStateType().equals(hookType.getState())) {
                            continue;
                        }
                    }
                    if (hookType.getFocusType() != null) {
                        if (context.getFocusContext() == null) {
                            continue;
                        }
                        QName hookFocusTypeQname = hookType.getFocusType();
                        ObjectTypes hookFocusType = ObjectTypes.getObjectTypeFromTypeQName(hookFocusTypeQname);
                        if (hookFocusType == null) {
                            throw new SchemaException("Unknown focus type QName " + hookFocusTypeQname + " in " + shortDesc);
                        }
                        Class<?> focusClass = context.getFocusClass();
                        Class<? extends ObjectType> hookFocusClass = hookFocusType.getClassDefinition();
                        if (!hookFocusClass.isAssignableFrom(focusClass)) {
                            continue;
                        }
                    }
                    ScriptExpressionEvaluatorType scriptExpressionEvaluatorType = hookType.getScript();
                    if (scriptExpressionEvaluatorType == null) {
                        continue;
                    }
                    try {
                        evaluateScriptingHook(context, scriptExpressionEvaluatorType, shortDesc, task, result);
                    } catch (ExpressionEvaluationException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new ExpressionEvaluationException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    } catch (ObjectNotFoundException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new ObjectNotFoundException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    } catch (SchemaException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new SchemaException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    } catch (CommunicationException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new CommunicationException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    } catch (ConfigurationException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new ConfigurationException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    } catch (SecurityViolationException e) {
                        LOGGER.error("Evaluation of {} failed: {}", shortDesc, e.getMessage(), e);
                        throw new SecurityViolationException("Evaluation of " + shortDesc + " failed: " + e.getMessage(), e);
                    }
                }
            }
        }
    }
    // Execute registered Java hooks
    HookOperationMode resultMode = HookOperationMode.FOREGROUND;
    if (hookRegistry != null) {
        for (ChangeHook hook : hookRegistry.getAllChangeHooks()) {
            HookOperationMode mode = hook.invoke(context, task, result);
            if (mode == HookOperationMode.ERROR) {
                resultMode = HookOperationMode.ERROR;
            } else if (mode == HookOperationMode.BACKGROUND) {
                if (resultMode != HookOperationMode.ERROR) {
                    resultMode = HookOperationMode.BACKGROUND;
                }
            }
        }
    }
    return resultMode;
}
Also used : QName(javax.xml.namespace.QName) ChangeHook(com.evolveum.midpoint.model.api.hooks.ChangeHook) ObjectTypes(com.evolveum.midpoint.schema.constants.ObjectTypes) HookOperationMode(com.evolveum.midpoint.model.api.hooks.HookOperationMode)

Example 9 with HookOperationMode

use of com.evolveum.midpoint.model.api.hooks.HookOperationMode in project midpoint by Evolveum.

the class TestAddAssociation method test100AddJackToGuests.

/**
 * Add entitlement for 'guests' to user jack - should be created without starting wf process
 */
@Test
public void test100AddJackToGuests() throws Exception {
    Task modelTask = getTestTask();
    OperationResult result = createOperationResult();
    modelTask.setOwner(repositoryService.getObject(UserType.class, USER_ADMINISTRATOR_OID, null, result));
    LensContext<UserType> context = createUserLensContext();
    fillContextWithUser(context, USER_JACK_OID, result);
    UserType jack = context.getFocusContext().getObjectCurrent().asObjectable();
    AssertJUnit.assertEquals("Jack has wrong number of accounts", 1, jack.getLinkRef().size());
    jackAccountShadowOid = jack.getLinkRef().get(0).getOid();
    ShadowType accountBefore = getObject(ShadowType.class, jackAccountShadowOid).asObjectable();
    assertEquals("Wrong # of jack's account associations", 1, accountBefore.getAssociation().size());
    assertHasAssociation(accountBefore, new QName("group"), SHADOW_TESTERS_OID);
    LensProjectionContext accountContext = fillContextWithAccount(context, jackAccountShadowOid, modelTask, result);
    ObjectModificationType modElement = PrismTestUtil.parseAtomicValue(REQ_ADD_ENTITLEMENT_GUESTS, ObjectModificationType.COMPLEX_TYPE);
    ObjectDelta shadowDelta = DeltaConvertor.createObjectDelta(modElement, ShadowType.class, prismContext);
    shadowDelta.setOid(jackAccountShadowOid);
    // noinspection unchecked
    accountContext.setPrimaryDelta(shadowDelta);
    HookOperationMode mode = clockwork.run(context, modelTask, result);
    assertEquals("Unexpected state of the context - workflow was started even if it should not", ModelState.FINAL, context.getState());
    assertEquals("Wrong mode after clockwork.run in " + context.getState(), HookOperationMode.FOREGROUND, mode);
    ShadowType accountAfter = getObject(ShadowType.class, jackAccountShadowOid).asObjectable();
    assertEquals("Wrong # of jack's account associations", 2, accountAfter.getAssociation().size());
    assertHasAssociation(accountAfter, new QName("group"), SHADOW_TESTERS_OID);
    assertHasAssociation(accountAfter, new QName("group"), SHADOW_GUESTS_OID);
}
Also used : ObjectModificationType(com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectModificationType) Task(com.evolveum.midpoint.task.api.Task) HookOperationMode(com.evolveum.midpoint.model.api.hooks.HookOperationMode) QName(javax.xml.namespace.QName) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) Test(org.testng.annotations.Test) AbstractWfTest(com.evolveum.midpoint.wf.impl.AbstractWfTest)

Example 10 with HookOperationMode

use of com.evolveum.midpoint.model.api.hooks.HookOperationMode in project midpoint by Evolveum.

the class TestAddAssociation method executeTest.

private void executeTest(String testName, String focusOid, TestDetails testDetails) throws Exception {
    // GIVEN
    prepareNotifications();
    dummyAuditService.clear();
    OperationResult result = new OperationResult("execution");
    Task task = taskManager.createTaskInstance(TestAddAssociation.class.getName() + "." + testName);
    task.setOwner(userAdministrator);
    if (focusOid != null && testDetails.removeAssignmentsBeforeTest()) {
        removeAllAssignments(focusOid, result);
    }
    // noinspection unchecked
    LensContext<UserType> context = (LensContext<UserType>) testDetails.createModelContext(task, result);
    displayDumpable("Input context", context);
    assertFocusModificationSanity(context);
    // WHEN
    HookOperationMode mode = clockwork.run(context, task, result);
    // THEN
    assertEquals("Unexpected state of the context", ModelState.PRIMARY, context.getState());
    assertEquals("Wrong mode after clockwork.run in " + context.getState(), HookOperationMode.BACKGROUND, mode);
    CaseType rootCase = testHelper.getRootCase(result);
    if (!testDetails.approvedAutomatically()) {
        List<CaseType> subcases = miscHelper.getSubcases(rootCase, result);
        assertEquals("Incorrect number of subcases", testDetails.subcasesCount(), subcases.size());
        CaseType case0 = WfTestHelper.findAndRemoveCase0(subcases);
        testDetails.assertsAfterClockworkRun(rootCase, case0, subcases, task, result);
        if (testDetails.immediate()) {
            CaseType rootCaseAfter = testHelper.waitForCaseClose(case0, 20000);
            testDetails.assertsAfterImmediateExecutionFinished(rootCaseAfter, result);
        }
        for (int i = 0; i < subcases.size(); i++) {
            CaseType subcase = subcases.get(i);
            // noinspection unchecked
            PrismProperty<ObjectTreeDeltasType> deltas = subcase.asPrismContainerValue().findProperty(ItemPath.create(F_APPROVAL_CONTEXT, F_DELTAS_TO_APPROVE));
            assertNotNull("There are no modifications in subcase #" + i + ": " + subcase, deltas);
            assertEquals("Incorrect number of modifications in subcase #" + i + ": " + subcase, 1, deltas.getRealValues().size());
            // todo check correctness of the modification?
            // now check the workflow state
            // WfProcessInstanceType processInstance = workflowServiceImpl.getProcessInstanceById(pid, false, true, result);
            // assertNotNull("Process instance information cannot be retrieved", processInstance);
            // assertEquals("Incorrect number of work items", 1, processInstance.getWorkItems().size());
            // String taskId = processInstance.getWorkItems().get(0).getWorkItemId();
            // WorkItemDetailed workItemDetailed = wfDataAccessor.getWorkItemDetailsById(taskId, result);
            List<CaseWorkItemType> workItems = getWorkItemsForCase(subcase.getOid(), null, result);
            CaseWorkItemType workItem = MiscUtil.extractSingleton(workItems);
            assertNotNull("work item not found", workItem);
            ApprovalContextType wfContext = subcase.getApprovalContext();
            logger.trace("wfContext = {}", wfContext);
            boolean approve = testDetails.decideOnApproval(subcase, wfContext);
            caseManager.completeWorkItem(WorkItemId.of(workItem), new AbstractWorkItemOutputType(prismContext).outcome(ApprovalUtils.toUri(approve)), null, task, result);
            login(userAdministrator);
        }
    }
    CaseType rootCaseAfter = testHelper.waitForCaseClose(rootCase, 60000);
    List<CaseType> subcases = miscHelper.getSubcases(rootCaseAfter, result);
    WfTestHelper.findAndRemoveCase0(subcases);
    // TestUtil.assertSuccess(rootCase.getResult());
    testDetails.assertsRootCaseFinishes(rootCaseAfter, subcases, task, result);
    if (focusOid == null) {
        focusOid = testDetails.getObjectOid(rootCaseAfter, result);
    }
    assertNotNull("object oid is null after operation", focusOid);
    if (!focusOid.equals(DONT_CHECK)) {
        assertObjectInTaskTree(rootCaseAfter, focusOid, testDetails.checkObjectOnSubtasks(), result);
    }
    if (!testDetails.approvedAutomatically()) {
    // ZZZ temporarily disabled
    // checkDummyTransportMessages("simpleWorkflowNotifier-Processes", workflowSubtaskCount * 2);
    // checkDummyTransportMessages("simpleWorkflowNotifier-WorkItems", workflowSubtaskCount * 2);
    }
    notificationManager.setDisabled(true);
    // Check audit
    displayDumpable("Audit", dummyAuditService);
    displayDumpable("Output context", context);
}
Also used : Task(com.evolveum.midpoint.task.api.Task) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) LensContext(com.evolveum.midpoint.model.impl.lens.LensContext) HookOperationMode(com.evolveum.midpoint.model.api.hooks.HookOperationMode)

Aggregations

HookOperationMode (com.evolveum.midpoint.model.api.hooks.HookOperationMode)21 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)14 Task (com.evolveum.midpoint.task.api.Task)9 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)4 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)4 QName (javax.xml.namespace.QName)4 ProgressInformation (com.evolveum.midpoint.model.api.ProgressInformation)3 ModelContext (com.evolveum.midpoint.model.api.context.ModelContext)3 LensContext (com.evolveum.midpoint.model.impl.lens.LensContext)3 ExpressionEvaluationException (com.evolveum.midpoint.util.exception.ExpressionEvaluationException)3 ChangeHook (com.evolveum.midpoint.model.api.hooks.ChangeHook)2 LensProjectionContext (com.evolveum.midpoint.model.impl.lens.LensProjectionContext)2 PrismContext (com.evolveum.midpoint.prism.PrismContext)2 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)2 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)2 SelectorOptions (com.evolveum.midpoint.schema.SelectorOptions)2 ObjectTypes (com.evolveum.midpoint.schema.constants.ObjectTypes)2 CommunicationException (com.evolveum.midpoint.util.exception.CommunicationException)2 ConfigurationException (com.evolveum.midpoint.util.exception.ConfigurationException)2 SecurityViolationException (com.evolveum.midpoint.util.exception.SecurityViolationException)2