in core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java [293:551]
protected void doHandle(final Any any, final Provision provision) throws JobExecutionException {
ProvisioningReport result = new ProvisioningReport();
profile.getResults().add(result);
result.setKey(any.getKey());
result.setAnyType(any.getType().getKey());
result.setName(getName(any));
LOG.debug("Pushing {} with key {} towards {}",
any.getType().getKind(), any.getKey(), profile.getTask().getResource());
// Try to read remote object BEFORE any actual operation
Set<String> moreAttrsToGet = new HashSet<>();
profile.getActions().forEach(action -> moreAttrsToGet.addAll(action.moreAttrsToGet(profile, any)));
List<ConnectorObject> connObjs = outboundMatcher.match(
profile.getConnector(),
any,
profile.getTask().getResource(),
provision,
Optional.of(moreAttrsToGet.toArray(String[]::new)));
LOG.debug("Match(es) found for {} as {}: {}", any, provision.getObjectClass(), connObjs);
if (connObjs.size() > 1) {
switch (profile.getConflictResolutionAction()) {
case IGNORE:
throw new IgnoreProvisionException("More than one match found for "
+ any.getKey() + ": " + connObjs);
case FIRSTMATCH:
connObjs = connObjs.subList(0, 1);
break;
case LASTMATCH:
connObjs = connObjs.subList(connObjs.size() - 1, connObjs.size());
break;
default:
}
}
ConnectorObject beforeObj = connObjs.isEmpty() ? null : connObjs.getFirst();
if (profile.isDryRun()) {
if (beforeObj == null) {
result.setOperation(toResourceOperation(profile.getTask().getUnmatchingRule()));
} else {
result.setOperation(toResourceOperation(profile.getTask().getMatchingRule()));
}
result.setStatus(ProvisioningReport.Status.SUCCESS);
} else {
String operation = beforeObj == null
? UnmatchingRule.toOp(profile.getTask().getUnmatchingRule())
: MatchingRule.toOp(profile.getTask().getMatchingRule());
boolean notificationsAvailable = notificationManager.notificationsAvailable(
AuthContextUtils.getDomain(),
OpEvent.CategoryType.PUSH,
any.getType().getKind().name(),
profile.getTask().getResource().getKey(),
operation);
boolean auditRequested = auditManager.auditRequested(
AuthContextUtils.getDomain(),
AuthContextUtils.getUsername(),
OpEvent.CategoryType.PUSH,
any.getType().getKind().name(),
profile.getTask().getResource().getKey(),
operation);
Object output = null;
OpEvent.Outcome resultStatus = null;
Boolean enable = any instanceof User user && profile.getTask().isSyncStatus()
? BooleanUtils.negate(user.isSuspended())
: null;
try {
if (beforeObj == null) {
result.setOperation(toResourceOperation(profile.getTask().getUnmatchingRule()));
switch (profile.getTask().getUnmatchingRule()) {
case ASSIGN -> {
for (PushActions action : profile.getActions()) {
action.beforeAssign(profile, any);
}
if (!profile.getTask().isPerformCreate()) {
LOG.debug("PushTask not configured for create");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
assign(any, enable, result);
}
}
case PROVISION -> {
for (PushActions action : profile.getActions()) {
action.beforeProvision(profile, any);
}
if (!profile.getTask().isPerformCreate()) {
LOG.debug("PushTask not configured for create");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
provision(any, enable, result);
}
}
case UNLINK -> {
for (PushActions action : profile.getActions()) {
action.beforeUnlink(profile, any);
}
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
link(any, true, result);
}
}
case IGNORE -> {
LOG.debug("Ignored any: {}", any);
result.setStatus(ProvisioningReport.Status.IGNORE);
}
default -> {
}
}
// do nothing
} else {
result.setOperation(toResourceOperation(profile.getTask().getMatchingRule()));
switch (profile.getTask().getMatchingRule()) {
case UPDATE -> {
for (PushActions action : profile.getActions()) {
action.beforeUpdate(profile, any);
}
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
update(any, enable, beforeObj, result);
}
}
case DEPROVISION -> {
for (PushActions action : profile.getActions()) {
action.beforeDeprovision(profile, any);
}
if (!profile.getTask().isPerformDelete()) {
LOG.debug("PushTask not configured for delete");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
deprovision(any, beforeObj, result);
}
}
case UNASSIGN -> {
for (PushActions action : profile.getActions()) {
action.beforeUnassign(profile, any);
}
if (!profile.getTask().isPerformDelete()) {
LOG.debug("PushTask not configured for delete");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
unassign(any, beforeObj, result);
}
}
case LINK -> {
for (PushActions action : profile.getActions()) {
action.beforeLink(profile, any);
}
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
link(any, false, result);
}
}
case UNLINK -> {
for (PushActions action : profile.getActions()) {
action.beforeUnlink(profile, any);
}
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
result.setStatus(ProvisioningReport.Status.IGNORE);
} else {
link(any, true, result);
}
}
case IGNORE -> {
LOG.debug("Ignored any: {}", any);
result.setStatus(ProvisioningReport.Status.IGNORE);
}
default -> {
}
}
// do nothing
}
for (PushActions action : profile.getActions()) {
action.after(profile, any, result);
}
if (result.getStatus() == null) {
result.setStatus(ProvisioningReport.Status.SUCCESS);
}
if (notificationsAvailable || auditRequested) {
resultStatus = OpEvent.Outcome.SUCCESS;
output = outboundMatcher.match(
profile.getConnector(),
any,
profile.getTask().getResource(),
provision,
Optional.of(moreAttrsToGet.toArray(String[]::new)));
}
} catch (IgnoreProvisionException e) {
throw e;
} catch (Exception e) {
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
if (notificationsAvailable || auditRequested) {
resultStatus = OpEvent.Outcome.FAILURE;
output = e;
}
LOG.warn("Error pushing {} towards {}", any, profile.getTask().getResource(), e);
for (PushActions action : profile.getActions()) {
action.onError(profile, any, result, e);
}
throw new JobExecutionException(e);
} finally {
if (notificationsAvailable || auditRequested) {
Map<String, Object> jobMap = new HashMap<>();
jobMap.put(AfterHandlingEvent.JOBMAP_KEY, new AfterHandlingEvent(
AuthContextUtils.getDomain(),
AuthContextUtils.getWho(),
OpEvent.CategoryType.PUSH,
any.getType().getKind().name(),
profile.getTask().getResource().getKey(),
operation,
resultStatus,
beforeObj,
output,
any));
AfterHandlingJob.schedule(scheduler, jobMap);
}
}
}
}