/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.syncope.core.provisioning.java.pushpull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.syncope.common.lib.patch.AnyPatch;
import org.apache.syncope.common.lib.patch.StringPatchItem;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditElements.Result;
import org.apache.syncope.common.lib.types.MatchingRule;
import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.core.provisioning.api.PropagationByResource;
import org.apache.syncope.common.lib.types.PullMode;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.provisioning.api.ProvisioningManager;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullExecutor;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandler;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.SyncDelta;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@Transactional(rollbackFor = Throwable.class)
public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHandler<PullTask, PullActions>
implements SyncopePullResultHandler {
@Autowired
protected PullUtils pullUtils;
@Autowired
protected VirSchemaDAO virSchemaDAO;
@Autowired
protected VirAttrCache virAttrCache;
protected SyncopePullExecutor executor;
protected Result latestResult;
protected abstract String getName(AnyTO anyTO);
protected abstract ProvisioningManager<?, ?> getProvisioningManager();
protected abstract AnyTO doCreate(AnyTO anyTO, SyncDelta delta, ProvisioningReport result);
protected abstract AnyTO doUpdate(AnyTO before, AnyPatch anyPatch, SyncDelta delta, ProvisioningReport result);
protected void doDelete(final AnyTypeKind kind, final String key) {
PropagationByResource propByRes = new PropagationByResource();
propByRes.add(ResourceOperation.DELETE, profile.getTask().getResource().getKey());
try {
taskExecutor.execute(propagationManager.getDeleteTasks(
kind,
key,
propByRes,
null));
} catch (Exception e) {
// A propagation failure doesn't imply a pull failure.
// The propagation exception status will be reported into the propagation task execution.
LOG.error("Could not propagate anyObject " + key, e);
}
getProvisioningManager().delete(key, Collections.singleton(profile.getTask().getResource().getKey()), true);
}
@Override
public void setPullExecutor(final SyncopePullExecutor executor) {
this.executor = executor;
}
@Override
public boolean handle(final SyncDelta delta) {
Provision provision = null;
try {
provision = profile.getTask().getResource().getProvision(delta.getObject().getObjectClass());
if (provision == null) {
throw new JobExecutionException("No provision found on " + profile.getTask().getResource() + " for "
+ delta.getObject().getObjectClass());
}
doHandle(delta, provision);
LOG.debug("Successfully handled {}", delta);
if (profile.getTask().getPullMode() != PullMode.INCREMENTAL) {
return true;
}
boolean shouldContinue;
synchronized (this) {
shouldContinue = latestResult == Result.SUCCESS;
this.latestResult = null;
}
if (shouldContinue) {
executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
}
return shouldContinue;
} catch (IgnoreProvisionException e) {
ProvisioningReport ignoreResult = new ProvisioningReport();
ignoreResult.setOperation(ResourceOperation.NONE);
ignoreResult.setAnyType(provision == null
? getAnyUtils().getAnyTypeKind().name() : provision.getAnyType().getKey());
ignoreResult.setStatus(ProvisioningReport.Status.IGNORE);
ignoreResult.setKey(null);
ignoreResult.setName(delta.getObject().getName().getNameValue());
profile.getResults().add(ignoreResult);
LOG.warn("Ignoring during pull", e);
executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
return true;
} catch (JobExecutionException e) {
LOG.error("Pull failed", e);
return false;
}
}
protected List<ProvisioningReport> assign(
final SyncDelta delta, final Provision provision, final AnyUtils anyUtils)
throws JobExecutionException {
if (!profile.getTask().isPerformCreate()) {
LOG.debug("PullTask not configured for create");
finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
AnyTO anyTO = connObjectUtils.getAnyTO(delta.getObject(), profile.getTask(), provision, anyUtils);
anyTO.getResources().add(profile.getTask().getResource().getKey());
ProvisioningReport result = new ProvisioningReport();
result.setOperation(ResourceOperation.CREATE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
result.setName(getName(anyTO));
if (profile.isDryRun()) {
result.setKey(null);
finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
} else {
SyncDelta actionedDelta = delta;
for (PullActions action : profile.getActions()) {
actionedDelta = action.beforeAssign(profile, actionedDelta, anyTO);
}
create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
}
return Collections.singletonList(result);
}
protected List<ProvisioningReport> provision(
final SyncDelta delta, final Provision provision, final AnyUtils anyUtils)
throws JobExecutionException {
if (!profile.getTask().isPerformCreate()) {
LOG.debug("PullTask not configured for create");
finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
AnyTO anyTO = connObjectUtils.getAnyTO(delta.getObject(), profile.getTask(), provision, anyUtils);
ProvisioningReport result = new ProvisioningReport();
result.setOperation(ResourceOperation.CREATE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
result.setName(getName(anyTO));
if (profile.isDryRun()) {
result.setKey(null);
finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
} else {
SyncDelta actionedDelta = delta;
for (PullActions action : profile.getActions()) {
actionedDelta = action.beforeProvision(profile, actionedDelta, anyTO);
}
create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
}
return Collections.singletonList(result);
}
protected void throwIgnoreProvisionException(final SyncDelta delta, final Exception exception)
throws JobExecutionException {
if (exception instanceof IgnoreProvisionException) {
throw IgnoreProvisionException.class.cast(exception);
}
IgnoreProvisionException ipe = null;
for (PullActions action : profile.getActions()) {
if (ipe == null) {
ipe = action.onError(profile, delta, exception);
}
}
if (ipe != null) {
throw ipe;
}
}
protected void create(
final AnyTO anyTO,
final SyncDelta delta,
final String operation,
final ProvisioningReport result)
throws JobExecutionException {
Object output;
Result resultStatus;
try {
AnyTO actual = doCreate(anyTO, delta, result);
result.setName(getName(actual));
output = actual;
resultStatus = Result.SUCCESS;
for (PullActions action : profile.getActions()) {
action.after(profile, delta, actual, result);
}
LOG.debug("{} {} successfully created", actual.getType(), actual.getKey());
} catch (PropagationException e) {
// A propagation failure doesn't imply a pull failure.
// The propagation exception status will be reported into the propagation task execution.
LOG.error("Could not propagate {} {}", anyTO.getType(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
} catch (Exception e) {
throwIgnoreProvisionException(delta, e);
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not create {} {} ", anyTO.getType(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
}
finalize(operation, resultStatus, null, output, delta);
}
protected List<ProvisioningReport> update(
final SyncDelta delta, final List<String> anys, final Provision provision) throws JobExecutionException {
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PullTask not configured for update");
finalize(MatchingRule.toEventName(MatchingRule.UPDATE), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
LOG.debug("About to update {}", anys);
List<ProvisioningReport> results = new ArrayList<>();
SyncDelta workingDelta = delta;
for (String key : anys) {
LOG.debug("About to update {}", key);
ProvisioningReport result = new ProvisioningReport();
result.setOperation(ResourceOperation.UPDATE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
result.setKey(key);
AnyTO before = getAnyTO(key);
if (before == null) {
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), key));
} else {
result.setName(getName(before));
}
Result resultStatus;
Object output;
if (!profile.isDryRun()) {
if (before == null) {
resultStatus = Result.FAILURE;
output = null;
} else {
try {
AnyPatch anyPatch = connObjectUtils.getAnyPatch(
before.getKey(),
workingDelta.getObject(),
before,
profile.getTask(),
provision,
getAnyUtils());
for (PullActions action : profile.getActions()) {
workingDelta = action.beforeUpdate(profile, workingDelta, before, anyPatch);
}
AnyTO updated = doUpdate(before, anyPatch, workingDelta, result);
for (PullActions action : profile.getActions()) {
action.after(profile, workingDelta, updated, result);
}
output = updated;
resultStatus = Result.SUCCESS;
result.setName(getName(updated));
LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), key);
} catch (PropagationException e) {
// A propagation failure doesn't imply a pull failure.
// The propagation exception status will be reported into the propagation task execution.
LOG.error("Could not propagate {} {}",
provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
} catch (Exception e) {
throwIgnoreProvisionException(delta, e);
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not update {} {}",
provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
}
}
finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, workingDelta);
}
results.add(result);
}
return results;
}
protected List<ProvisioningReport> deprovision(
final SyncDelta delta,
final List<String> anys,
final Provision provision,
final boolean unlink)
throws JobExecutionException {
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PullTask not configured for update");
finalize(unlink
? MatchingRule.toEventName(MatchingRule.UNASSIGN)
: MatchingRule.toEventName(MatchingRule.DEPROVISION), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
LOG.debug("About to update {}", anys);
final List<ProvisioningReport> updResults = new ArrayList<>();
for (String key : anys) {
LOG.debug("About to unassign resource {}", key);
Object output;
Result resultStatus;
ProvisioningReport result = new ProvisioningReport();
result.setOperation(ResourceOperation.DELETE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
result.setKey(key);
AnyTO before = getAnyTO(key);
if (before == null) {
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), key));
}
if (!profile.isDryRun()) {
if (before == null) {
resultStatus = Result.FAILURE;
output = null;
} else {
result.setName(getName(before));
try {
if (unlink) {
for (PullActions action : profile.getActions()) {
action.beforeUnassign(profile, delta, before);
}
} else {
for (PullActions action : profile.getActions()) {
action.beforeDeprovision(profile, delta, before);
}
}
PropagationByResource propByRes = new PropagationByResource();
propByRes.add(ResourceOperation.DELETE, profile.getTask().getResource().getKey());
taskExecutor.execute(propagationManager.getDeleteTasks(
provision.getAnyType().getKind(),
key,
propByRes,
null));
AnyPatch anyPatch = null;
if (unlink) {
anyPatch = newPatch(key);
anyPatch.getResources().add(new StringPatchItem.Builder().
operation(PatchOperation.DELETE).
value(profile.getTask().getResource().getKey()).build());
}
if (anyPatch == null) {
output = getAnyTO(key);
} else {
output = doUpdate(before, anyPatch, delta, result);
}
for (PullActions action : profile.getActions()) {
action.after(profile, delta, AnyTO.class.cast(output), result);
}
resultStatus = Result.SUCCESS;
LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), key);
} catch (PropagationException e) {
// A propagation failure doesn't imply a pull failure.
// The propagation exception status will be reported into the propagation task execution.
LOG.error("Could not propagate {} {}",
provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
} catch (Exception e) {
throwIgnoreProvisionException(delta, e);
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not update {} {}",
provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
}
}
finalize(unlink
? MatchingRule.toEventName(MatchingRule.UNASSIGN)
: MatchingRule.toEventName(MatchingRule.DEPROVISION), resultStatus, before, output, delta);
}
updResults.add(result);
}
return updResults;
}
protected List<ProvisioningReport> link(
final SyncDelta delta,
final List<String> anys,
final Provision provision,
final boolean unlink)
throws JobExecutionException {
if (!profile.getTask().isPerformUpdate()) {
LOG.debug("PullTask not configured for update");
finalize(unlink
? MatchingRule.toEventName(MatchingRule.UNLINK)
: MatchingRule.toEventName(MatchingRule.LINK), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
LOG.debug("About to update {}", anys);
final List<ProvisioningReport> updResults = new ArrayList<>();
for (String key : anys) {
LOG.debug("About to unassign resource {}", key);
Object output;
Result resultStatus;
ProvisioningReport result = new ProvisioningReport();
result.setOperation(ResourceOperation.NONE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
result.setKey(key);
AnyTO before = getAnyTO(key);
if (before == null) {
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), key));
}
if (!profile.isDryRun()) {
if (before == null) {
resultStatus = Result.FAILURE;
output = null;
} else {
result.setName(getName(before));
try {
if (unlink) {
for (PullActions action : profile.getActions()) {
action.beforeUnlink(profile, delta, before);
}
} else {
for (PullActions action : profile.getActions()) {
action.beforeLink(profile, delta, before);
}
}
AnyPatch patch = newPatch(before.getKey());
patch.getResources().add(new StringPatchItem.Builder().
operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
value(profile.getTask().getResource().getKey()).build());
output = getAnyTO(update(patch).getResult());
for (PullActions action : profile.getActions()) {
action.after(profile, delta, AnyTO.class.cast(output), result);
}
resultStatus = Result.SUCCESS;
LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), key);
} catch (PropagationException e) {
// A propagation failure doesn't imply a pull failure.
// The propagation exception status will be reported into the propagation task execution.
LOG.error("Could not propagate {} {}",
provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
} catch (Exception e) {
throwIgnoreProvisionException(delta, e);
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not update {} {}",
provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
}
}
finalize(unlink
? MatchingRule.toEventName(MatchingRule.UNLINK)
: MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, delta);
}
updResults.add(result);
}
return updResults;
}
protected List<ProvisioningReport> delete(
final SyncDelta delta,
final List<String> anys,
final Provision provision)
throws JobExecutionException {
if (!profile.getTask().isPerformDelete()) {
LOG.debug("PullTask not configured for delete");
finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
return Collections.<ProvisioningReport>emptyList();
}
LOG.debug("About to delete {}", anys);
List<ProvisioningReport> delResults = new ArrayList<>();
SyncDelta workingDelta = delta;
for (String key : anys) {
Object output;
Result resultStatus = Result.FAILURE;
ProvisioningReport result = new ProvisioningReport();
try {
AnyTO before = getAnyTO(key);
result.setKey(key);
result.setName(getName(before));
result.setOperation(ResourceOperation.DELETE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
if (!profile.isDryRun()) {
for (PullActions action : profile.getActions()) {
workingDelta = action.beforeDelete(profile, workingDelta, before);
}
try {
doDelete(provision.getAnyType().getKind(), key);
output = null;
resultStatus = Result.SUCCESS;
for (PullActions action : profile.getActions()) {
action.after(profile, workingDelta, before, result);
}
} catch (Exception e) {
throwIgnoreProvisionException(delta, e);
result.setStatus(ProvisioningReport.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not delete {} {}", provision.getAnyType().getKey(), key, e);
output = e;
}
finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
}
delResults.add(result);
} catch (NotFoundException e) {
LOG.error("Could not find {} {}", provision.getAnyType().getKey(), key, e);
} catch (DelegatedAdministrationException e) {
LOG.error("Not allowed to read {} {}", provision.getAnyType().getKey(), key, e);
} catch (Exception e) {
LOG.error("Could not delete {} {}", provision.getAnyType().getKey(), key, e);
}
}
return delResults;
}
protected ProvisioningReport ignore(
final SyncDelta delta,
final Provision provision,
final boolean matching)
throws JobExecutionException {
LOG.debug("Any to ignore {}", delta.getObject().getUid().getUidValue());
ProvisioningReport result = new ProvisioningReport();
result.setKey(null);
result.setName(delta.getObject().getUid().getUidValue());
result.setOperation(ResourceOperation.NONE);
result.setAnyType(provision.getAnyType().getKey());
result.setStatus(ProvisioningReport.Status.SUCCESS);
finalize(matching
? MatchingRule.toEventName(MatchingRule.IGNORE)
: UnmatchingRule.toEventName(UnmatchingRule.IGNORE), Result.SUCCESS, null, null, delta);
return result;
}
/**
* Look into SyncDelta and take necessary profile.getActions() (create / update / delete) on any object(s).
*
* @param delta returned by the underlying profile.getConnector()
* @param provision provisioning info
* @throws JobExecutionException in case of pull failure.
*/
protected void doHandle(final SyncDelta delta, final Provision provision) throws JobExecutionException {
AnyUtils anyUtils = getAnyUtils();
LOG.debug("Process {} for {} as {}",
delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
String uid = delta.getPreviousUid() == null
? delta.getUid().getUidValue()
: delta.getPreviousUid().getUidValue();
try {
List<String> anyKeys = pullUtils.findExisting(uid, delta.getObject(), provision, anyUtils);
LOG.debug("Match(es) found for {} as {}: {}",
delta.getUid().getUidValue(), delta.getObject().getObjectClass(), anyKeys);
if (anyKeys.size() > 1) {
switch (profile.getResAct()) {
case IGNORE:
throw new IllegalStateException("More than one match " + anyKeys);
case FIRSTMATCH:
anyKeys = anyKeys.subList(0, 1);
break;
case LASTMATCH:
anyKeys = anyKeys.subList(anyKeys.size() - 1, anyKeys.size());
break;
default:
// keep anyKeys unmodified
}
}
if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
if (anyKeys.isEmpty()) {
switch (profile.getTask().getUnmatchingRule()) {
case ASSIGN:
profile.getResults().addAll(assign(delta, provision, anyUtils));
break;
case PROVISION:
profile.getResults().addAll(provision(delta, provision, anyUtils));
break;
case IGNORE:
profile.getResults().add(ignore(delta, provision, false));
break;
default:
// do nothing
}
} else {
// update VirAttrCache
for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
Attribute attr = delta.getObject().getAttributeByName(virSchema.getExtAttrName());
for (String anyKey : anyKeys) {
if (attr == null) {
virAttrCache.expire(
provision.getAnyType().getKey(),
anyKey,
virSchema.getKey());
} else {
VirAttrCacheValue cacheValue = new VirAttrCacheValue();
cacheValue.setValues(attr.getValue());
virAttrCache.put(
provision.getAnyType().getKey(),
anyKey,
virSchema.getKey(),
cacheValue);
}
}
}
switch (profile.getTask().getMatchingRule()) {
case UPDATE:
profile.getResults().addAll(update(delta, anyKeys, provision));
break;
case DEPROVISION:
profile.getResults().addAll(deprovision(delta, anyKeys, provision, false));
break;
case UNASSIGN:
profile.getResults().addAll(deprovision(delta, anyKeys, provision, true));
break;
case LINK:
profile.getResults().addAll(link(delta, anyKeys, provision, false));
break;
case UNLINK:
profile.getResults().addAll(link(delta, anyKeys, provision, true));
break;
case IGNORE:
profile.getResults().add(ignore(delta, provision, true));
break;
default:
// do nothing
}
}
} else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
if (anyKeys.isEmpty()) {
finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
LOG.debug("No match found for deletion");
} else {
profile.getResults().addAll(delete(delta, anyKeys, provision));
}
}
} catch (IllegalStateException | IllegalArgumentException e) {
LOG.warn(e.getMessage());
}
}
protected void finalize(
final String event,
final Result result,
final Object before,
final Object output,
final SyncDelta delta) {
synchronized (this) {
this.latestResult = result;
}
notificationManager.createTasks(AuditElements.EventCategoryType.PULL,
getAnyUtils().getAnyTypeKind().name().toLowerCase(),
profile.getTask().getResource().getKey(),
event,
result,
before,
output,
delta);
auditManager.audit(AuditElements.EventCategoryType.PULL,
getAnyUtils().getAnyTypeKind().name().toLowerCase(),
profile.getTask().getResource().getKey(),
event,
result,
before,
output,
delta);
}
}