You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2014/06/26 14:18:30 UTC

svn commit: r1605756 - in /syncope/trunk/core/src/main/java/org/apache/syncope/core: propagation/impl/ sync/ sync/impl/ workflow/user/activiti/

Author: fmartelli
Date: Thu Jun 26 12:18:30 2014
New Revision: 1605756

URL: http://svn.apache.org/r1605756
Log:
[SYNCOPE-392] removed controllers from result handlers

Modified:
    syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncProfile.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncUtilities.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectPushResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectSyncResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSyncopeResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/PushJob.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RolePushResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RoleSyncResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserPushResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java Thu Jun 26 12:18:30 2014
@@ -133,7 +133,27 @@ public class PropagationManager {
             final Set<String> noPropResourceNames, final List<MembershipTO> membershipTOs)
             throws NotFoundException, UnauthorizedRoleException {
 
-        SyncopeUser user = userDataBinder.getUserFromId(wfResult.getResult().getKey());
+        return getUserCreateTaskIds(
+                wfResult.getResult().getKey(),
+                wfResult.getResult().getValue(),
+                wfResult.getPropByRes(),
+                password,
+                vAttrs,
+                membershipTOs,
+                noPropResourceNames);
+    }
+
+    public List<PropagationTask> getUserCreateTaskIds(
+            final Long id,
+            final Boolean enabled,
+            final PropagationByResource propByRes,
+            final String password,
+            final Collection<AttributeTO> vAttrs,
+            final Collection<MembershipTO> membershipTOs,
+            final Collection<String> noPropResourceNames)
+            throws NotFoundException, UnauthorizedRoleException {
+
+        SyncopeUser user = userDataBinder.getUserFromId(id);
         if (vAttrs != null && !vAttrs.isEmpty()) {
             userDataBinder.fillVirtual(user, vAttrs, AttributableUtil.getInstance(AttributableType.USER));
 
@@ -148,8 +168,7 @@ public class PropagationManager {
                 }
             }
         }
-        return getCreateTaskIds(user, password,
-                wfResult.getResult().getValue(), wfResult.getPropByRes(), noPropResourceNames);
+        return getCreateTaskIds(user, password, enabled, propByRes, noPropResourceNames);
     }
 
     /**
@@ -178,21 +197,44 @@ public class PropagationManager {
      * @throws NotFoundException if role is not found
      * @throws UnauthorizedRoleException if caller doesn't own enough entitlements to administer the given role
      */
-    public List<PropagationTask> getRoleCreateTaskIds(final WorkflowResult<Long> wfResult,
-            final Collection<AttributeTO> vAttrs, final Set<String> noPropResourceNames)
+    public List<PropagationTask> getRoleCreateTaskIds(
+            final WorkflowResult<Long> wfResult,
+            final Collection<AttributeTO> vAttrs,
+            final Collection<String> noPropResourceNames)
             throws NotFoundException, UnauthorizedRoleException {
+        return getRoleCreateTaskIds(wfResult.getResult(), vAttrs, wfResult.getPropByRes(), noPropResourceNames);
+    }
 
-        SyncopeRole role = roleDataBinder.getRoleFromId(wfResult.getResult());
+    /**
+     * Create the role on every associated resource.
+     *
+     * @param id role id
+     * @param vAttrs virtual attributes to be set
+     * @param propByRes operation to be performed per resource
+     * @param noPropResourceNames external resources performing not to be considered for propagation
+     * @return list of propagation tasks
+     * @throws NotFoundException if role is not found
+     * @throws UnauthorizedRoleException if caller doesn't own enough entitlements to administer the given role
+     */
+    public List<PropagationTask> getRoleCreateTaskIds(
+            final Long id,
+            final Collection<AttributeTO> vAttrs,
+            final PropagationByResource propByRes,
+            final Collection<String> noPropResourceNames)
+            throws NotFoundException, UnauthorizedRoleException {
+
+        SyncopeRole role = roleDataBinder.getRoleFromId(id);
         if (vAttrs != null && !vAttrs.isEmpty()) {
             roleDataBinder.fillVirtual(role, vAttrs, AttributableUtil.getInstance(AttributableType.ROLE));
         }
 
-        return getCreateTaskIds(role, null, null, wfResult.getPropByRes(), noPropResourceNames);
+        return getCreateTaskIds(role, null, null, propByRes, noPropResourceNames);
     }
 
     protected List<PropagationTask> getCreateTaskIds(final AbstractSubject subject,
             final String password, final Boolean enable,
-            final PropagationByResource propByRes, final Set<String> noPropResourceNames) {
+            final PropagationByResource propByRes,
+            final Collection<String> noPropResourceNames) {
 
         if (propByRes == null || propByRes.isEmpty()) {
             return Collections.<PropagationTask>emptyList();
@@ -361,7 +403,7 @@ public class PropagationManager {
                                 : membershipMod.getVirAttrsToRemove(),
                                 membershipMod.getVirAttrsToUpdate() == null ? Collections.<AttributeMod>emptySet()
                                 : membershipMod.getVirAttrsToUpdate(), AttributableUtil.getInstance(
-                                        AttributableType.MEMBERSHIP));
+                                AttributableType.MEMBERSHIP));
                     }
                 }
             }
@@ -679,7 +721,7 @@ public class PropagationManager {
         return tasks;
     }
 
