in core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java [530:733]
protected TaskExec<PropagationTask> doExecute(
final PropagationTaskInfo taskInfo,
final PropagationReporter reporter,
final String executor) {
Connector connector = taskInfo.getConnector() == null
? connectorManager.getConnector(taskInfo.getResource())
: taskInfo.getConnector();
List<PropagationActions> actions = getPropagationActions(taskInfo.getResource());
OffsetDateTime start = OffsetDateTime.now();
TaskExec<PropagationTask> exec = taskUtilsFactory.getInstance(TaskType.PROPAGATION).newTaskExec();
exec.setStatus(ExecStatus.CREATED.name());
exec.setExecutor(executor);
String taskExecutionMessage = null;
String failureReason = null;
// Flag to state whether any propagation has been attempted
Mutable<Boolean> propagationAttempted = new MutableObject<>(false);
boolean fetchRemoteObj = isFetchRemoteObj(taskInfo);
ConnectorObject beforeObj = null;
ConnectorObject afterObj = null;
Provision provision = null;
OrgUnit orgUnit = null;
Uid uid = null;
OpEvent.Outcome result;
try {
provision = taskInfo.getResource().
getProvisionByObjectClass(taskInfo.getObjectClass().getObjectClassValue()).orElse(null);
orgUnit = taskInfo.getResource().getOrgUnit();
if (taskInfo.getBeforeObj().isEmpty()) {
if (fetchRemoteObj) {
// Try to read remote object BEFORE any actual operation
beforeObj = provision == null && orgUnit == null
? null
: orgUnit == null
? getRemoteObject(taskInfo, connector, provision, actions, false)
: getRemoteObject(taskInfo, connector, orgUnit, actions, false);
taskInfo.setBeforeObj(Optional.ofNullable(beforeObj));
}
} else {
beforeObj = taskInfo.getBeforeObj().get();
}
actions.forEach(action -> action.before(taskInfo));
switch (taskInfo.getOperation()) {
case CREATE:
case UPDATE:
uid = createOrUpdate(taskInfo, fetchRemoteObj, beforeObj, connector, propagationAttempted);
break;
case DELETE:
uid = delete(taskInfo, fetchRemoteObj, beforeObj, connector, propagationAttempted);
break;
default:
}
exec.setStatus(propagationAttempted.getValue()
? ExecStatus.SUCCESS.name()
: ExecStatus.NOT_ATTEMPTED.name());
result = OpEvent.Outcome.SUCCESS;
LOG.debug("Successfully propagated to {}", taskInfo.getResource());
} catch (Exception e) {
result = OpEvent.Outcome.FAILURE;
exec.setStatus(ExecStatus.FAILURE.name());
propagationAttempted.setValue(true);
LOG.error("Exception during provision on resource {}", taskInfo.getResource().getKey(), e);
if (e instanceof ConnectorException && e.getCause() != null) {
taskExecutionMessage = e.getCause().getMessage();
if (e.getCause().getMessage() == null) {
failureReason = e.getMessage();
} else {
failureReason = e.getMessage() + "\n\n Cause: " + e.getCause().getMessage().split("\n")[0];
}
} else {
taskExecutionMessage = ExceptionUtils2.getFullStackTrace(e);
if (e.getCause() == null) {
failureReason = e.getMessage();
} else {
failureReason = e.getMessage() + "\n\n Cause: " + e.getCause().getMessage().split("\n")[0];
}
}
actions.forEach(action -> action.onError(taskInfo, exec, e));
} finally {
// Try to read remote object AFTER any actual operation
if (uid != null) {
taskInfo.setConnObjectKey(uid.getUidValue());
}
if (fetchRemoteObj) {
try {
afterObj = provision == null && orgUnit == null
? null
: orgUnit == null
? getRemoteObject(taskInfo, connector, provision, actions, true)
: getRemoteObject(taskInfo, connector, orgUnit, actions, true);
} catch (Exception ignore) {
// ignore exception
LOG.error("Error retrieving after object", ignore);
}
}
if (!ExecStatus.FAILURE.name().equals(exec.getStatus())
&& afterObj == null
&& uid != null
&& taskInfo.getOperation() != ResourceOperation.DELETE) {
afterObj = new ConnectorObjectBuilder().
setObjectClass(taskInfo.getObjectClass()).
setUid(uid).
setName(Optional.ofNullable(
AttributeUtil.getNameFromAttributes(taskInfo.getPropagationData().getAttributes())).
orElseGet(() -> new Name(taskInfo.getConnObjectKey()))).
build();
}
exec.setStart(start);
exec.setMessage(taskExecutionMessage);
exec.setEnd(OffsetDateTime.now());
LOG.debug("Execution finished: {}", exec);
hasToBeregistered(taskInfo, exec).ifPresent(task -> {
LOG.debug("Execution to be stored: {}", exec);
exec.setTask(task);
task.add(exec);
taskInfo.setKey(taskDAO.save(task).getKey());
});
String fiql = provision == null
? null
: afterObj != null
? outboundMatcher.getFIQL(afterObj, taskInfo.getResource(), provision)
: beforeObj != null
? outboundMatcher.getFIQL(beforeObj, taskInfo.getResource(), provision)
: null;
reporter.onSuccessOrNonPriorityResourceFailures(
taskInfo,
ExecStatus.valueOf(exec.getStatus()),
failureReason,
fiql,
beforeObj,
afterObj);
}
for (PropagationActions action : actions) {
action.after(taskInfo, exec, afterObj);
}
// SYNCOPE-1136
String anyTypeKind = Optional.ofNullable(taskInfo.getAnyTypeKind()).map(Enum::name).orElse("realm");
String operation = taskInfo.getOperation().name().toLowerCase();
boolean notificationsAvailable = notificationManager.notificationsAvailable(
AuthContextUtils.getDomain(),
OpEvent.CategoryType.PROPAGATION,
anyTypeKind,
taskInfo.getResource().getKey(),
operation);
boolean auditRequested = auditManager.auditRequested(
AuthContextUtils.getDomain(),
AuthContextUtils.getUsername(),
OpEvent.CategoryType.PROPAGATION,
anyTypeKind,
taskInfo.getResource().getKey(),
operation);
if (notificationsAvailable || auditRequested) {
ExecTO execTO = taskDataBinder.getExecTO(exec);
AfterHandlingEvent event = new AfterHandlingEvent(
AuthContextUtils.getDomain(),
AuthContextUtils.getWho(),
OpEvent.CategoryType.PROPAGATION,
anyTypeKind,
taskInfo.getResource().getKey(),
operation,
result,
beforeObj,
new Object[] { execTO, afterObj },
taskInfo);
notificationManager.createTasks(event);
auditManager.audit(event);
}
return exec;
}