You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/01/23 17:41:28 UTC
[06/15] syncope git commit: FIT server integration tests
http://git-wip-us.apache.org/repos/asf/syncope/blob/80589a1b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractPushResultHandler.java b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractPushResultHandler.java
new file mode 100644
index 0000000..74cd5f0
--- /dev/null
+++ b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractPushResultHandler.java
@@ -0,0 +1,374 @@
+/*
+ * 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.server.provisioning.java.sync;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.mod.MembershipMod;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.AuditElements.Result;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.server.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.server.persistence.api.entity.Mapping;
+import org.apache.syncope.server.persistence.api.entity.MappingItem;
+import org.apache.syncope.server.persistence.api.entity.Subject;
+import org.apache.syncope.server.persistence.api.entity.VirAttr;
+import org.apache.syncope.server.persistence.api.entity.membership.Membership;
+import org.apache.syncope.server.persistence.api.entity.task.PushTask;
+import org.apache.syncope.server.persistence.api.entity.user.User;
+import org.apache.syncope.server.provisioning.api.sync.ProvisioningResult;
+import org.apache.syncope.server.provisioning.api.sync.PushActions;
+import org.apache.syncope.server.misc.MappingUtil;
+import org.apache.syncope.server.provisioning.api.sync.SyncopePushResultHandler;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.quartz.JobExecutionException;
+import org.springframework.transaction.annotation.Transactional;
+
+public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHandler<PushTask, PushActions>
+ implements SyncopePushResultHandler {
+
+ protected abstract String getName(final Subject<?, ?, ?> subject);
+
+ protected abstract Mapping<?> getMapping();
+
+ protected abstract AbstractSubjectTO getSubjectTO(final long key);
+
+ protected abstract Subject<?, ?, ?> getSubject(final long key);
+
+ protected abstract Subject<?, ?, ?> deprovision(final Subject<?, ?, ?> sbj);
+
+ protected abstract Subject<?, ?, ?> provision(final Subject<?, ?, ?> sbj, final Boolean enabled);
+
+ protected abstract Subject<?, ?, ?> link(final Subject<?, ?, ?> sbj, final Boolean unlink);
+
+ protected abstract Subject<?, ?, ?> unassign(final Subject<?, ?, ?> sbj);
+
+ protected abstract Subject<?, ?, ?> assign(final Subject<?, ?, ?> sbj, Boolean enabled);
+
+ protected abstract ConnectorObject getRemoteObject(final String accountId);
+
+ @Transactional
+ @Override
+ public boolean handle(final long subjectId) {
+ try {
+ doHandle(subjectId);
+ return true;
+ } catch (JobExecutionException e) {
+ LOG.error("Synchronization failed", e);
+ return false;
+ }
+ }
+
+ protected final void doHandle(final long subjectId)
+ throws JobExecutionException {
+
+ final Subject<?, ?, ?> subject = getSubject(subjectId);
+
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(subject);
+
+ final ProvisioningResult result = new ProvisioningResult();
+ profile.getResults().add(result);
+
+ result.setId(subject.getKey());
+ result.setSubjectType(attrUtil.getType());
+ result.setName(getName(subject));
+
+ final Boolean enabled = subject instanceof User && profile.getTask().isSyncStatus()
+ ? ((User) subject).isSuspended() ? Boolean.FALSE : Boolean.TRUE
+ : null;
+
+ LOG.debug("Propagating {} with key {} towards {}",
+ attrUtil.getType(), subject.getKey(), profile.getTask().getResource());
+
+ Object output = null;
+ Result resultStatus = null;
+ ConnectorObject beforeObj = null;
+ String operation = null;
+
+ // Try to read remote object (user / group) BEFORE any actual operation
+ final String accountId = MappingUtil.getAccountIdValue(
+ subject, profile.getTask().getResource(), getMapping().getAccountIdItem());
+
+ beforeObj = getRemoteObject(accountId);
+
+ Boolean status = profile.getTask().isSyncStatus() ? enabled : null;
+
+ if (profile.isDryRun()) {
+ if (beforeObj == null) {
+ result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
+ } else {
+ result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
+ }
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+ } else {
+ try {
+ if (beforeObj == null) {
+ operation = profile.getTask().getUnmatchingRule().name().toLowerCase();
+ result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
+
+ switch (profile.getTask().getUnmatchingRule()) {
+ case ASSIGN:
+ for (PushActions action : profile.getActions()) {
+ action.beforeAssign(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("PushTask not configured for create");
+ } else {
+ assign(subject, status);
+ }
+
+ break;
+ case PROVISION:
+ for (PushActions action : profile.getActions()) {
+ action.beforeProvision(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("PushTask not configured for create");
+ } else {
+ provision(subject, status);
+ }
+
+ break;
+ case UNLINK:
+ for (PushActions action : profile.getActions()) {
+ action.beforeUnlink(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PushTask not configured for update");
+ } else {
+ link(subject, true);
+ }
+
+ break;
+ default:
+ // do nothing
+ }
+
+ } else {
+ operation = profile.getTask().getMatchingRule().name().toLowerCase();
+ result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
+
+ switch (profile.getTask().getMatchingRule()) {
+ case UPDATE:
+ for (PushActions action : profile.getActions()) {
+ action.beforeUpdate(this.getProfile(), subject);
+ }
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PushTask not configured for update");
+ } else {
+ update(subject, status);
+ }
+
+ break;
+ case DEPROVISION:
+ for (PushActions action : profile.getActions()) {
+ action.beforeDeprovision(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformDelete()) {
+ LOG.debug("PushTask not configured for delete");
+ } else {
+ deprovision(subject);
+ }
+
+ break;
+ case UNASSIGN:
+ for (PushActions action : profile.getActions()) {
+ action.beforeUnassign(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformDelete()) {
+ LOG.debug("PushTask not configured for delete");
+ } else {
+ unassign(subject);
+ }
+
+ break;
+ case LINK:
+ for (PushActions action : profile.getActions()) {
+ action.beforeLink(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PushTask not configured for update");
+ } else {
+ link(subject, false);
+ }
+
+ break;
+ case UNLINK:
+ for (PushActions action : profile.getActions()) {
+ action.beforeUnlink(this.getProfile(), subject);
+ }
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PushTask not configured for update");
+ } else {
+ link(subject, true);
+ }
+
+ break;
+ default:
+ // do nothing
+ }
+ }
+
+ for (PushActions action : profile.getActions()) {
+ action.after(this.getProfile(), subject, result);
+ }
+
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+ resultStatus = AuditElements.Result.SUCCESS;
+ output = getRemoteObject(accountId);
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ resultStatus = AuditElements.Result.FAILURE;
+ output = e;
+
+ LOG.warn("Error pushing {} towards {}", subject, profile.getTask().getResource(), e);
+ throw new JobExecutionException(e);
+ } finally {
+ notificationManager.createTasks(
+ AuditElements.EventCategoryType.PUSH,
+ AttributableType.USER.name().toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ operation,
+ resultStatus,
+ beforeObj,
+ output,
+ subject);
+ auditManager.audit(
+ AuditElements.EventCategoryType.PUSH,
+ AttributableType.USER.name().toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ operation,
+ resultStatus,
+ beforeObj,
+ output,
+ subject);
+ }
+ }
+ }
+
+ private ResourceOperation getResourceOperation(final UnmatchingRule rule) {
+ switch (rule) {
+ case ASSIGN:
+ case PROVISION:
+ return ResourceOperation.CREATE;
+ default:
+ return ResourceOperation.NONE;
+ }
+ }
+
+ private ResourceOperation getResourceOperation(final MatchingRule rule) {
+ switch (rule) {
+ case UPDATE:
+ return ResourceOperation.UPDATE;
+ case DEPROVISION:
+ case UNASSIGN:
+ return ResourceOperation.DELETE;
+ default:
+ return ResourceOperation.NONE;
+ }
+ }
+
+ protected Subject<?, ?, ?> update(final Subject<?, ?, ?> sbj, final Boolean enabled) {
+
+ final Set<MembershipMod> membsToAdd = new HashSet<>();
+ final Set<String> vattrToBeRemoved = new HashSet<>();
+ final Set<String> membVattrToBeRemoved = new HashSet<>();
+ final Set<AttrMod> vattrToBeUpdated = new HashSet<>();
+
+ // Search for all mapped vattrs
+ final Mapping<?> umapping = getMapping();
+ for (MappingItem mappingItem : umapping.getItems()) {
+ if (mappingItem.getIntMappingType() == IntMappingType.UserVirtualSchema) {
+ vattrToBeRemoved.add(mappingItem.getIntAttrName());
+ } else if (mappingItem.getIntMappingType() == IntMappingType.MembershipVirtualSchema) {
+ membVattrToBeRemoved.add(mappingItem.getIntAttrName());
+ }
+ }
+
+ // Search for all user's vattrs and:
+ // 1. add mapped vattrs not owned by the user to the set of vattrs to be removed
+ // 2. add all vattrs owned by the user to the set of vattrs to be update
+ for (VirAttr vattr : sbj.getVirAttrs()) {
+ vattrToBeRemoved.remove(vattr.getSchema().getKey());
+ final AttrMod mod = new AttrMod();
+ mod.setSchema(vattr.getSchema().getKey());
+ mod.getValuesToBeAdded().addAll(vattr.getValues());
+ vattrToBeUpdated.add(mod);
+ }
+
+ final boolean changepwd;
+
+ if (sbj instanceof User) {
+ changepwd = true;
+
+ // Search for memberships
+ for (Membership membership : User.class.cast(sbj).getMemberships()) {
+ final MembershipMod membershipMod = new MembershipMod();
+ membershipMod.setKey(membership.getKey());
+ membershipMod.setRole(membership.getRole().getKey());
+
+ for (VirAttr vattr : membership.getVirAttrs()) {
+ membVattrToBeRemoved.remove(vattr.getSchema().getKey());
+ final AttrMod mod = new AttrMod();
+ mod.setSchema(vattr.getSchema().getKey());
+ mod.getValuesToBeAdded().addAll(vattr.getValues());
+ membershipMod.getVirAttrsToUpdate().add(mod);
+ }
+
+ membsToAdd.add(membershipMod);
+ }
+
+ if (!membsToAdd.isEmpty()) {
+ membsToAdd.iterator().next().getVirAttrsToRemove().addAll(membVattrToBeRemoved);
+ }
+ } else {
+ changepwd = false;
+ }
+
+ final List<String> noPropResources = new ArrayList<>(sbj.getResourceNames());
+ noPropResources.remove(profile.getTask().getResource().getKey());
+
+ final PropagationByResource propByRes = new PropagationByResource();
+ propByRes.add(ResourceOperation.CREATE, profile.getTask().getResource().getKey());
+
+ taskExecutor.execute(propagationManager.getUpdateTaskIds(
+ sbj, null, changepwd, enabled, vattrToBeRemoved, vattrToBeUpdated, propByRes, noPropResources,
+ membsToAdd));
+
+ return userDAO.authFetch(sbj.getKey());
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/80589a1b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectPushResultHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectPushResultHandler.java b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectPushResultHandler.java
deleted file mode 100644
index f0b70cd..0000000
--- a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectPushResultHandler.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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.server.provisioning.java.sync;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.syncope.common.lib.mod.AttrMod;
-import org.apache.syncope.common.lib.mod.MembershipMod;
-import org.apache.syncope.common.lib.to.AbstractSubjectTO;
-import org.apache.syncope.common.lib.types.AttributableType;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.AuditElements.Result;
-import org.apache.syncope.common.lib.types.IntMappingType;
-import org.apache.syncope.common.lib.types.MatchingRule;
-import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.common.lib.types.UnmatchingRule;
-import org.apache.syncope.server.persistence.api.entity.AttributableUtil;
-import org.apache.syncope.server.persistence.api.entity.Mapping;
-import org.apache.syncope.server.persistence.api.entity.MappingItem;
-import org.apache.syncope.server.persistence.api.entity.Subject;
-import org.apache.syncope.server.persistence.api.entity.VirAttr;
-import org.apache.syncope.server.persistence.api.entity.membership.Membership;
-import org.apache.syncope.server.persistence.api.entity.task.PushTask;
-import org.apache.syncope.server.persistence.api.entity.user.User;
-import org.apache.syncope.server.provisioning.api.sync.ProvisioningResult;
-import org.apache.syncope.server.provisioning.api.sync.PushActions;
-import org.apache.syncope.server.misc.MappingUtil;
-import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.quartz.JobExecutionException;
-import org.springframework.transaction.annotation.Transactional;
-
-public abstract class AbstractSubjectPushResultHandler extends AbstractSyncopeResultHandler<PushTask, PushActions> {
-
- protected abstract String getName(final Subject<?, ?, ?> subject);
-
- protected abstract Mapping<?> getMapping();
-
- protected abstract AbstractSubjectTO getSubjectTO(final long key);
-
- protected abstract Subject<?, ?, ?> getSubject(final long key);
-
- protected abstract Subject<?, ?, ?> deprovision(final Subject<?, ?, ?> sbj);
-
- protected abstract Subject<?, ?, ?> provision(final Subject<?, ?, ?> sbj, final Boolean enabled);
-
- protected abstract Subject<?, ?, ?> link(final Subject<?, ?, ?> sbj, final Boolean unlink);
-
- protected abstract Subject<?, ?, ?> unassign(final Subject<?, ?, ?> sbj);
-
- protected abstract Subject<?, ?, ?> assign(final Subject<?, ?, ?> sbj, Boolean enabled);
-
- protected abstract ConnectorObject getRemoteObject(final String accountId);
-
- @Transactional
- public boolean handle(final long subjectId) {
- try {
- doHandle(subjectId);
- return true;
- } catch (JobExecutionException e) {
- LOG.error("Synchronization failed", e);
- return false;
- }
- }
-
- protected final void doHandle(final long subjectId)
- throws JobExecutionException {
-
- final Subject<?, ?, ?> subject = getSubject(subjectId);
-
- final AttributableUtil attrUtil = attrUtilFactory.getInstance(subject);
-
- final ProvisioningResult result = new ProvisioningResult();
- profile.getResults().add(result);
-
- result.setId(subject.getKey());
- result.setSubjectType(attrUtil.getType());
- result.setName(getName(subject));
-
- final Boolean enabled = subject instanceof User && profile.getTask().isSyncStatus()
- ? ((User) subject).isSuspended() ? Boolean.FALSE : Boolean.TRUE
- : null;
-
- LOG.debug("Propagating {} with key {} towards {}",
- attrUtil.getType(), subject.getKey(), profile.getTask().getResource());
-
- Object output = null;
- Result resultStatus = null;
- ConnectorObject beforeObj = null;
- String operation = null;
-
- // Try to read remote object (user / group) BEFORE any actual operation
- final String accountId = MappingUtil.getAccountIdValue(
- subject, profile.getTask().getResource(), getMapping().getAccountIdItem());
-
- beforeObj = getRemoteObject(accountId);
-
- Boolean status = profile.getTask().isSyncStatus() ? enabled : null;
-
- if (profile.isDryRun()) {
- if (beforeObj == null) {
- result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
- } else {
- result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
- }
- result.setStatus(ProvisioningResult.Status.SUCCESS);
- } else {
- try {
- if (beforeObj == null) {
- operation = profile.getTask().getUnmatchingRule().name().toLowerCase();
- result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
-
- switch (profile.getTask().getUnmatchingRule()) {
- case ASSIGN:
- for (PushActions action : profile.getActions()) {
- action.beforeAssign(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformCreate()) {
- LOG.debug("PushTask not configured for create");
- } else {
- assign(subject, status);
- }
-
- break;
- case PROVISION:
- for (PushActions action : profile.getActions()) {
- action.beforeProvision(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformCreate()) {
- LOG.debug("PushTask not configured for create");
- } else {
- provision(subject, status);
- }
-
- break;
- case UNLINK:
- for (PushActions action : profile.getActions()) {
- action.beforeUnlink(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("PushTask not configured for update");
- } else {
- link(subject, true);
- }
-
- break;
- default:
- // do nothing
- }
-
- } else {
- operation = profile.getTask().getMatchingRule().name().toLowerCase();
- result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
-
- switch (profile.getTask().getMatchingRule()) {
- case UPDATE:
- for (PushActions action : profile.getActions()) {
- action.beforeUpdate(this.getProfile(), subject);
- }
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("PushTask not configured for update");
- } else {
- update(subject, status);
- }
-
- break;
- case DEPROVISION:
- for (PushActions action : profile.getActions()) {
- action.beforeDeprovision(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformDelete()) {
- LOG.debug("PushTask not configured for delete");
- } else {
- deprovision(subject);
- }
-
- break;
- case UNASSIGN:
- for (PushActions action : profile.getActions()) {
- action.beforeUnassign(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformDelete()) {
- LOG.debug("PushTask not configured for delete");
- } else {
- unassign(subject);
- }
-
- break;
- case LINK:
- for (PushActions action : profile.getActions()) {
- action.beforeLink(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("PushTask not configured for update");
- } else {
- link(subject, false);
- }
-
- break;
- case UNLINK:
- for (PushActions action : profile.getActions()) {
- action.beforeUnlink(this.getProfile(), subject);
- }
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("PushTask not configured for update");
- } else {
- link(subject, true);
- }
-
- break;
- default:
- // do nothing
- }
- }
-
- for (PushActions action : profile.getActions()) {
- action.after(this.getProfile(), subject, result);
- }
-
- result.setStatus(ProvisioningResult.Status.SUCCESS);
- resultStatus = AuditElements.Result.SUCCESS;
- output = getRemoteObject(accountId);
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- resultStatus = AuditElements.Result.FAILURE;
- output = e;
-
- LOG.warn("Error pushing {} towards {}", subject, profile.getTask().getResource(), e);
- throw new JobExecutionException(e);
- } finally {
- notificationManager.createTasks(
- AuditElements.EventCategoryType.PUSH,
- AttributableType.USER.name().toLowerCase(),
- profile.getTask().getResource().getKey(),
- operation,
- resultStatus,
- beforeObj,
- output,
- subject);
- auditManager.audit(
- AuditElements.EventCategoryType.PUSH,
- AttributableType.USER.name().toLowerCase(),
- profile.getTask().getResource().getKey(),
- operation,
- resultStatus,
- beforeObj,
- output,
- subject);
- }
- }
- }
-
- private ResourceOperation getResourceOperation(final UnmatchingRule rule) {
- switch (rule) {
- case ASSIGN:
- case PROVISION:
- return ResourceOperation.CREATE;
- default:
- return ResourceOperation.NONE;
- }
- }
-
- private ResourceOperation getResourceOperation(final MatchingRule rule) {
- switch (rule) {
- case UPDATE:
- return ResourceOperation.UPDATE;
- case DEPROVISION:
- case UNASSIGN:
- return ResourceOperation.DELETE;
- default:
- return ResourceOperation.NONE;
- }
- }
-
- protected Subject<?, ?, ?> update(final Subject<?, ?, ?> sbj, final Boolean enabled) {
-
- final Set<MembershipMod> membsToAdd = new HashSet<>();
- final Set<String> vattrToBeRemoved = new HashSet<>();
- final Set<String> membVattrToBeRemoved = new HashSet<>();
- final Set<AttrMod> vattrToBeUpdated = new HashSet<>();
-
- // Search for all mapped vattrs
- final Mapping<?> umapping = getMapping();
- for (MappingItem mappingItem : umapping.getItems()) {
- if (mappingItem.getIntMappingType() == IntMappingType.UserVirtualSchema) {
- vattrToBeRemoved.add(mappingItem.getIntAttrName());
- } else if (mappingItem.getIntMappingType() == IntMappingType.MembershipVirtualSchema) {
- membVattrToBeRemoved.add(mappingItem.getIntAttrName());
- }
- }
-
- // Search for all user's vattrs and:
- // 1. add mapped vattrs not owned by the user to the set of vattrs to be removed
- // 2. add all vattrs owned by the user to the set of vattrs to be update
- for (VirAttr vattr : sbj.getVirAttrs()) {
- vattrToBeRemoved.remove(vattr.getSchema().getKey());
- final AttrMod mod = new AttrMod();
- mod.setSchema(vattr.getSchema().getKey());
- mod.getValuesToBeAdded().addAll(vattr.getValues());
- vattrToBeUpdated.add(mod);
- }
-
- final boolean changepwd;
-
- if (sbj instanceof User) {
- changepwd = true;
-
- // Search for memberships
- for (Membership membership : User.class.cast(sbj).getMemberships()) {
- final MembershipMod membershipMod = new MembershipMod();
- membershipMod.setKey(membership.getKey());
- membershipMod.setRole(membership.getRole().getKey());
-
- for (VirAttr vattr : membership.getVirAttrs()) {
- membVattrToBeRemoved.remove(vattr.getSchema().getKey());
- final AttrMod mod = new AttrMod();
- mod.setSchema(vattr.getSchema().getKey());
- mod.getValuesToBeAdded().addAll(vattr.getValues());
- membershipMod.getVirAttrsToUpdate().add(mod);
- }
-
- membsToAdd.add(membershipMod);
- }
-
- if (!membsToAdd.isEmpty()) {
- membsToAdd.iterator().next().getVirAttrsToRemove().addAll(membVattrToBeRemoved);
- }
- } else {
- changepwd = false;
- }
-
- final List<String> noPropResources = new ArrayList<>(sbj.getResourceNames());
- noPropResources.remove(profile.getTask().getResource().getKey());
-
- final PropagationByResource propByRes = new PropagationByResource();
- propByRes.add(ResourceOperation.CREATE, profile.getTask().getResource().getKey());
-
- taskExecutor.execute(propagationManager.getUpdateTaskIds(
- sbj, null, changepwd, enabled, vattrToBeRemoved, vattrToBeUpdated, propByRes, noPropResources,
- membsToAdd));
-
- return userDAO.authFetch(sbj.getKey());
- }
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/80589a1b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectSyncResultHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectSyncResultHandler.java b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectSyncResultHandler.java
deleted file mode 100644
index 3c49eee..0000000
--- a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSubjectSyncResultHandler.java
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * 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.server.provisioning.java.sync;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.syncope.common.lib.mod.AbstractSubjectMod;
-import org.apache.syncope.common.lib.to.AbstractSubjectTO;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.AuditElements.Result;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.server.persistence.api.dao.NotFoundException;
-import org.apache.syncope.server.persistence.api.dao.UserDAO;
-import org.apache.syncope.server.persistence.api.entity.AttributableUtil;
-import org.apache.syncope.server.persistence.api.entity.task.SyncTask;
-import org.apache.syncope.server.provisioning.api.AttributableTransformer;
-import org.apache.syncope.server.provisioning.api.propagation.PropagationException;
-import org.apache.syncope.server.provisioning.api.sync.SyncActions;
-import org.apache.syncope.server.provisioning.api.sync.ProvisioningResult;
-import org.apache.syncope.server.misc.security.UnauthorizedRoleException;
-import org.identityconnectors.framework.common.objects.SyncDelta;
-import org.identityconnectors.framework.common.objects.SyncDeltaType;
-import org.identityconnectors.framework.common.objects.SyncResultsHandler;
-import org.quartz.JobExecutionException;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public abstract class AbstractSubjectSyncResultHandler extends AbstractSyncopeResultHandler<SyncTask, SyncActions>
- implements SyncResultsHandler {
-
- @Autowired
- protected SyncUtilities syncUtilities;
-
- @Autowired
- protected AttributableTransformer attrTransformer;
-
- protected abstract AttributableUtil getAttributableUtil();
-
- protected abstract String getName(AbstractSubjectTO subjectTO);
-
- protected abstract AbstractSubjectTO getSubjectTO(long key);
-
- protected abstract AbstractSubjectMod getSubjectMod(AbstractSubjectTO subjectTO, SyncDelta delta);
-
- protected abstract AbstractSubjectTO create(AbstractSubjectTO subjectTO, SyncDelta _delta, ProvisioningResult result);
-
- protected abstract AbstractSubjectTO link(AbstractSubjectTO before, ProvisioningResult result, boolean unlink);
-
- protected abstract AbstractSubjectTO update(AbstractSubjectTO before, AbstractSubjectMod subjectMod,
- SyncDelta delta, ProvisioningResult result);
-
- protected abstract void deprovision(Long key, boolean unlink);
-
- protected abstract void delete(Long key);
-
- @Override
- public boolean handle(final SyncDelta delta) {
- try {
- doHandle(delta, profile.getResults());
- return true;
- } catch (JobExecutionException e) {
- LOG.error("Synchronization failed", e);
- return false;
- }
- }
-
- protected List<ProvisioningResult> assign(final SyncDelta delta, final AttributableUtil attrUtil)
- throws JobExecutionException {
- if (!profile.getTask().isPerformCreate()) {
- LOG.debug("SyncTask not configured for create");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- final AbstractSubjectTO subjectTO =
- connObjectUtil.getSubjectTO(delta.getObject(), profile.getTask(), attrUtil);
-
- subjectTO.getResources().add(profile.getTask().getResource().getKey());
-
- final ProvisioningResult result = new ProvisioningResult();
- result.setOperation(ResourceOperation.CREATE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
-
- // Attributable transformation (if configured)
- AbstractSubjectTO transformed = attrTransformer.transform(subjectTO);
- LOG.debug("Transformed: {}", transformed);
-
- result.setName(getName(transformed));
-
- if (profile.isDryRun()) {
- result.setId(0L);
- } else {
- SyncDelta _delta = delta;
- for (SyncActions action : profile.getActions()) {
- _delta = action.beforeAssign(this.getProfile(), _delta, transformed);
- }
-
- create(transformed, _delta, attrUtil, "assign", result);
- }
-
- return Collections.singletonList(result);
- }
-
- protected List<ProvisioningResult> create(final SyncDelta delta, final AttributableUtil attrUtil)
- throws JobExecutionException {
-
- if (!profile.getTask().isPerformCreate()) {
- LOG.debug("SyncTask not configured for create");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- final AbstractSubjectTO subjectTO =
- connObjectUtil.getSubjectTO(delta.getObject(), profile.getTask(), attrUtil);
-
- // Attributable transformation (if configured)
- AbstractSubjectTO transformed = attrTransformer.transform(subjectTO);
- LOG.debug("Transformed: {}", transformed);
-
- final ProvisioningResult result = new ProvisioningResult();
- result.setOperation(ResourceOperation.CREATE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
-
- result.setName(getName(transformed));
-
- if (profile.isDryRun()) {
- result.setId(0L);
- } else {
- SyncDelta _delta = delta;
- for (SyncActions action : profile.getActions()) {
- _delta = action.beforeProvision(this.getProfile(), _delta, transformed);
- }
-
- create(transformed, _delta, attrUtil, "provision", result);
- }
-
- return Collections.<ProvisioningResult>singletonList(result);
- }
-
- private void create(
- final AbstractSubjectTO subjectTO,
- final SyncDelta delta,
- final AttributableUtil attrUtil,
- final String operation,
- final ProvisioningResult result)
- throws JobExecutionException {
-
- Object output;
- Result resultStatus;
-
- try {
- AbstractSubjectTO actual = create(subjectTO, delta, result);
- result.setName(getName(actual));
- output = actual;
- resultStatus = Result.SUCCESS;
-
- for (SyncActions action : profile.getActions()) {
- action.after(this.getProfile(), delta, actual, result);
- }
- } catch (PropagationException e) {
- // A propagation failure doesn't imply a synchronization failure.
- // The propagation exception status will be reported into the propagation task execution.
- LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- LOG.error("Could not create {} {} ", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- }
-
- audit(operation, resultStatus, null, output, delta);
- }
-
- protected List<ProvisioningResult> update(SyncDelta delta, final List<Long> subjects,
- final AttributableUtil attrUtil)
- throws JobExecutionException {
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("SyncTask not configured for update");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- LOG.debug("About to update {}", subjects);
-
- List<ProvisioningResult> updResults = new ArrayList<>();
-
- for (Long id : subjects) {
- LOG.debug("About to update {}", id);
-
- Object output;
- AbstractSubjectTO before = null;
- Result resultStatus;
-
- final ProvisioningResult result = new ProvisioningResult();
- result.setOperation(ResourceOperation.UPDATE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
- result.setId(id);
-
- before = getSubjectTO(id);
-
- if (before == null) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
- } else {
- result.setName(getName(before));
- }
-
- if (!profile.isDryRun()) {
- if (before == null) {
- resultStatus = Result.FAILURE;
- output = null;
- } else {
- try {
- final AbstractSubjectMod attributableMod = getSubjectMod(before, delta);
-
- // Attribute value transformation (if configured)
- final AbstractSubjectMod actual = attrTransformer.transform(attributableMod);
- LOG.debug("Transformed: {}", actual);
-
- for (SyncActions action : profile.getActions()) {
- delta = action.beforeUpdate(this.getProfile(), delta, before, attributableMod);
- }
-
- final AbstractSubjectTO updated = update(before, attributableMod, delta, result);
-
- for (SyncActions action : profile.getActions()) {
- action.after(this.getProfile(), delta, updated, result);
- }
-
- output = updated;
- resultStatus = Result.SUCCESS;
- result.setName(getName(updated));
- LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
- } catch (PropagationException e) {
- // A propagation failure doesn't imply a synchronization failure.
- // The propagation exception status will be reported into the propagation task execution.
- LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- }
- }
- audit("update", resultStatus, before, output, delta);
- }
- updResults.add(result);
- }
- return updResults;
- }
-
- protected List<ProvisioningResult> deprovision(
- SyncDelta delta,
- final List<Long> subjects,
- final AttributableUtil attrUtil,
- final boolean unlink)
- throws JobExecutionException {
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("SyncTask not configured for update");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- LOG.debug("About to update {}", subjects);
-
- final List<ProvisioningResult> updResults = new ArrayList<>();
-
- for (Long id : subjects) {
- LOG.debug("About to unassign resource {}", id);
-
- Object output;
- Result resultStatus;
-
- final ProvisioningResult result = new ProvisioningResult();
- result.setOperation(ResourceOperation.DELETE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
- result.setId(id);
-
- final AbstractSubjectTO before = getSubjectTO(id);
-
- if (before == null) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
- }
-
- if (!profile.isDryRun()) {
- if (before == null) {
- resultStatus = Result.FAILURE;
- output = null;
- } else {
- result.setName(getName(before));
-
- try {
- if (unlink) {
- for (SyncActions action : profile.getActions()) {
- action.beforeUnassign(this.getProfile(), delta, before);
- }
- } else {
- for (SyncActions action : profile.getActions()) {
- action.beforeDeprovision(this.getProfile(), delta, before);
- }
- }
-
- deprovision(id, unlink);
- output = getSubjectTO(id);
-
- for (SyncActions action : profile.getActions()) {
- action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
- }
-
- resultStatus = Result.SUCCESS;
- LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
- } catch (PropagationException e) {
- // A propagation failure doesn't imply a synchronization failure.
- // The propagation exception status will be reported into the propagation task execution.
- LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- }
- }
- audit(unlink ? "unassign" : "deprovision", resultStatus, before, output, delta);
- }
- updResults.add(result);
- }
-
- return updResults;
- }
-
- protected List<ProvisioningResult> link(
- SyncDelta delta,
- final List<Long> subjects,
- final AttributableUtil attrUtil,
- final boolean unlink)
- throws JobExecutionException {
-
- if (!profile.getTask().isPerformUpdate()) {
- LOG.debug("SyncTask not configured for update");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- LOG.debug("About to update {}", subjects);
-
- final List<ProvisioningResult> updResults = new ArrayList<>();
-
- for (Long id : subjects) {
- LOG.debug("About to unassign resource {}", id);
-
- Object output;
- Result resultStatus;
-
- final ProvisioningResult result = new ProvisioningResult();
- result.setOperation(ResourceOperation.NONE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
- result.setId(id);
-
- final AbstractSubjectTO before = getSubjectTO(id);
-
- if (before == null) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
- }
-
- if (!profile.isDryRun()) {
- if (before == null) {
- resultStatus = Result.FAILURE;
- output = null;
- } else {
- result.setName(getName(before));
-
- try {
- if (unlink) {
- for (SyncActions action : profile.getActions()) {
- action.beforeUnlink(this.getProfile(), delta, before);
- }
- } else {
- for (SyncActions action : profile.getActions()) {
- action.beforeLink(this.getProfile(), delta, before);
- }
- }
-
- output = link(before, result, unlink);
-
- for (SyncActions action : profile.getActions()) {
- action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
- }
-
- resultStatus = Result.SUCCESS;
- LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
- } catch (PropagationException e) {
- // A propagation failure doesn't imply a synchronization failure.
- // The propagation exception status will be reported into the propagation task execution.
- LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
- output = e;
- resultStatus = Result.FAILURE;
- }
- }
- audit(unlink ? "unlink" : "link", resultStatus, before, output, delta);
- }
- updResults.add(result);
- }
-
- return updResults;
- }
-
- protected List<ProvisioningResult> delete(
- SyncDelta delta, final List<Long> subjects, final AttributableUtil attrUtil)
- throws JobExecutionException {
-
- if (!profile.getTask().isPerformDelete()) {
- LOG.debug("SyncTask not configured for delete");
- return Collections.<ProvisioningResult>emptyList();
- }
-
- LOG.debug("About to delete {}", subjects);
-
- List<ProvisioningResult> delResults = new ArrayList<>();
-
- for (Long id : subjects) {
- Object output;
- Result resultStatus = Result.FAILURE;
-
- AbstractSubjectTO before = null;
- final ProvisioningResult result = new ProvisioningResult();
-
- try {
- before = getSubjectTO(id);
-
- result.setId(id);
- result.setName(getName(before));
- result.setOperation(ResourceOperation.DELETE);
- result.setSubjectType(attrUtil.getType());
- result.setStatus(ProvisioningResult.Status.SUCCESS);
-
- if (!profile.isDryRun()) {
- for (SyncActions action : profile.getActions()) {
- delta = action.beforeDelete(this.getProfile(), delta, before);
- }
-
- try {
- delete(id);
- output = null;
- resultStatus = Result.SUCCESS;
- } catch (Exception e) {
- result.setStatus(ProvisioningResult.Status.FAILURE);
- result.setMessage(ExceptionUtils.getRootCauseMessage(e));
- LOG.error("Could not delete {} {}", attrUtil.getType(), id, e);
- output = e;
- }
-
- for (SyncActions action : profile.getActions()) {
- action.after(this.getProfile(), delta, before, result);
- }
-
- audit("delete", resultStatus, before, output, delta);
- }
-
- delResults.add(result);
-
- } catch (NotFoundException e) {
- LOG.error("Could not find {} {}", attrUtil.getType(), id, e);
- } catch (UnauthorizedRoleException e) {
- LOG.error("Not allowed to read {} {}", attrUtil.getType(), id, e);
- } catch (Exception e) {
- LOG.error("Could not delete {} {}", attrUtil.getType(), id, e);
- }
- }
-
- return delResults;
- }
-
- /**
- * Look into SyncDelta and take necessary profile.getActions() (create / update / delete) on user(s)/role(s).
- *
- * @param delta returned by the underlying profile.getConnector()
- * @throws JobExecutionException in case of synchronization failure.
- */
- protected final void doHandle(final SyncDelta delta, final Collection<ProvisioningResult> syncResults)
- throws JobExecutionException {
-
- final AttributableUtil attrUtil = getAttributableUtil();
-
- LOG.debug("Process {} for {} as {}",
- delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
-
- final String uid = delta.getPreviousUid() == null
- ? delta.getUid().getUidValue()
- : delta.getPreviousUid().getUidValue();
-
- try {
- List<Long> subjectIds = syncUtilities.findExisting(
- uid, delta.getObject(), profile.getTask().getResource(), attrUtil);
-
- if (subjectIds.size() > 1) {
- switch (profile.getResAct()) {
- case IGNORE:
- throw new IllegalStateException("More than one match " + subjectIds);
-
- case FIRSTMATCH:
- subjectIds = subjectIds.subList(0, 1);
- break;
-
- case LASTMATCH:
- subjectIds = subjectIds.subList(subjectIds.size() - 1, subjectIds.size());
- break;
-
- default:
- // keep subjectIds as is
- }
- }
-
- if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
- if (subjectIds.isEmpty()) {
- switch (profile.getTask().getUnmatchingRule()) {
- case ASSIGN:
- profile.getResults().addAll(assign(delta, attrUtil));
- break;
- case PROVISION:
- profile.getResults().addAll(create(delta, attrUtil));
- break;
- default:
- // do nothing
- }
- } else {
- switch (profile.getTask().getMatchingRule()) {
- case UPDATE:
- profile.getResults().addAll(update(delta, subjectIds, attrUtil));
- break;
- case DEPROVISION:
- profile.getResults().addAll(deprovision(delta, subjectIds, attrUtil, false));
- break;
- case UNASSIGN:
- profile.getResults().addAll(deprovision(delta, subjectIds, attrUtil, true));
- break;
- case LINK:
- profile.getResults().addAll(link(delta, subjectIds, attrUtil, false));
- break;
- case UNLINK:
- profile.getResults().addAll(link(delta, subjectIds, attrUtil, true));
- break;
- default:
- // do nothing
- }
- }
- } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
- if (subjectIds.isEmpty()) {
- LOG.debug("No match found for deletion");
- } else {
- profile.getResults().addAll(delete(delta, subjectIds, attrUtil));
- }
- }
- } catch (IllegalStateException e) {
- LOG.warn(e.getMessage());
- } catch (IllegalArgumentException e) {
- LOG.warn(e.getMessage());
- }
- }
-
- private void audit(
- final String event,
- final Result result,
- final Object before,
- final Object output,
- final Object... input) {
-
- notificationManager.createTasks(
- AuditElements.EventCategoryType.SYNCHRONIZATION,
- getAttributableUtil().getType().name().toLowerCase(),
- profile.getTask().getResource().getKey(),
- event,
- result,
- before,
- output,
- input);
-
- auditManager.audit(
- AuditElements.EventCategoryType.SYNCHRONIZATION,
- getAttributableUtil().getType().name().toLowerCase(),
- profile.getTask().getResource().getKey(),
- event,
- result,
- before,
- output,
- input);
- }
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/80589a1b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSyncResultHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSyncResultHandler.java b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSyncResultHandler.java
new file mode 100644
index 0000000..83377f3
--- /dev/null
+++ b/syncope620/server/provisioning-java/src/main/java/org/apache/syncope/server/provisioning/java/sync/AbstractSyncResultHandler.java
@@ -0,0 +1,617 @@
+/*
+ * 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.server.provisioning.java.sync;
+
+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.mod.AbstractSubjectMod;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.AuditElements.Result;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.server.persistence.api.dao.NotFoundException;
+import org.apache.syncope.server.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.server.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.server.provisioning.api.AttributableTransformer;
+import org.apache.syncope.server.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.server.provisioning.api.sync.SyncActions;
+import org.apache.syncope.server.provisioning.api.sync.ProvisioningResult;
+import org.apache.syncope.server.misc.security.UnauthorizedRoleException;
+import org.apache.syncope.server.provisioning.api.sync.SyncopeSyncResultHandler;
+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;
+
+public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHandler<SyncTask, SyncActions>
+ implements SyncopeSyncResultHandler {
+
+ @Autowired
+ protected SyncUtilities syncUtilities;
+
+ @Autowired
+ protected AttributableTransformer attrTransformer;
+
+ protected abstract AttributableUtil getAttributableUtil();
+
+ protected abstract String getName(AbstractSubjectTO subjectTO);
+
+ protected abstract AbstractSubjectTO getSubjectTO(long key);
+
+ protected abstract AbstractSubjectMod getSubjectMod(AbstractSubjectTO subjectTO, SyncDelta delta);
+
+ protected abstract AbstractSubjectTO create(AbstractSubjectTO subjectTO, SyncDelta _delta, ProvisioningResult result);
+
+ protected abstract AbstractSubjectTO link(AbstractSubjectTO before, ProvisioningResult result, boolean unlink);
+
+ protected abstract AbstractSubjectTO update(AbstractSubjectTO before, AbstractSubjectMod subjectMod,
+ SyncDelta delta, ProvisioningResult result);
+
+ protected abstract void deprovision(Long key, boolean unlink);
+
+ protected abstract void delete(Long key);
+
+ @Override
+ public boolean handle(final SyncDelta delta) {
+ try {
+ doHandle(delta);
+ return true;
+ } catch (JobExecutionException e) {
+ LOG.error("Synchronization failed", e);
+ return false;
+ }
+ }
+
+ protected List<ProvisioningResult> assign(final SyncDelta delta, final AttributableUtil attrUtil)
+ throws JobExecutionException {
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("SyncTask not configured for create");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ final AbstractSubjectTO subjectTO =
+ connObjectUtil.getSubjectTO(delta.getObject(), profile.getTask(), attrUtil);
+
+ subjectTO.getResources().add(profile.getTask().getResource().getKey());
+
+ final ProvisioningResult result = new ProvisioningResult();
+ result.setOperation(ResourceOperation.CREATE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+
+ // Attributable transformation (if configured)
+ AbstractSubjectTO transformed = attrTransformer.transform(subjectTO);
+ LOG.debug("Transformed: {}", transformed);
+
+ result.setName(getName(transformed));
+
+ if (profile.isDryRun()) {
+ result.setId(0L);
+ } else {
+ SyncDelta _delta = delta;
+ for (SyncActions action : profile.getActions()) {
+ _delta = action.beforeAssign(this.getProfile(), _delta, transformed);
+ }
+
+ create(transformed, _delta, attrUtil, "assign", result);
+ }
+
+ return Collections.singletonList(result);
+ }
+
+ protected List<ProvisioningResult> create(final SyncDelta delta, final AttributableUtil attrUtil)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("SyncTask not configured for create");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ final AbstractSubjectTO subjectTO =
+ connObjectUtil.getSubjectTO(delta.getObject(), profile.getTask(), attrUtil);
+
+ // Attributable transformation (if configured)
+ AbstractSubjectTO transformed = attrTransformer.transform(subjectTO);
+ LOG.debug("Transformed: {}", transformed);
+
+ final ProvisioningResult result = new ProvisioningResult();
+ result.setOperation(ResourceOperation.CREATE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+
+ result.setName(getName(transformed));
+
+ if (profile.isDryRun()) {
+ result.setId(0L);
+ } else {
+ SyncDelta _delta = delta;
+ for (SyncActions action : profile.getActions()) {
+ _delta = action.beforeProvision(this.getProfile(), _delta, transformed);
+ }
+
+ create(transformed, _delta, attrUtil, "provision", result);
+ }
+
+ return Collections.<ProvisioningResult>singletonList(result);
+ }
+
+ private void create(
+ final AbstractSubjectTO subjectTO,
+ final SyncDelta delta,
+ final AttributableUtil attrUtil,
+ final String operation,
+ final ProvisioningResult result)
+ throws JobExecutionException {
+
+ Object output;
+ Result resultStatus;
+
+ try {
+ AbstractSubjectTO actual = create(subjectTO, delta, result);
+ result.setName(getName(actual));
+ output = actual;
+ resultStatus = Result.SUCCESS;
+
+ for (SyncActions action : profile.getActions()) {
+ action.after(this.getProfile(), delta, actual, result);
+ }
+ } catch (PropagationException e) {
+ // A propagation failure doesn't imply a synchronization failure.
+ // The propagation exception status will be reported into the propagation task execution.
+ LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not create {} {} ", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+
+ audit(operation, resultStatus, null, output, delta);
+ }
+
+ protected List<ProvisioningResult> update(SyncDelta delta, final List<Long> subjects,
+ final AttributableUtil attrUtil)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("SyncTask not configured for update");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ LOG.debug("About to update {}", subjects);
+
+ List<ProvisioningResult> results = new ArrayList<>();
+
+ for (Long key : subjects) {
+ LOG.debug("About to update {}", key);
+
+ final ProvisioningResult result = new ProvisioningResult();
+ result.setOperation(ResourceOperation.UPDATE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+ result.setId(key);
+
+ AbstractSubjectTO before = getSubjectTO(key);
+ if (before == null) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), key));
+ } else {
+ result.setName(getName(before));
+ }
+
+ Result resultStatus;
+ Object output;
+ if (!profile.isDryRun()) {
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ try {
+ final AbstractSubjectMod attributableMod = getSubjectMod(before, delta);
+
+ // Attribute value transformation (if configured)
+ final AbstractSubjectMod actual = attrTransformer.transform(attributableMod);
+ LOG.debug("Transformed: {}", actual);
+
+ for (SyncActions action : profile.getActions()) {
+ delta = action.beforeUpdate(this.getProfile(), delta, before, attributableMod);
+ }
+
+ final AbstractSubjectTO updated = update(before, attributableMod, delta, result);
+
+ for (SyncActions action : profile.getActions()) {
+ action.after(this.getProfile(), delta, updated, result);
+ }
+
+ output = updated;
+ resultStatus = Result.SUCCESS;
+ result.setName(getName(updated));
+ LOG.debug("{} {} successfully updated", attrUtil.getType(), key);
+ } catch (PropagationException e) {
+ // A propagation failure doesn't imply a synchronization failure.
+ // The propagation exception status will be reported into the propagation task execution.
+ LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ audit("update", resultStatus, before, output, delta);
+ }
+ results.add(result);
+ }
+ return results;
+ }
+
+ protected List<ProvisioningResult> deprovision(
+ SyncDelta delta,
+ final List<Long> subjects,
+ final AttributableUtil attrUtil,
+ final boolean unlink)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("SyncTask not configured for update");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ LOG.debug("About to update {}", subjects);
+
+ final List<ProvisioningResult> updResults = new ArrayList<>();
+
+ for (Long id : subjects) {
+ LOG.debug("About to unassign resource {}", id);
+
+ Object output;
+ Result resultStatus;
+
+ final ProvisioningResult result = new ProvisioningResult();
+ result.setOperation(ResourceOperation.DELETE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+ result.setId(id);
+
+ final AbstractSubjectTO before = getSubjectTO(id);
+
+ if (before == null) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
+ }
+
+ if (!profile.isDryRun()) {
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ result.setName(getName(before));
+
+ try {
+ if (unlink) {
+ for (SyncActions action : profile.getActions()) {
+ action.beforeUnassign(this.getProfile(), delta, before);
+ }
+ } else {
+ for (SyncActions action : profile.getActions()) {
+ action.beforeDeprovision(this.getProfile(), delta, before);
+ }
+ }
+
+ deprovision(id, unlink);
+ output = getSubjectTO(id);
+
+ for (SyncActions action : profile.getActions()) {
+ action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
+ }
+
+ resultStatus = Result.SUCCESS;
+ LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
+ } catch (PropagationException e) {
+ // A propagation failure doesn't imply a synchronization failure.
+ // The propagation exception status will be reported into the propagation task execution.
+ LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ audit(unlink ? "unassign" : "deprovision", resultStatus, before, output, delta);
+ }
+ updResults.add(result);
+ }
+
+ return updResults;
+ }
+
+ protected List<ProvisioningResult> link(
+ SyncDelta delta,
+ final List<Long> subjects,
+ final AttributableUtil attrUtil,
+ final boolean unlink)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("SyncTask not configured for update");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ LOG.debug("About to update {}", subjects);
+
+ final List<ProvisioningResult> updResults = new ArrayList<>();
+
+ for (Long id : subjects) {
+ LOG.debug("About to unassign resource {}", id);
+
+ Object output;
+ Result resultStatus;
+
+ final ProvisioningResult result = new ProvisioningResult();
+ result.setOperation(ResourceOperation.NONE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+ result.setId(id);
+
+ final AbstractSubjectTO before = getSubjectTO(id);
+
+ if (before == null) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
+ }
+
+ if (!profile.isDryRun()) {
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ result.setName(getName(before));
+
+ try {
+ if (unlink) {
+ for (SyncActions action : profile.getActions()) {
+ action.beforeUnlink(this.getProfile(), delta, before);
+ }
+ } else {
+ for (SyncActions action : profile.getActions()) {
+ action.beforeLink(this.getProfile(), delta, before);
+ }
+ }
+
+ output = link(before, result, unlink);
+
+ for (SyncActions action : profile.getActions()) {
+ action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
+ }
+
+ resultStatus = Result.SUCCESS;
+ LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
+ } catch (PropagationException e) {
+ // A propagation failure doesn't imply a synchronization failure.
+ // The propagation exception status will be reported into the propagation task execution.
+ LOG.error("Could not propagate {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ audit(unlink ? "unlink" : "link", resultStatus, before, output, delta);
+ }
+ updResults.add(result);
+ }
+
+ return updResults;
+ }
+
+ protected List<ProvisioningResult> delete(
+ SyncDelta delta, final List<Long> subjects, final AttributableUtil attrUtil)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformDelete()) {
+ LOG.debug("SyncTask not configured for delete");
+ return Collections.<ProvisioningResult>emptyList();
+ }
+
+ LOG.debug("About to delete {}", subjects);
+
+ List<ProvisioningResult> delResults = new ArrayList<>();
+
+ for (Long id : subjects) {
+ Object output;
+ Result resultStatus = Result.FAILURE;
+
+ AbstractSubjectTO before = null;
+ final ProvisioningResult result = new ProvisioningResult();
+
+ try {
+ before = getSubjectTO(id);
+
+ result.setId(id);
+ result.setName(getName(before));
+ result.setOperation(ResourceOperation.DELETE);
+ result.setSubjectType(attrUtil.getType());
+ result.setStatus(ProvisioningResult.Status.SUCCESS);
+
+ if (!profile.isDryRun()) {
+ for (SyncActions action : profile.getActions()) {
+ delta = action.beforeDelete(this.getProfile(), delta, before);
+ }
+
+ try {
+ delete(id);
+ output = null;
+ resultStatus = Result.SUCCESS;
+ } catch (Exception e) {
+ result.setStatus(ProvisioningResult.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not delete {} {}", attrUtil.getType(), id, e);
+ output = e;
+ }
+
+ for (SyncActions action : profile.getActions()) {
+ action.after(this.getProfile(), delta, before, result);
+ }
+
+ audit("delete", resultStatus, before, output, delta);
+ }
+
+ delResults.add(result);
+
+ } catch (NotFoundException e) {
+ LOG.error("Could not find {} {}", attrUtil.getType(), id, e);
+ } catch (UnauthorizedRoleException e) {
+ LOG.error("Not allowed to read {} {}", attrUtil.getType(), id, e);
+ } catch (Exception e) {
+ LOG.error("Could not delete {} {}", attrUtil.getType(), id, e);
+ }
+ }
+
+ return delResults;
+ }
+
+ /**
+ * Look into SyncDelta and take necessary profile.getActions() (create / update / delete) on user(s)/role(s).
+ *
+ * @param delta returned by the underlying profile.getConnector()
+ * @throws JobExecutionException in case of synchronization failure.
+ */
+ protected final void doHandle(final SyncDelta delta)
+ throws JobExecutionException {
+
+ final AttributableUtil attrUtil = getAttributableUtil();
+
+ LOG.debug("Process {} for {} as {}",
+ delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
+
+ final String uid = delta.getPreviousUid() == null
+ ? delta.getUid().getUidValue()
+ : delta.getPreviousUid().getUidValue();
+
+ try {
+ List<Long> subjectKeys = syncUtilities.findExisting(
+ uid, delta.getObject(), profile.getTask().getResource(), attrUtil);
+
+ if (subjectKeys.size() > 1) {
+ switch (profile.getResAct()) {
+ case IGNORE:
+ throw new IllegalStateException("More than one match " + subjectKeys);
+
+ case FIRSTMATCH:
+ subjectKeys = subjectKeys.subList(0, 1);
+ break;
+
+ case LASTMATCH:
+ subjectKeys = subjectKeys.subList(subjectKeys.size() - 1, subjectKeys.size());
+ break;
+
+ default:
+ // keep subjectIds as is
+ }
+ }
+
+ if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+ if (subjectKeys.isEmpty()) {
+ switch (profile.getTask().getUnmatchingRule()) {
+ case ASSIGN:
+ profile.getResults().addAll(assign(delta, attrUtil));
+ break;
+ case PROVISION:
+ profile.getResults().addAll(create(delta, attrUtil));
+ break;
+ default:
+ // do nothing
+ }
+ } else {
+ switch (profile.getTask().getMatchingRule()) {
+ case UPDATE:
+ profile.getResults().addAll(update(delta, subjectKeys, attrUtil));
+ break;
+ case DEPROVISION:
+ profile.getResults().addAll(deprovision(delta, subjectKeys, attrUtil, false));
+ break;
+ case UNASSIGN:
+ profile.getResults().addAll(deprovision(delta, subjectKeys, attrUtil, true));
+ break;
+ case LINK:
+ profile.getResults().addAll(link(delta, subjectKeys, attrUtil, false));
+ break;
+ case UNLINK:
+ profile.getResults().addAll(link(delta, subjectKeys, attrUtil, true));
+ break;
+ default:
+ // do nothing
+ }
+ }
+ } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+ if (subjectKeys.isEmpty()) {
+ LOG.debug("No match found for deletion");
+ } else {
+ profile.getResults().addAll(delete(delta, subjectKeys, attrUtil));
+ }
+ }
+ } catch (IllegalStateException | IllegalArgumentException e) {
+ LOG.warn(e.getMessage());
+ }
+ }
+
+ private void audit(
+ final String event,
+ final Result result,
+ final Object before,
+ final Object output,
+ final Object... input) {
+
+ notificationManager.createTasks(
+ AuditElements.EventCategoryType.SYNCHRONIZATION,
+ getAttributableUtil().getType().name().toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ event,
+ result,
+ before,
+ output,
+ input);
+
+ auditManager.audit(
+ AuditElements.EventCategoryType.SYNCHRONIZATION,
+ getAttributableUtil().getType().name().toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ event,
+ result,
+ before,
+ output,
+ input);
+ }
+}