use of com.evolveum.midpoint.model.api.ProgressInformation in project midpoint by Evolveum.
the class Projector method projectInternal.
private <F extends ObjectType> void projectInternal(LensContext<F> context, String activityDescription, boolean fromStart, boolean allWaves, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
context.checkAbortRequested();
if (context.getDebugListener() != null) {
context.getDebugListener().beforeProjection(context);
}
// Read the time at the beginning so all processors have the same notion of "now"
// this provides nicer unified timestamp that can be used in equality checks in tests and also for
// troubleshooting
XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
String traceTitle = fromStart ? "projector start" : "projector resume";
LensUtil.traceContext(LOGGER, activityDescription, traceTitle, false, context, false);
if (consistencyChecks)
context.checkConsistence();
if (fromStart) {
context.normalize();
context.resetProjectionWave();
}
OperationResult result = parentResult.createSubresult(Projector.class.getName() + ".project");
result.addParam("fromStart", fromStart);
result.addContext("projectionWave", context.getProjectionWave());
result.addContext("executionWave", context.getExecutionWave());
PartialProcessingOptionsType partialProcessingOptions = context.getPartialProcessingOptions();
try {
context.reportProgress(new ProgressInformation(PROJECTOR, ENTERING));
if (fromStart) {
LensUtil.partialExecute("load", () -> {
contextLoader.load(context, activityDescription, task, result);
// Set the "fresh" mark now so following consistency check will be stricter
context.setFresh(true);
if (consistencyChecks)
context.checkConsistence();
}, partialProcessingOptions::getLoad, result);
}
// For now let's pretend to do just one wave. The maxWaves number will be corrected in the
// first wave when dependencies are sorted out for the first time.
int maxWaves = context.getExecutionWave() + 1;
// Start the waves ....
LOGGER.trace("WAVE: Starting the waves.");
boolean firstWave = true;
while ((allWaves && context.getProjectionWave() < maxWaves) || (!allWaves && context.getProjectionWave() <= context.getExecutionWave())) {
boolean inFirstWave = firstWave;
// in order to not forget to reset it ;)
firstWave = false;
context.checkAbortRequested();
LOGGER.trace("WAVE {} (maxWaves={}, executionWave={})", context.getProjectionWave(), maxWaves, context.getExecutionWave());
//just make sure everything is loaded and set as needed
dependencyProcessor.preprocessDependencies(context);
// Process the focus-related aspects of the context. That means inbound, focus activation,
// object template and assignments.
LensUtil.partialExecute("focus", () -> {
focusProcessor.processFocus(context, activityDescription, now, task, result);
context.recomputeFocus();
if (consistencyChecks)
context.checkConsistence();
}, partialProcessingOptions::getFocus, result);
LensUtil.traceContext(LOGGER, activityDescription, "focus processing", false, context, false);
LensUtil.checkContextSanity(context, "focus processing", result);
// a projection is provisioned or deprovisioned only after the activation is processed.
if (fromStart && inFirstWave) {
LOGGER.trace("Processing activation for all contexts");
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
if (projectionContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN || projectionContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.IGNORE) {
continue;
}
activationProcessor.processActivation(context, projectionContext, now, task, result);
projectionContext.recompute();
}
// TODO move implementation of this method elsewhere; but it has to be invoked here, as activationProcessor sets the IGNORE flag
assignmentProcessor.removeIgnoredContexts(context);
}
LensUtil.traceContext(LOGGER, activityDescription, "projection activation of all resources", true, context, true);
if (consistencyChecks)
context.checkConsistence();
dependencyProcessor.sortProjectionsToWaves(context);
maxWaves = dependencyProcessor.computeMaxWaves(context);
LOGGER.trace("Continuing wave {}, maxWaves={}", context.getProjectionWave(), maxWaves);
for (LensProjectionContext projectionContext : context.getProjectionContexts()) {
LensUtil.partialExecute("projection " + projectionContext.getHumanReadableName(), () -> projectProjection(context, projectionContext, partialProcessingOptions, now, activityDescription, task, result), partialProcessingOptions::getProjection);
// TODO: make this condition more complex in the future. We may want the ability
// to select only some projections to process
}
// if there exists some conflicting projection contexts, add them to the context so they will be recomputed in the next wave..
addConflictingContexts(context);
if (consistencyChecks)
context.checkConsistence();
context.incrementProjectionWave();
}
LOGGER.trace("WAVE: Stopping the waves. There was {} waves", context.getProjectionWave());
// We can do this only when computation of all the waves is finished. Before that we do not know
// activation of every account and therefore cannot decide what is OK and what is not
dependencyProcessor.checkDependenciesFinal(context, result);
if (consistencyChecks)
context.checkConsistence();
computeResultStatus(now, result);
} catch (SchemaException | PolicyViolationException | ExpressionEvaluationException | ObjectAlreadyExistsException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException e) {
recordFatalError(e, now, result);
throw e;
} catch (RuntimeException e) {
recordFatalError(e, now, result);
// This should not normally happen unless there is something really bad or there is a bug.
// Make sure that it is logged.
LOGGER.error("Runtime error in projector: {}", e.getMessage(), e);
throw e;
} finally {
if (context.getDebugListener() != null) {
context.getDebugListener().afterProjection(context);
}
context.reportProgress(new ProgressInformation(PROJECTOR, result));
}
}
use of com.evolveum.midpoint.model.api.ProgressInformation in project midpoint by Evolveum.
the class CustomNotifier method processEvent.
@Override
public boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, Task task, OperationResult parentResult) throws SchemaException {
OperationResult result = parentResult.createSubresult(CustomNotifier.class.getName() + ".processEvent");
logStart(getLogger(), event, eventHandlerType);
boolean applies = aggregatedEventHandler.processEvent(event, eventHandlerType, notificationManager, task, result);
if (applies) {
CustomNotifierType config = (CustomNotifierType) eventHandlerType;
ExpressionVariables variables = getDefaultVariables(event, result);
if (event instanceof ModelEvent) {
((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, ENTERING));
}
List<String> transports = new ArrayList<>(config.getTransport());
if (transports.isEmpty()) {
transports.add(customTransport.getName());
}
try {
for (String transportName : config.getTransport()) {
variables.addVariableDefinition(SchemaConstants.C_TRANSPORT_NAME, transportName);
Transport transport = notificationManager.getTransport(transportName);
Message message = getMessageFromExpression(config, variables, task, result);
if (message != null) {
getLogger().trace("Sending notification via transport {}:\n{}", transportName, message);
transport.send(message, transportName, event, task, result);
} else {
getLogger().debug("No message for transport {}, won't send anything", transportName);
}
}
} finally {
if (event instanceof ModelEvent) {
((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, result));
}
}
}
logEnd(getLogger(), event, eventHandlerType, applies);
result.computeStatusIfUnknown();
// not-applicable notifiers do not stop processing of other notifiers
return true;
}
use of com.evolveum.midpoint.model.api.ProgressInformation in project midpoint by Evolveum.
the class GeneralNotifier method processEvent.
@Override
public boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, Task task, OperationResult parentResult) throws SchemaException {
OperationResult result = parentResult.createSubresult(GeneralNotifier.class.getName() + ".processEvent");
logStart(getLogger(), event, eventHandlerType);
boolean applies = aggregatedEventHandler.processEvent(event, eventHandlerType, notificationManager, task, result);
if (applies) {
GeneralNotifierType generalNotifierType = (GeneralNotifierType) eventHandlerType;
if (!quickCheckApplicability(event, generalNotifierType, result)) {
// nothing to do -- an appropriate message has to be logged in quickCheckApplicability method
} else {
if (!checkApplicability(event, generalNotifierType, result)) {
// nothing to do -- an appropriate message has to be logged in checkApplicability method
} else if (generalNotifierType.getTransport().isEmpty()) {
getLogger().warn("No transports for this notifier, exiting without sending any notifications.");
} else {
ExpressionVariables variables = getDefaultVariables(event, result);
if (event instanceof ModelEvent) {
((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, ENTERING));
}
try {
for (String transportName : generalNotifierType.getTransport()) {
variables.addVariableDefinition(SchemaConstants.C_TRANSPORT_NAME, transportName);
Transport transport = notificationManager.getTransport(transportName);
List<String> recipientsAddresses = getRecipientsAddresses(event, generalNotifierType, variables, getDefaultRecipient(event, generalNotifierType, result), transportName, transport, task, result);
if (!recipientsAddresses.isEmpty()) {
String body = getBodyFromExpression(event, generalNotifierType, variables, task, result);
String subject = getSubjectFromExpression(event, generalNotifierType, variables, task, result);
String from = getFromFromExpression(event, generalNotifierType, variables, task, result);
String contentType = getContentTypeFromExpression(event, generalNotifierType, variables, task, result);
if (body == null) {
body = getBody(event, generalNotifierType, transportName, task, result);
}
if (subject == null) {
subject = generalNotifierType.getSubjectPrefix() != null ? generalNotifierType.getSubjectPrefix() : "";
subject += getSubject(event, generalNotifierType, transportName, task, result);
}
Message message = new Message();
message.setBody(body != null ? body : "");
if (contentType != null) {
message.setContentType(contentType);
} else if (generalNotifierType.getContentType() != null) {
message.setContentType(generalNotifierType.getContentType());
}
message.setSubject(subject);
if (from != null) {
message.setFrom(from);
}
message.setTo(recipientsAddresses);
message.setCc(getCcBccAddresses(generalNotifierType.getCcExpression(), variables, "notification cc-expression", task, result));
message.setBcc(getCcBccAddresses(generalNotifierType.getBccExpression(), variables, "notification bcc-expression", task, result));
getLogger().trace("Sending notification via transport {}:\n{}", transportName, message);
transport.send(message, transportName, event, task, result);
} else {
getLogger().info("No recipients addresses for transport " + transportName + ", message corresponding to event " + event.getId() + " will not be send.");
}
}
} finally {
if (event instanceof ModelEvent) {
((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, result));
}
}
}
}
}
logEnd(getLogger(), event, eventHandlerType, applies);
result.computeStatusIfUnknown();
// not-applicable notifiers do not stop processing of other notifiers
return true;
}
use of com.evolveum.midpoint.model.api.ProgressInformation in project midpoint by Evolveum.
the class ChangeExecutor method executeChanges.
// returns true if current operation has to be restarted, see
// ObjectAlreadyExistsException handling (TODO specify more exactly)
public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Task task, OperationResult parentResult) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
OperationResult result = parentResult.createSubresult(OPERATION_EXECUTE);
// FOCUS
context.checkAbortRequested();
LensFocusContext<O> focusContext = context.getFocusContext();
if (focusContext != null) {
ObjectDelta<O> focusDelta = focusContext.getWaveExecutableDelta(context.getExecutionWave());
focusDelta = policyRuleProcessor.applyAssignmentSituation(context, focusDelta);
if (focusDelta != null) {
ObjectPolicyConfigurationType objectPolicyConfigurationType = focusContext.getObjectPolicyConfigurationType();
applyObjectPolicy(focusContext, focusDelta, objectPolicyConfigurationType);
OperationResult subResult = result.createSubresult(OPERATION_EXECUTE_FOCUS + "." + focusContext.getObjectTypeClass().getSimpleName());
try {
// Will remove credential deltas or hash them
focusDelta = credentialsProcessor.transformFocusExectionDelta(context, focusDelta);
} catch (EncryptionException e) {
recordFatalError(subResult, result, null, e);
result.computeStatus();
throw new SystemException(e.getMessage(), e);
}
try {
context.reportProgress(new ProgressInformation(FOCUS_OPERATION, ENTERING));
executeDelta(focusDelta, focusContext, context, null, null, task, subResult);
subResult.computeStatus();
} catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException | RuntimeException e) {
recordFatalError(subResult, result, null, e);
throw e;
} catch (ObjectAlreadyExistsException e) {
subResult.computeStatus();
if (!subResult.isSuccess() && !subResult.isHandledError()) {
subResult.recordFatalError(e);
}
result.computeStatusComposite();
throw e;
} finally {
context.reportProgress(new ProgressInformation(FOCUS_OPERATION, subResult));
}
} else {
LOGGER.trace("Skipping focus change execute, because user delta is null");
}
}
// PROJECTIONS
context.checkAbortRequested();
boolean restartRequested = false;
for (LensProjectionContext projCtx : context.getProjectionContexts()) {
if (projCtx.getWave() != context.getExecutionWave()) {
continue;
}
if (!projCtx.isCanProject()) {
continue;
}
// we should not get here, but just to be sure
if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.IGNORE) {
LOGGER.trace("Skipping ignored projection context {}", projCtx.toHumanReadableString());
continue;
}
OperationResult subResult = result.createSubresult(OPERATION_EXECUTE_PROJECTION + "." + projCtx.getObjectTypeClass().getSimpleName());
subResult.addContext("discriminator", projCtx.getResourceShadowDiscriminator());
if (projCtx.getResource() != null) {
subResult.addParam("resource", projCtx.getResource().getName());
}
try {
context.checkAbortRequested();
context.reportProgress(new ProgressInformation(RESOURCE_OBJECT_OPERATION, projCtx.getResourceShadowDiscriminator(), ENTERING));
executeReconciliationScript(projCtx, context, BeforeAfterType.BEFORE, task, subResult);
ObjectDelta<ShadowType> projDelta = projCtx.getExecutableDelta();
if (shouldBeDeleted(projDelta, projCtx)) {
projDelta = ObjectDelta.createDeleteDelta(projCtx.getObjectTypeClass(), projCtx.getOid(), prismContext);
}
if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
if (context.getFocusContext() != null && context.getFocusContext().getDelta() != null && context.getFocusContext().getDelta().isDelete() && context.getOptions() != null && ModelExecuteOptions.isForce(context.getOptions())) {
if (projDelta == null) {
projDelta = ObjectDelta.createDeleteDelta(projCtx.getObjectTypeClass(), projCtx.getOid(), prismContext);
}
}
if (projDelta != null && projDelta.isDelete()) {
executeDelta(projDelta, projCtx, context, null, projCtx.getResource(), task, subResult);
}
} else {
if (projDelta == null || projDelta.isEmpty()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("No change for " + projCtx.getResourceShadowDiscriminator());
}
if (focusContext != null) {
updateLinks(focusContext, projCtx, task, subResult);
}
// Make sure post-reconcile delta is always executed,
// even if there is no change
executeReconciliationScript(projCtx, context, BeforeAfterType.AFTER, task, subResult);
subResult.computeStatus();
subResult.recordNotApplicableIfUnknown();
continue;
} else if (projDelta.isDelete() && projCtx.getResourceShadowDiscriminator() != null && projCtx.getResourceShadowDiscriminator().getOrder() > 0) {
// HACK ... for higher-order context check if this was
// already deleted
LensProjectionContext lowerOrderContext = LensUtil.findLowerOrderContext(context, projCtx);
if (lowerOrderContext != null && lowerOrderContext.isDelete()) {
// We assume that this was already executed
subResult.setStatus(OperationResultStatus.NOT_APPLICABLE);
continue;
}
}
executeDelta(projDelta, projCtx, context, null, projCtx.getResource(), task, subResult);
}
subResult.computeStatus();
if (focusContext != null) {
updateLinks(focusContext, projCtx, task, subResult);
}
executeReconciliationScript(projCtx, context, BeforeAfterType.AFTER, task, subResult);
subResult.computeStatus();
subResult.recordNotApplicableIfUnknown();
} catch (SchemaException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ObjectNotFoundException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ObjectAlreadyExistsException e) {
if (isRepeatedAlreadyExistsException(projCtx)) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
}
// in his case we do not need to set account context as
// broken, instead we need to restart projector for this
// context to recompute new account or find out if the
// account was already linked..
// and also do not set fatal error to the operation result, this
// is a special case
// if it is fatal, it will be set later
// but we need to set some result
subResult.recordSuccess();
subResult.muteLastSubresultError();
restartRequested = true;
// we will process remaining projections when retrying
break;
// the wave
} catch (CommunicationException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ConfigurationException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (SecurityViolationException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ExpressionEvaluationException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} catch (RuntimeException e) {
recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN);
continue;
} finally {
context.reportProgress(new ProgressInformation(RESOURCE_OBJECT_OPERATION, projCtx.getResourceShadowDiscriminator(), subResult));
}
}
// Result computation here needs to be slightly different
result.computeStatusComposite();
return restartRequested;
}
use of com.evolveum.midpoint.model.api.ProgressInformation in project midpoint by Evolveum.
the class WfHook method processModelInvocation.
private HookOperationMode processModelInvocation(@NotNull ModelContext<? extends ObjectType> modelContext, WfConfigurationType wfConfigurationType, @NotNull Task taskFromModel, @NotNull OperationResult result) {
try {
modelContext.reportProgress(new ProgressInformation(WORKFLOWS, ENTERING));
for (ChangeProcessor changeProcessor : wfConfiguration.getChangeProcessors()) {
LOGGER.trace("Trying change processor: {}", changeProcessor.getClass().getName());
try {
HookOperationMode hookOperationMode = changeProcessor.processModelInvocation(modelContext, wfConfigurationType, taskFromModel, result);
if (hookOperationMode != null) {
return hookOperationMode;
}
} catch (ObjectNotFoundException | SchemaException | RuntimeException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Exception while running change processor {}", e, changeProcessor.getClass().getName());
result.recordFatalError("Exception while running change processor " + changeProcessor.getClass(), e);
return HookOperationMode.ERROR;
}
}
} finally {
if (result.isInProgress()) {
// a bit of hack: IN_PROGRESS for workflows actually means "success"
OperationResult r = result.clone();
r.recordSuccess();
modelContext.reportProgress(new ProgressInformation(WORKFLOWS, r));
} else {
modelContext.reportProgress(new ProgressInformation(WORKFLOWS, result));
}
}
LOGGER.trace("No change processor caught this request, returning the FOREGROUND flag.");
return HookOperationMode.FOREGROUND;
}
Aggregations