-    private MembershipTO findMembershipTO(final Membership membership, final List<MembershipTO> memberships) {
+    private MembershipTO findMembershipTO(final Membership membership, final Collection<MembershipTO> memberships) {
         for (MembershipTO membershipTO : memberships) {
             if (membershipTO.getRoleId() == membership.getSyncopeRole().getId()) {
                 return membershipTO;

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncProfile.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncProfile.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncProfile.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncProfile.java Thu Jun 26 12:18:30 2014
@@ -23,8 +23,6 @@ import java.util.List;
 import org.apache.syncope.common.types.ConflictResolutionAction;
 import org.apache.syncope.core.persistence.beans.AbstractSyncTask;
 import org.apache.syncope.core.propagation.Connector;
-import org.apache.syncope.core.sync.AbstractSyncActions;
-import org.apache.syncope.core.sync.SyncResult;
 
 public class SyncProfile<T extends AbstractSyncTask, A extends AbstractSyncActions<?>> {
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncUtilities.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncUtilities.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncUtilities.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/SyncUtilities.java Thu Jun 26 12:18:30 2014
@@ -47,7 +47,6 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.dao.search.SubjectCond;
 import org.apache.syncope.core.persistence.validation.attrvalue.ParsingValidationException;
 import org.apache.syncope.core.propagation.Connector;
-import org.apache.syncope.core.sync.SyncCorrelationRule;
 import org.apache.syncope.core.util.AttributableUtil;
 import org.apache.syncope.core.util.EntitlementUtil;
 import org.identityconnectors.framework.common.objects.Attribute;

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectPushResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectPushResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectPushResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectPushResultHandler.java Thu Jun 26 12:18:30 2014
@@ -19,36 +19,54 @@
 package org.apache.syncope.core.sync.impl;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.syncope.common.to.AbstractSubjectTO;
 import org.apache.syncope.common.types.AttributableType;
 import org.apache.syncope.common.types.AuditElements;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.core.persistence.beans.AbstractSubject;
-import org.apache.syncope.core.persistence.beans.AbstractMappingItem;
 import org.apache.syncope.core.persistence.beans.PushTask;
-import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
-import org.apache.syncope.core.propagation.TimeoutException;
-import org.apache.syncope.core.propagation.impl.AbstractPropagationTaskExecutor;
-import org.apache.syncope.core.rest.controller.AbstractSubjectController;
 import org.apache.syncope.core.sync.PushActions;
 import org.apache.syncope.core.sync.SyncResult;
 import org.apache.syncope.core.util.AttributableUtil;
 import org.apache.syncope.core.util.MappingUtil;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.identityconnectors.framework.common.objects.ObjectClass;
-import org.identityconnectors.framework.common.objects.Uid;
 import org.quartz.JobExecutionException;
 import org.springframework.transaction.annotation.Transactional;
 
 public abstract class AbstractSubjectPushResultHandler extends AbstractSyncopeResultHandler<PushTask, PushActions> {
 
+    protected abstract String getName(final AbstractSubject subject);
+
+    protected abstract AbstractSubjectTO getSubjectTO(final long id);
+
+    protected abstract AbstractSubject getSubject(final long id);
+
+    protected abstract AbstractSubject deprovision(final AbstractSubject sbj, final SyncResult result);
+
+    protected abstract AbstractSubject provision(
+            final AbstractSubject sbj, final Boolean enabled, final SyncResult result);
+
+    protected abstract AbstractSubject link(final AbstractSubject sbj, final Boolean unlink, final SyncResult result);
+
+    protected abstract AbstractSubject unassign(final AbstractSubject sbj, final SyncResult result);
+
+    protected abstract AbstractSubject assign(final AbstractSubject sbj, Boolean enabled, final SyncResult result);
+
+    protected abstract AbstractSubject update(
+            final AbstractSubject sbj,
+            final String accountId,
+            final Set<Attribute> attributes,
+            final ConnectorObject beforeObj,
+            final SyncResult result);
+
+    protected abstract ConnectorObject getRemoteObject(final String accountId);
+
     @Transactional
     public boolean handle(final AbstractSubject subject) {
         try {
@@ -67,32 +85,20 @@ public abstract class AbstractSubjectPus
             profile.setResults(new ArrayList<SyncResult>());
         }
 
-        final AttributableUtil attrUtil = AttributableUtil.getInstance(subject);
+        final AbstractSubject toBeHandled = getSubject(subject.getId());
+        
+        final AttributableUtil attrUtil = AttributableUtil.getInstance(toBeHandled);
 
         final SyncResult result = new SyncResult();
         profile.getResults().add(result);
 
-        result.setId(subject.getId());
+        result.setId(toBeHandled.getId());
         result.setSubjectType(attrUtil.getType());
 
-        final AbstractSubjectController<?, ?> controller;
-        final AbstractSubject toBeHandled;
-
-        final Boolean enabled;
-
-        if (attrUtil.getType() == AttributableType.USER) {
-            toBeHandled = userDataBinder.getUserFromId(subject.getId());
-            result.setName(((SyncopeUser) toBeHandled).getUsername());
-            enabled = profile.getSyncTask().isSyncStatus()
-                    ? ((SyncopeUser) toBeHandled).isSuspended() ? Boolean.FALSE : Boolean.TRUE
-                    : null;
-            controller = userController;
-        } else {
-            toBeHandled = roleDataBinder.getRoleFromId(subject.getId());
-            result.setName(((SyncopeRole) toBeHandled).getName());
-            enabled = null;
-            controller = roleController;
-        }
+        result.setName(getName(toBeHandled));
+        final Boolean enabled = toBeHandled instanceof SyncopeUser && profile.getSyncTask().isSyncStatus()
+                ? ((SyncopeUser) toBeHandled).isSuspended() ? Boolean.FALSE : Boolean.TRUE
+                : null;
 
         LOG.debug("Propagating {} with ID {} towards {}",
                 attrUtil.getType(), toBeHandled.getId(), profile.getSyncTask().getResource());
@@ -117,11 +123,8 @@ public abstract class AbstractSubjectPus
                     enabled, // propagate status (suspended or not) if required
                     profile.getSyncTask().getResource()); // target external resource
 
-            final ObjectClass oclass =
-                    attrUtil.getType() == AttributableType.USER ? ObjectClass.ACCOUNT : ObjectClass.GROUP;
-
             // Try to read remote object (user / group) BEFORE any actual operation
-            beforeObj = getRemoteObject(oclass, values.getKey(), profile.getSyncTask().getResource().getName());
+            beforeObj = getRemoteObject(values.getKey());
 
             if (beforeObj == null) {
                 operation = profile.getSyncTask().getUnmatchigRule().name().toLowerCase();
@@ -131,27 +134,21 @@ public abstract class AbstractSubjectPus
                         for (PushActions action : profile.getActions()) {
                             action.beforeAssign(this.getProfile(), values, toBeHandled);
                         }
-                        controller.assign(
-                                toBeHandled.getId(),
-                                Collections.singleton(profile.getSyncTask().getResource().getName()), true, null);
+                        assign(toBeHandled, enabled, result);
                         break;
                     case PROVISION:
                         result.setOperation(ResourceOperation.CREATE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeProvision(this.getProfile(), values, toBeHandled);
                         }
-                        controller.provision(
-                                toBeHandled.getId(),
-                                Collections.singleton(profile.getSyncTask().getResource().getName()), true, null);
+                        provision(toBeHandled, enabled, result);
                         break;
                     case UNLINK:
                         result.setOperation(ResourceOperation.NONE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeUnlink(this.getProfile(), values, toBeHandled);
                         }
-                        controller.unlink(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
+                        link(toBeHandled, false, result);
                         break;
                     default:
                     // do nothing
@@ -165,56 +162,35 @@ public abstract class AbstractSubjectPus
                         for (PushActions action : profile.getActions()) {
                             action.beforeUpdate(this.getProfile(), values, toBeHandled);
                         }
-
-                        AbstractPropagationTaskExecutor.createOrUpdate(
-                                oclass,
-                                values.getKey(),
-                                values.getValue(),
-                                profile.getSyncTask().getResource().getName(),
-                                profile.getSyncTask().getResource().getPropagationMode(),
-                                beforeObj,
-                                profile.getConnector(),
-                                new HashSet<String>(),
-                                connObjectUtil);
+                        update(toBeHandled, values.getKey(), values.getValue(), beforeObj, result);
                         break;
                     case DEPROVISION:
                         result.setOperation(ResourceOperation.DELETE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeDeprovision(this.getProfile(), values, toBeHandled);
                         }
-                        controller.deprovision(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
+                        deprovision(toBeHandled, result);
                         break;
                     case UNASSIGN:
                         result.setOperation(ResourceOperation.DELETE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeUnassign(this.getProfile(), values, toBeHandled);
                         }
-                        controller.unlink(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
-                        controller.deprovision(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
+                        unassign(toBeHandled, result);
                         break;
                     case LINK:
                         result.setOperation(ResourceOperation.NONE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeLink(this.getProfile(), values, toBeHandled);
                         }
-                        controller.link(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
+                        link(toBeHandled, true, result);
                         break;
                     case UNLINK:
                         result.setOperation(ResourceOperation.NONE);
                         for (PushActions action : profile.getActions()) {
                             action.beforeUnlink(this.getProfile(), values, toBeHandled);
                         }
-                        controller.unlink(
-                                toBeHandled.getId(), Collections.
-                                singleton(profile.getSyncTask().getResource().getName()));
+                        link(toBeHandled, false, result);
                         break;
                     default:
                     // do nothing
@@ -223,7 +199,7 @@ public abstract class AbstractSubjectPus
 
             result.setStatus(SyncResult.Status.SUCCESS);
             resultStatus = AuditElements.Result.SUCCESS;
-            output = getRemoteObject(oclass, values.getKey(), profile.getSyncTask().getResource().getName());
+            output = getRemoteObject(values.getKey());
         } catch (Exception e) {
             result.setStatus(SyncResult.Status.FAILURE);
             result.setMessage(ExceptionUtils.getRootCauseMessage(e));
@@ -256,26 +232,4 @@ public abstract class AbstractSubjectPus
                     toBeHandled);
         }
     }
-
-    private ConnectorObject getRemoteObject(
-            final ObjectClass oclass, final String accountId, final String resource) {
-        ConnectorObject obj = null;
-
-        try {
-
-            final Uid uid = new Uid(accountId);
-
-            profile.getConnector().getObject(
-                    oclass,
-                    uid,
-                    profile.getConnector().getOperationOptions(Collections.<AbstractMappingItem>emptySet()));
-
-        } catch (TimeoutException toe) {
-            LOG.debug("Request timeout", toe);
-            throw toe;
-        } catch (RuntimeException ignore) {
-            LOG.debug("While resolving {}", accountId, ignore);
-        }
-        return obj;
-    }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectSyncResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectSyncResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectSyncResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSubjectSyncResultHandler.java Thu Jun 26 12:18:30 2014
@@ -29,9 +29,6 @@ import java.util.List;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.syncope.common.mod.AbstractSubjectMod;
 import org.apache.syncope.common.to.AbstractSubjectTO;
-import org.apache.syncope.common.to.RoleTO;
-import org.apache.syncope.common.to.UserTO;
-import org.apache.syncope.common.types.AttributableType;
 import org.apache.syncope.common.types.AuditElements;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.ResourceOperation;
@@ -39,9 +36,6 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.persistence.dao.NotFoundException;
 import org.apache.syncope.core.persistence.dao.UserDAO;
 import org.apache.syncope.core.propagation.PropagationException;
-import org.apache.syncope.core.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.propagation.impl.PropagationManager;
-import org.apache.syncope.core.rest.controller.AbstractSubjectController;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
 import org.apache.syncope.core.rest.data.AttributableTransformer;
 import org.apache.syncope.core.sync.SyncActions;
@@ -60,12 +54,6 @@ public abstract class AbstractSubjectSyn
     protected SyncUtilities syncUtilities;
 
     @Autowired
-    protected PropagationManager propagationManager;
-
-    @Autowired
-    protected PropagationTaskExecutor taskExecutor;
-
-    @Autowired
     protected AttributableTransformer attrTransformer;
 
     @Autowired
@@ -87,6 +75,12 @@ public abstract class AbstractSubjectSyn
             final SyncDelta _delta,
             final SyncResult result);
 
+    protected abstract AbstractSubjectTO link(
+            final AbstractSubjectTO before,
+            final SyncResult result,
+            final boolean unlink)
+            throws Exception;
+
     protected abstract AbstractSubjectTO update(
             final AbstractSubjectTO before,
             final AbstractSubjectMod subjectMod,
@@ -94,6 +88,8 @@ public abstract class AbstractSubjectSyn
             final SyncResult result)
             throws Exception;
 
+    protected abstract void deprovision(final Long id, final boolean unlink) throws Exception;
+
     protected abstract void delete(final Long id);
 
     @Override
@@ -175,6 +171,7 @@ public abstract class AbstractSubjectSyn
 
             try {
                 actual = create(actual, _delta, result);
+                result.setName(getName(actual));
                 output = actual;
                 resultStatus = Result.SUCCESS;
             } catch (PropagationException e) {
@@ -195,25 +192,7 @@ public abstract class AbstractSubjectSyn
                 action.after(this.getProfile(), _delta, actual, result);
             }
 
-            notificationManager.createTasks(
-                    AuditElements.EventCategoryType.SYNCHRONIZATION,
-                    AttributableType.USER.name().toLowerCase(),
-                    profile.getSyncTask().getResource().getName(),
-                    operation,
-                    resultStatus,
-                    null,
-                    output,
-                    _delta);
-
-            auditManager.audit(
-                    AuditElements.EventCategoryType.SYNCHRONIZATION,
-                    AttributableType.USER.name().toLowerCase(),
-                    profile.getSyncTask().getResource().getName(),
-                    operation,
-                    resultStatus,
-                    null,
-                    output,
-                    _delta);
+            audit(operation, resultStatus, null, output, _delta);
         }
 
         return Collections.singletonList(result);
@@ -245,73 +224,59 @@ public abstract class AbstractSubjectSyn
             result.setStatus(SyncResult.Status.SUCCESS);
             result.setId(id);
 
-            try {
-                before = userDataBinder.getUserTO(id);
+            before = getSubjectTO(id);
 
-                if (dryRun) {
-                    output = before;
+            if (before == null) {
+                result.setStatus(SyncResult.Status.FAILURE);
+                result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
+            } else {
+                result.setName(getName(before));
+            }
+
+            if (!dryRun) {
+                if (before == null) {
+                    resultStatus = Result.FAILURE;
+                    output = null;
                 } else {
+                    try {
+                        final AbstractSubjectMod attributableMod = getSubjectMod(before, delta);
 
-                    final AbstractSubjectMod attributableMod = getSubjectMod(before, delta);
+                        // Attribute value transformation (if configured)
+                        final AbstractSubjectMod actual = attrTransformer.transform(attributableMod);
+                        LOG.debug("Transformed: {}", actual);
 
-                    // 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);
+                        }
 
-                    for (SyncActions action : profile.getActions()) {
-                        delta = action.beforeUpdate(this.getProfile(), delta, before, attributableMod);
-                    }
+                        final AbstractSubjectTO updated = update(before, attributableMod, delta, result);
 
-                    final AbstractSubjectTO updated = update(before, attributableMod, delta, result);
+                        for (SyncActions action : profile.getActions()) {
+                            action.after(this.getProfile(), delta, updated, 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(SyncResult.Status.FAILURE);
+                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+                        LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+                        output = e;
+                        resultStatus = Result.FAILURE;
                     }
-
-                    output = updated;
                 }
-
-                resultStatus = Result.SUCCESS;
-            } 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(SyncResult.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);
-
-            if (!dryRun) {
-                notificationManager.createTasks(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        "update",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-
-                auditManager.audit(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        "update",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-            }
-
-            LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
         }
-
         return updResults;
     }
 
@@ -332,13 +297,6 @@ public abstract class AbstractSubjectSyn
 
         final List<SyncResult> updResults = new ArrayList<SyncResult>();
 
-        final AbstractSubjectController<?, ?> controller;
-        if (AttributableType.USER == attrUtil.getType()) {
-            controller = userController;
-        } else {
-            controller = roleController;
-        }
-
         for (Long id : subjects) {
             LOG.debug("About to unassign resource {}", id);
 
@@ -351,74 +309,57 @@ public abstract class AbstractSubjectSyn
             result.setStatus(SyncResult.Status.SUCCESS);
             result.setId(id);
 
-            final AbstractSubjectTO before = controller.read(id);
-            result.setName(before instanceof UserTO ? UserTO.class.cast(before).getUsername()
-                    : before instanceof RoleTO ? RoleTO.class.cast(before).getName() : null);
+            final AbstractSubjectTO before = getSubjectTO(id);
 
-            try {
-                if (!dryRun) {
-                    if (unlink) {
-                        for (SyncActions action : profile.getActions()) {
-                            action.beforeUnassign(this.getProfile(), delta, before);
+            if (before == null) {
+                result.setStatus(SyncResult.Status.FAILURE);
+                result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
+            }
+
+            if (!dryRun) {
+                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);
+                            }
                         }
-                        controller.unlink(
-                                id, Collections.<String>singleton(profile.getSyncTask().getResource().getName()));
-                    } else {
+
+                        deprovision(id, unlink);
+                        output = getSubjectTO(id);
+
                         for (SyncActions action : profile.getActions()) {
-                            action.beforeDeprovision(this.getProfile(), delta, before);
+                            action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
                         }
-                    }
 
-                    controller.deprovision(
-                            id, Collections.<String>singleton(profile.getSyncTask().getResource().getName()));
-
-                    output = controller.read(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(SyncResult.Status.FAILURE);
+                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+                        LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+                        output = e;
+                        resultStatus = Result.FAILURE;
                     }
-                } else {
-                    output = before;
                 }
-
-                resultStatus = Result.SUCCESS;
-            } 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(SyncResult.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);
-
-            if (!dryRun) {
-                notificationManager.createTasks(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        unlink ? "unassign" : "deprovision",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-
-                auditManager.audit(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        unlink ? "unassign" : "deprovision",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-            }
-
-            LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
         }
 
         return updResults;
@@ -441,13 +382,6 @@ public abstract class AbstractSubjectSyn
 
         final List<SyncResult> updResults = new ArrayList<SyncResult>();
 
-        final AbstractSubjectController<?, ?> controller;
-        if (AttributableType.USER == attrUtil.getType()) {
-            controller = userController;
-        } else {
-            controller = roleController;
-        }
-
         for (Long id : subjects) {
             LOG.debug("About to unassign resource {}", id);
 
@@ -460,73 +394,56 @@ public abstract class AbstractSubjectSyn
             result.setStatus(SyncResult.Status.SUCCESS);
             result.setId(id);
 
-            final AbstractSubjectTO before = controller.read(id);
-            result.setName(before instanceof UserTO ? UserTO.class.cast(before).getUsername()
-                    : before instanceof RoleTO ? RoleTO.class.cast(before).getName() : null);
+            final AbstractSubjectTO before = getSubjectTO(id);
 
-            try {
-                if (!dryRun) {
-                    if (unlink) {
-                        for (SyncActions action : profile.getActions()) {
-                            action.beforeUnlink(this.getProfile(), delta, before);
+            if (before == null) {
+                result.setStatus(SyncResult.Status.FAILURE);
+                result.setMessage(String.format("Subject '%s(%d)' not found", attrUtil.getType().name(), id));
+            }
+
+            if (!dryRun) {
+                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);
+                            }
                         }
-                        controller.unlink(
-                                id, Collections.<String>singleton(profile.getSyncTask().getResource().getName()));
-                    } else {
+
+                        output = link(before, result, unlink);
+
                         for (SyncActions action : profile.getActions()) {
-                            action.beforeLink(this.getProfile(), delta, before);
+                            action.after(this.getProfile(), delta, AbstractSubjectTO.class.cast(output), result);
                         }
-                        controller.link(
-                                id, Collections.<String>singleton(profile.getSyncTask().getResource().getName()));
-                    }
 
-                    output = controller.read(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(SyncResult.Status.FAILURE);
+                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+                        LOG.error("Could not update {} {}", attrUtil.getType(), delta.getUid().getUidValue(), e);
+                        output = e;
+                        resultStatus = Result.FAILURE;
                     }
-                } else {
-                    output = before;
                 }
-
-                resultStatus = Result.SUCCESS;
-            } 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(SyncResult.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);
-
-            if (!dryRun) {
-                notificationManager.createTasks(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        unlink ? "unlink" : "link",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-
-                auditManager.audit(
-                        AuditElements.EventCategoryType.SYNCHRONIZATION,
-                        attrUtil.getType().name().toLowerCase(),
-                        profile.getSyncTask().getResource().getName(),
-                        unlink ? "unlink" : "link",
-                        resultStatus,
-                        before,
-                        output,
-                        delta);
-            }
-
-            LOG.debug("{} {} successfully updated", attrUtil.getType(), id);
         }
 
         return updResults;
@@ -556,12 +473,7 @@ public abstract class AbstractSubjectSyn
                 before = getSubjectTO(id);
 
                 result.setId(id);
-                if (before instanceof UserTO) {
-                    result.setName(((UserTO) before).getUsername());
-                }
-                if (before instanceof RoleTO) {
-                    result.setName(((RoleTO) before).getName());
-                }
+                result.setName(getName(before));
                 result.setOperation(ResourceOperation.DELETE);
                 result.setSubjectType(attrUtil.getType());
                 result.setStatus(SyncResult.Status.SUCCESS);
@@ -586,25 +498,7 @@ public abstract class AbstractSubjectSyn
                         action.after(this.getProfile(), delta, before, result);
                     }
 
-                    notificationManager.createTasks(
-                            AuditElements.EventCategoryType.SYNCHRONIZATION,
-                            attrUtil.getType().name().toLowerCase(),
-                            profile.getSyncTask().getResource().getName(),
-                            "delete",
-                            resultStatus,
-                            before,
-                            output,
-                            delta);
-
-                    auditManager.audit(
-                            AuditElements.EventCategoryType.SYNCHRONIZATION,
-                            attrUtil.getType().name().toLowerCase(),
-                            profile.getSyncTask().getResource().getName(),
-                            "delete",
-                            resultStatus,
-                            before,
-                            output,
-                            delta);
+                    audit("delete", resultStatus, before, output, delta);
                 }
 
                 delResults.add(result);
@@ -707,4 +601,32 @@ public abstract class AbstractSubjectSyn
             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.getSyncTask().getResource().getName(),
+                event,
+                result,
+                before,
+                output,
+                input);
+
+        auditManager.audit(
+                AuditElements.EventCategoryType.SYNCHRONIZATION,
+                getAttributableUtil().getType().name().toLowerCase(),
+                profile.getSyncTask().getResource().getName(),
+                event,
+                result,
+                before,
+                output,
+                input);
+    }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSyncopeResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSyncopeResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSyncopeResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/AbstractSyncopeResultHandler.java Thu Jun 26 12:18:30 2014
@@ -23,8 +23,8 @@ import org.apache.syncope.core.audit.Aud
 import org.apache.syncope.core.connid.ConnObjectUtil;
 import org.apache.syncope.core.notification.NotificationManager;
 import org.apache.syncope.core.persistence.beans.AbstractSyncTask;
-import org.apache.syncope.core.rest.controller.RoleController;
-import org.apache.syncope.core.rest.controller.UserController;
+import org.apache.syncope.core.propagation.PropagationTaskExecutor;
+import org.apache.syncope.core.propagation.impl.PropagationManager;
 import org.apache.syncope.core.rest.data.RoleDataBinder;
 import org.apache.syncope.core.rest.data.UserDataBinder;
 import org.apache.syncope.core.sync.AbstractSyncActions;
@@ -41,12 +41,6 @@ public abstract class AbstractSyncopeRes
      */
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractSyncopeResultHandler.class);
 
-    @Autowired
-    protected UserController userController;
-
-    @Autowired
-    protected RoleController roleController;
-
     /**
      * User data binder.
      */
@@ -78,6 +72,18 @@ public abstract class AbstractSyncopeRes
     protected AuditManager auditManager;
 
     /**
+     * Propagation manager.
+     */
+    @Autowired
+    protected PropagationManager propagationManager;
+    
+    /**
+     * task executor.
+     */
+    @Autowired
+    protected PropagationTaskExecutor taskExecutor;
+
+    /**
      * User workflow adapter.
      */
     @Autowired

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/PushJob.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/PushJob.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/PushJob.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/PushJob.java Thu Jun 26 12:18:30 2014
@@ -123,7 +123,7 @@ public class PushJob extends AbstractSyn
                         // user propagation
                         uhandler.handle(localUser);
                     } catch (Exception e) {
-                        LOG.warn("Failure pushing user '{}' on '{}'", localUser, pushTask.getResource());
+                        LOG.warn("Failure pushing user '{}' on '{}'", localUser, pushTask.getResource(), e);
                         if (!continueOnError()) {
                             throw new JobExecutionException("While pushing users on connector", e);
                         }
@@ -140,7 +140,7 @@ public class PushJob extends AbstractSyn
                     // role propagation
                     rhandler.handle(localRole);
                 } catch (Exception e) {
-                    LOG.warn("Failure pushing role '{}' on '{}'", localRole, pushTask.getResource());
+                    LOG.warn("Failure pushing role '{}' on '{}'", localRole, pushTask.getResource(), e);
                     if (!continueOnError()) {
                         throw new JobExecutionException("While pushing roles on connector", e);
                     }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RolePushResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RolePushResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RolePushResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RolePushResultHandler.java Thu Jun 26 12:18:30 2014
@@ -18,5 +18,168 @@
  */
 package org.apache.syncope.core.sync.impl;
 
+import static org.apache.syncope.core.sync.impl.AbstractSyncopeResultHandler.LOG;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.mod.RoleMod;
+import org.apache.syncope.common.to.AbstractSubjectTO;
+import org.apache.syncope.common.to.RoleTO;
+import org.apache.syncope.common.types.ResourceOperation;
+import org.apache.syncope.core.persistence.beans.AbstractMappingItem;
+import org.apache.syncope.core.persistence.beans.AbstractSubject;
+import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
+import org.apache.syncope.core.propagation.PropagationByResource;
+import org.apache.syncope.core.propagation.TimeoutException;
+import org.apache.syncope.core.propagation.impl.AbstractPropagationTaskExecutor;
+import org.apache.syncope.core.sync.SyncResult;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.Uid;
+
 public class RolePushResultHandler extends AbstractSubjectPushResultHandler {
+
+    @Override
+    protected AbstractSubject deprovision(final AbstractSubject sbj, final SyncResult result) {
+        final RoleTO before = roleDataBinder.getRoleTO(SyncopeRole.class.cast(sbj));
+
+        final List<String> noPropResources = new ArrayList<String>(before.getResources());
+        noPropResources.remove(profile.getSyncTask().getResource().getName());
+
+        taskExecutor.execute(propagationManager.getRoleDeleteTaskIds(before.getId(), noPropResources));
+
+        result.setId(before.getId());
+        return roleDataBinder.getRoleFromId(before.getId());
+    }
+
+    @Override
+    protected AbstractSubject provision(final AbstractSubject sbj, final Boolean enabled, final SyncResult result) {
+        final RoleTO before = roleDataBinder.getRoleTO(SyncopeRole.class.cast(sbj));
+
+        final List<String> noPropResources = new ArrayList<String>(before.getResources());
+        noPropResources.remove(profile.getSyncTask().getResource().getName());
+
+        final PropagationByResource propByRes = new PropagationByResource();
+        propByRes.add(ResourceOperation.CREATE, profile.getSyncTask().getResource().getName());
+
+        taskExecutor.execute(propagationManager.getRoleCreateTaskIds(
+                before.getId(),
+                Collections.unmodifiableCollection(before.getVirAttrs()),
+                propByRes,
+                noPropResources));
+
+        result.setId(before.getId());
+        return roleDataBinder.getRoleFromId(before.getId());
+    }
+
+    @Override
+    protected AbstractSubject link(
+            final AbstractSubject sbj, final Boolean unlink, final SyncResult result) {
+
+        final RoleMod roleMod = new RoleMod();
+        roleMod.setId(sbj.getId());
+
+        if (unlink) {
+            roleMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        } else {
+            roleMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        }
+
+        rwfAdapter.update(roleMod);
+
+        result.setId(sbj.getId());
+        return roleDataBinder.getRoleFromId(sbj.getId());
+    }
+
+    @Override
+    protected AbstractSubject unassign(final AbstractSubject sbj, final SyncResult result) {
+        final RoleMod roleMod = new RoleMod();
+        roleMod.setId(sbj.getId());
+        roleMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        rwfAdapter.update(roleMod);
+        return deprovision(sbj, result);
+    }
+
+    @Override
+    protected AbstractSubject assign(final AbstractSubject sbj, final Boolean enabled, final SyncResult result) {
+        final RoleMod roleMod = new RoleMod();
+        roleMod.setId(sbj.getId());
+        roleMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        rwfAdapter.update(roleMod);
+        return provision(sbj, enabled, result);
+    }
+
+    @Override
+    protected AbstractSubject update(
+            final AbstractSubject sbj,
+            final String accountId,
+            final Set<Attribute> attributes,
+            final ConnectorObject beforeObj,
+            final SyncResult result) {
+
+        AbstractPropagationTaskExecutor.createOrUpdate(
+                ObjectClass.GROUP,
+                accountId,
+                attributes,
+                profile.getSyncTask().getResource().getName(),
+                profile.getSyncTask().getResource().getPropagationMode(),
+                beforeObj,
+                profile.getConnector(),
+                new HashSet<String>(),
+                connObjectUtil);
+
+        result.setId(sbj.getId());
+        return userDataBinder.getUserFromId(sbj.getId());
+    }
+
+    @Override
+    protected String getName(final AbstractSubject subject) {
+        return SyncopeRole.class.cast(subject).getName();
+    }
+
+    @Override
+    protected AbstractSubjectTO getSubjectTO(final long id) {
+        try {
+            return roleDataBinder.getRoleTO(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", id, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected AbstractSubject getSubject(final long id) {
+        try {
+            return roleDataBinder.getRoleFromId(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", id, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected ConnectorObject getRemoteObject(final String accountId) {
+        ConnectorObject obj = null;
+
+        try {
+
+            final Uid uid = new Uid(accountId);
+
+            profile.getConnector().getObject(
+                    ObjectClass.GROUP,
+                    uid,
+                    profile.getConnector().getOperationOptions(Collections.<AbstractMappingItem>emptySet()));
+
+        } catch (TimeoutException toe) {
+            LOG.debug("Request timeout", toe);
+            throw toe;
+        } catch (RuntimeException ignore) {
+            LOG.debug("While resolving {}", accountId, ignore);
+        }
+        return obj;
+    }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RoleSyncResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RoleSyncResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RoleSyncResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/RoleSyncResultHandler.java Thu Jun 26 12:18:30 2014
@@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUt
 import org.apache.syncope.common.mod.AbstractSubjectMod;
 import org.apache.syncope.common.mod.AttributeMod;
 import org.apache.syncope.common.mod.RoleMod;
+import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.common.to.AbstractSubjectTO;
 import org.apache.syncope.common.to.AttributeTO;
 import org.apache.syncope.common.to.RoleTO;
@@ -58,7 +59,12 @@ public class RoleSyncResultHandler exten
 
     @Override
     protected AbstractSubjectTO getSubjectTO(final long id) {
-        return roleDataBinder.getRoleTO(id);
+        try {
+            return roleDataBinder.getRoleTO(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving role {}", id, e);
+            return null;
+        }
     }
 
     @Override
@@ -101,6 +107,25 @@ public class RoleSyncResultHandler exten
     }
 
     @Override
+    protected AbstractSubjectTO link(
+            final AbstractSubjectTO before,
+            final SyncResult result,
+            final boolean unlink)
+            throws Exception {
+
+        final RoleMod roleMod = new RoleMod();
+        roleMod.setId(before.getId());
+
+        if (unlink) {
+            roleMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        } else {
+            roleMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        }
+
+        return userDataBinder.getUserTO(rwfAdapter.update(roleMod).getResult());
+    }
+
+    @Override
     protected AbstractSubjectTO update(
             final AbstractSubjectTO before,
             final AbstractSubjectMod subjectMod,
@@ -135,7 +160,20 @@ public class RoleSyncResultHandler exten
     }
 
     @Override
-    protected void delete(Long id) {
+    protected void deprovision(final Long id, final boolean unlink) {
+
+        taskExecutor.execute(
+                propagationManager.getRoleDeleteTaskIds(id, profile.getSyncTask().getResource().getName()));
+
+        if (unlink) {
+            final UserMod userMod = new UserMod();
+            userMod.setId(id);
+            userMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        }
+    }
+
+    @Override
+    protected void delete(final Long id) {
         try {
             taskExecutor.execute(
                     propagationManager.getRoleDeleteTaskIds(id, profile.getSyncTask().getResource().getName()));

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserPushResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserPushResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserPushResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserPushResultHandler.java Thu Jun 26 12:18:30 2014
@@ -18,5 +18,170 @@
  */
 package org.apache.syncope.core.sync.impl;
 
+import static org.apache.syncope.core.sync.impl.AbstractSyncopeResultHandler.LOG;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.mod.UserMod;
+import org.apache.syncope.common.to.AbstractSubjectTO;
+import org.apache.syncope.common.to.UserTO;
+import org.apache.syncope.common.types.ResourceOperation;
+import org.apache.syncope.core.persistence.beans.AbstractMappingItem;
+import org.apache.syncope.core.persistence.beans.AbstractSubject;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.propagation.PropagationByResource;
+import org.apache.syncope.core.propagation.TimeoutException;
+import org.apache.syncope.core.propagation.impl.AbstractPropagationTaskExecutor;
+import org.apache.syncope.core.sync.SyncResult;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.Uid;
+
 public class UserPushResultHandler extends AbstractSubjectPushResultHandler {
+
+    @Override
+    protected AbstractSubject deprovision(final AbstractSubject sbj, final SyncResult result) {
+        final UserTO before = userDataBinder.getUserTO(sbj.getId());
+
+        final List<String> noPropResources = new ArrayList<String>(before.getResources());
+        noPropResources.remove(profile.getSyncTask().getResource().getName());
+
+        taskExecutor.execute(propagationManager.getUserDeleteTaskIds(before.getId(), noPropResources));
+
+        result.setId(before.getId());
+        return userDataBinder.getUserFromId(before.getId());
+    }
+
+    @Override
+    protected AbstractSubject provision(final AbstractSubject sbj, final Boolean enabled, final SyncResult result) {
+        final UserTO before = userDataBinder.getUserTO(sbj.getId());
+
+        final List<String> noPropResources = new ArrayList<String>(before.getResources());
+        noPropResources.remove(profile.getSyncTask().getResource().getName());
+
+        final PropagationByResource propByRes = new PropagationByResource();
+        propByRes.add(ResourceOperation.CREATE, profile.getSyncTask().getResource().getName());
+
+        taskExecutor.execute(propagationManager.getUserCreateTaskIds(
+                before.getId(),
+                enabled,
+                propByRes,
+                null,
+                Collections.unmodifiableCollection(before.getVirAttrs()),
+                Collections.unmodifiableCollection(before.getMemberships()),
+                noPropResources));
+
+        result.setId(before.getId());
+        return userDataBinder.getUserFromId(before.getId());
+    }
+
+    @Override
+    protected AbstractSubject link(
+            final AbstractSubject sbj, final Boolean unlink, final SyncResult result) {
+
+        final UserMod userMod = new UserMod();
+        userMod.setId(sbj.getId());
+
+        if (unlink) {
+            userMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        } else {
+            userMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        }
+
+        uwfAdapter.update(userMod);
+
+        result.setId(sbj.getId());
+        return userDataBinder.getUserFromId(sbj.getId());
+    }
+
+    @Override
+    protected AbstractSubject unassign(final AbstractSubject sbj, final SyncResult result) {
+        final UserMod userMod = new UserMod();
+        userMod.setId(sbj.getId());
+        userMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        uwfAdapter.update(userMod);
+        return deprovision(sbj, result);
+    }
+
+    @Override
+    protected AbstractSubject assign(final AbstractSubject sbj, final Boolean enabled, final SyncResult result) {
+        final UserMod userMod = new UserMod();
+        userMod.setId(sbj.getId());
+        userMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        uwfAdapter.update(userMod);
+        return provision(sbj, enabled, result);
+    }
+
+    @Override
+    protected AbstractSubject update(
+            final AbstractSubject sbj,
+            final String accountId,
+            final Set<Attribute> attributes,
+            final ConnectorObject beforeObj,
+            final SyncResult result) {
+
+        AbstractPropagationTaskExecutor.createOrUpdate(
+                ObjectClass.ACCOUNT,
+                accountId,
+                attributes,
+                profile.getSyncTask().getResource().getName(),
+                profile.getSyncTask().getResource().getPropagationMode(),
+                beforeObj,
+                profile.getConnector(),
+                new HashSet<String>(),
+                connObjectUtil);
+
+        result.setId(sbj.getId());
+        return userDataBinder.getUserFromId(sbj.getId());
+    }
+
+    @Override
+    protected String getName(final AbstractSubject subject) {
+        return SyncopeUser.class.cast(subject).getUsername();
+    }
+
+    @Override
+    protected AbstractSubjectTO getSubjectTO(final long id) {
+        try {
+            return userDataBinder.getUserTO(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", id, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected AbstractSubject getSubject(final long id) {
+        try {
+            return userDataBinder.getUserFromId(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", id, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected ConnectorObject getRemoteObject(final String accountId) {
+        ConnectorObject obj = null;
+
+        try {
+
+            final Uid uid = new Uid(accountId);
+
+            profile.getConnector().getObject(
+                    ObjectClass.ACCOUNT,
+                    uid,
+                    profile.getConnector().getOperationOptions(Collections.<AbstractMappingItem>emptySet()));
+
+        } catch (TimeoutException toe) {
+            LOG.debug("Request timeout", toe);
+            throw toe;
+        } catch (RuntimeException ignore) {
+            LOG.debug("While resolving {}", accountId, ignore);
+        }
+        return obj;
+    }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/UserSyncResultHandler.java Thu Jun 26 12:18:30 2014
@@ -53,7 +53,12 @@ public class UserSyncResultHandler exten
 
     @Override
     protected AbstractSubjectTO getSubjectTO(final long id) {
-        return userDataBinder.getUserTO(id);
+        try {
+            return userDataBinder.getUserTO(id);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", id, e);
+            return null;
+        }
     }
 
     @Override
@@ -88,16 +93,35 @@ public class UserSyncResultHandler exten
         userTO = userDataBinder.getUserTO(created.getResult().getKey());
 
         result.setId(created.getResult().getKey());
-        result.setName(getName(subjectTO));
 
         return userTO;
     }
 
     @Override
+    protected AbstractSubjectTO link(
+            final AbstractSubjectTO before,
+            final SyncResult result,
+            final boolean unlink)
+            throws Exception {
+
+        final UserMod userMod = new UserMod();
+        userMod.setId(before.getId());
+
+        if (unlink) {
+            userMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        } else {
+            userMod.getResourcesToAdd().add(profile.getSyncTask().getResource().getName());
+        }
+
+        return userDataBinder.getUserTO(uwfAdapter.update(userMod).getResult().getKey().getId());
+    }
+
+    @Override
     protected AbstractSubjectTO update(
             final AbstractSubjectTO before,
             final AbstractSubjectMod subjectMod,
-            final SyncDelta delta, final SyncResult result)
+            final SyncDelta delta,
+            final SyncResult result)
             throws Exception {
 
         final UserMod userMod = UserMod.class.cast(subjectMod);
@@ -113,7 +137,8 @@ public class UserSyncResultHandler exten
                     + ExceptionUtils.getRootCauseMessage(e));
 
             updated = new WorkflowResult<Map.Entry<UserMod, Boolean>>(
-                    new AbstractMap.SimpleEntry<UserMod, Boolean>(userMod, false), new PropagationByResource(),
+                    new AbstractMap.SimpleEntry<UserMod, Boolean>(userMod, false),
+                    new PropagationByResource(),
                     new HashSet<String>());
         }
 
@@ -145,10 +170,22 @@ public class UserSyncResultHandler exten
 
         taskExecutor.execute(tasks);
 
-        final UserTO after = userDataBinder.getUserTO(updated.getResult().getKey().getId());
+        return userDataBinder.getUserTO(updated.getResult().getKey().getId());
+    }
 
-        result.setName(getName(after));
-        return after;
+    @Override
+    protected void deprovision(
+            final Long id,
+            final boolean unlink) {
+
+        taskExecutor.execute(
+                propagationManager.getUserDeleteTaskIds(id, profile.getSyncTask().getResource().getName()));
+
+        if (unlink) {
+            final UserMod userMod = new UserMod();
+            userMod.setId(id);
+            userMod.getResourcesToRemove().add(profile.getSyncTask().getResource().getName());
+        }
     }
 
     @Override

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java?rev=1605756&r1=1605755&r2=1605756&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java Thu Jun 26 12:18:30 2014
@@ -30,11 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import javax.annotation.Resource;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
 import org.activiti.bpmn.converter.BpmnXMLConverter;
 import org.activiti.bpmn.model.BpmnModel;
 import org.activiti.editor.constants.ModelDataJsonConstants;
@@ -85,8 +80,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
 
 /**
  * Activiti (http://www.activiti.org/) based implementation.