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 2017/11/13 15:35:22 UTC

[1/2] syncope git commit: [SYNCOPE-1234] Pre-processing method added

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 1965e5b10 -> 460bd265e
  refs/heads/master e7f03f43d -> e3ac8999d


[SYNCOPE-1234] Pre-processing method added


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/460bd265
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/460bd265
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/460bd265

Branch: refs/heads/2_0_X
Commit: 460bd265ea2c681dfdab3dd1d8f78f08254531b5
Parents: 1965e5b
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 13 16:23:48 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 13 16:23:48 2017 +0100

----------------------------------------------------------------------
 .../core/migration/MigrationPullActions.java    |   4 +-
 .../provisioning/api/pushpull/PullActions.java  |  32 +++---
 .../pushpull/AbstractPullResultHandler.java     |  78 +++++++-------
 .../java/pushpull/DBPasswordPullActions.java    |   8 +-
 .../java/pushpull/DefaultPullActions.java       |  29 +++---
 .../pushpull/DefaultRealmPullResultHandler.java | 104 ++++++++++---------
 .../java/pushpull/GoogleAppsPullActions.java    |  34 +++---
 .../java/pushpull/LDAPPasswordPullActions.java  |   8 +-
 .../fit/core/reference/TestPullActions.java     |  12 +--
 9 files changed, 144 insertions(+), 165 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
----------------------------------------------------------------------
diff --git a/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java b/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
index caf633a..aab5f8f 100644
--- a/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
+++ b/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
@@ -62,7 +62,7 @@ public class MigrationPullActions extends SchedulingPullActions {
     private final Map<String, Set<String>> memberships = new HashMap<>();
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
@@ -75,8 +75,6 @@ public class MigrationPullActions extends SchedulingPullActions {
             ((AnyTO) entity).getResources().addAll(
                     CollectionUtils.collect(resourcesAttr.getValue(), TransformerUtils.stringValueTransformer()));
         }
-
-        return delta;
     }
 
     @Transactional

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
index c872d1b..f5ee92f 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
@@ -31,6 +31,14 @@ import org.quartz.JobExecutionException;
 public interface PullActions extends ProvisioningActions {
 
     /**
+     * Pre-process the pull information received by the underlying connector, before any internal activity occurs.
+     *
+     * @param delta retrieved pull information
+     * @return pull information, possibly altered.
+     */
+    SyncDelta preprocess(SyncDelta delta);
+
+    /**
      * Action to be executed before to create a pulled entity locally.
      * The entity is created locally upon pull in case of the un-matching rule
      * {@link org.apache.syncope.common.lib.types.UnmatchingRule#PROVISION} (default un-matching rule) is applied.
@@ -38,10 +46,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeProvision(
+    void beforeProvision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -54,10 +61,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeAssign(
+    void beforeAssign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -70,10 +76,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeUnassign(
+    void beforeUnassign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -86,10 +91,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeDeprovision(
+    void beforeDeprovision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -102,10 +106,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeUnlink(
+    void beforeUnlink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -118,10 +121,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeLink(
+    void beforeLink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;
@@ -136,10 +138,9 @@ public interface PullActions extends ProvisioningActions {
      * @param delta retrieved pull information
      * @param entity entity
      * @param anyPatch modification
-     * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure.
      */
-    <P extends AnyPatch> SyncDelta beforeUpdate(
+    <P extends AnyPatch> void beforeUpdate(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity,
@@ -152,10 +153,9 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure
      */
-    SyncDelta beforeDelete(
+    void beforeDelete(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException;

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index e09f39b..9836394 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -191,12 +191,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeAssign(profile, actionedDelta, anyTO);
+                action.beforeAssign(profile, delta, anyTO);
             }
 
-            create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
+            create(anyTO, delta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
         }
 
         return Collections.singletonList(result);
@@ -224,12 +223,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeProvision(profile, actionedDelta, anyTO);
+                action.beforeProvision(profile, delta, anyTO);
             }
 
-            create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
+            create(anyTO, delta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
         }
 
         return Collections.singletonList(result);
@@ -307,7 +305,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : anyKeys) {
             LOG.debug("About to update {}", key);
 
@@ -337,21 +334,21 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                     try {
                         AnyPatch anyPatch = connObjectUtils.getAnyPatch(
                                 before.getKey(),
-                                workingDelta.getObject(),
+                                delta.getObject(),
                                 before,
                                 profile.getTask(),
                                 provision,
                                 getAnyUtils());
 
                         for (PullActions action : profile.getActions()) {
-                            workingDelta = action.beforeUpdate(profile, workingDelta, before, anyPatch);
+                            action.beforeUpdate(profile, delta, before, anyPatch);
                         }
 
-                        effectivePatch = doUpdate(before, anyPatch, workingDelta, result);
+                        effectivePatch = doUpdate(before, anyPatch, delta, result);
                         AnyTO updated = AnyOperations.patch(before, effectivePatch);
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, updated, result);
+                            action.after(profile, delta, updated, result);
                         }
 
                         output = updated;
@@ -363,7 +360,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
                         LOG.error("Could not propagate {} {}",
-                                provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
+                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
@@ -372,13 +369,13 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                         LOG.error("Could not update {} {}",
-                                provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
+                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
                 finalize(MatchingRule.toEventName(MatchingRule.UPDATE),
-                        resultStatus, before, output, workingDelta, effectivePatch);
+                        resultStatus, before, output, delta, effectivePatch);
             }
             results.add(result);
         }
@@ -615,7 +612,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : anyKeys) {
             Object output;
             Result resultStatus = Result.FAILURE;
@@ -633,7 +629,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
                 if (!profile.isDryRun()) {
                     for (PullActions action : profile.getActions()) {
-                        workingDelta = action.beforeDelete(profile, workingDelta, before);
+                        action.beforeDelete(profile, delta, before);
                     }
 
                     try {
@@ -642,7 +638,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         resultStatus = Result.SUCCESS;
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, before, result);
+                            action.after(profile, delta, before, result);
                         }
                     } catch (Exception e) {
                         throwIgnoreProvisionException(delta, e);
@@ -653,7 +649,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         output = e;
                     }
 
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
                 }
 
                 results.add(result);
@@ -729,14 +725,22 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
         LOG.debug("Process {} for {} as {}",
                 delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
 
-        String uid = delta.getPreviousUid() == null
-                ? delta.getUid().getUidValue()
-                : delta.getPreviousUid().getUidValue();
+        SyncDelta processed = delta;
+        for (PullActions action : profile.getActions()) {
+            processed = action.preprocess(processed);
+        }
+
+        LOG.debug("Transformed {} for {} as {}",
+                processed.getDeltaType(), processed.getUid().getUidValue(), processed.getObject().getObjectClass());
+
+        String uid = processed.getPreviousUid() == null
+                ? processed.getUid().getUidValue()
+                : processed.getPreviousUid().getUidValue();
 
         try {
-            List<String> anyKeys = pullUtils.findExisting(uid, delta.getObject(), provision, anyUtils);
+            List<String> anyKeys = pullUtils.findExisting(uid, processed.getObject(), provision, anyUtils);
             LOG.debug("Match(es) found for {} as {}: {}",
-                    delta.getUid().getUidValue(), delta.getObject().getObjectClass(), anyKeys);
+                    processed.getUid().getUidValue(), processed.getObject().getObjectClass(), anyKeys);
 
             if (anyKeys.size() > 1) {
                 switch (profile.getResAct()) {
@@ -756,19 +760,19 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 }
             }
 
-            if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+            if (SyncDeltaType.CREATE_OR_UPDATE == processed.getDeltaType()) {
                 if (anyKeys.isEmpty()) {
                     switch (profile.getTask().getUnmatchingRule()) {
                         case ASSIGN:
-                            profile.getResults().addAll(assign(delta, provision, anyUtils));
+                            profile.getResults().addAll(assign(processed, provision, anyUtils));
                             break;
 
                         case PROVISION:
-                            profile.getResults().addAll(provision(delta, provision, anyUtils));
+                            profile.getResults().addAll(provision(processed, provision, anyUtils));
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, null, provision, false));
+                            profile.getResults().addAll(ignore(processed, null, provision, false));
                             break;
 
                         default:
@@ -777,7 +781,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 } else {
                     // update VirAttrCache
                     for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
-                        Attribute attr = delta.getObject().getAttributeByName(virSchema.getExtAttrName());
+                        Attribute attr = processed.getObject().getAttributeByName(virSchema.getExtAttrName());
                         for (String anyKey : anyKeys) {
                             if (attr == null) {
                                 virAttrCache.expire(
@@ -798,39 +802,39 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
                     switch (profile.getTask().getMatchingRule()) {
                         case UPDATE:
-                            profile.getResults().addAll(update(delta, anyKeys, provision));
+                            profile.getResults().addAll(update(processed, anyKeys, provision));
                             break;
 
                         case DEPROVISION:
-                            profile.getResults().addAll(deprovision(delta, anyKeys, provision, false));
+                            profile.getResults().addAll(deprovision(processed, anyKeys, provision, false));
                             break;
 
                         case UNASSIGN:
-                            profile.getResults().addAll(deprovision(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(deprovision(processed, anyKeys, provision, true));
                             break;
 
                         case LINK:
-                            profile.getResults().addAll(link(delta, anyKeys, provision, false));
+                            profile.getResults().addAll(link(processed, anyKeys, provision, false));
                             break;
 
                         case UNLINK:
-                            profile.getResults().addAll(link(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(link(processed, anyKeys, provision, true));
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(ignore(processed, anyKeys, provision, true));
                             break;
 
                         default:
                         // do nothing
                     }
                 }
-            } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+            } else if (SyncDeltaType.DELETE == processed.getDeltaType()) {
                 if (anyKeys.isEmpty()) {
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, processed);
                     LOG.debug("No match found for deletion");
                 } else {
-                    profile.getResults().addAll(delete(delta, anyKeys, provision));
+                    profile.getResults().addAll(delete(processed, anyKeys, provision));
                 }
             }
         } catch (IllegalStateException | IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
index d5b2093..0a173c3 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
@@ -60,7 +60,7 @@ public class DBPasswordPullActions extends DefaultPullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO any) throws JobExecutionException {
@@ -69,13 +69,11 @@ public class DBPasswordPullActions extends DefaultPullActions {
             String password = ((UserTO) any).getPassword();
             parseEncodedPassword(password, profile.getConnector());
         }
-
-        return delta;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -85,8 +83,6 @@ public class DBPasswordPullActions extends DefaultPullActions {
             PasswordPatch modPassword = ((UserPatch) anyPatch).getPassword();
             parseEncodedPassword(modPassword == null ? null : modPassword.getValue(), profile.getConnector());
         }
-
-        return delta;
     }
 
     private void parseEncodedPassword(final String password, final Connector connector) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
index a6871b0..31a671c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
@@ -33,73 +33,70 @@ import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
 public abstract class DefaultPullActions implements PullActions {
 
     @Override
+    public SyncDelta preprocess(final SyncDelta delta) {
+        return delta;
+    }
+
+    @Override
     public void beforeAll(final ProvisioningProfile<?, ?> profile) throws JobExecutionException {
     }
 
     @Override
-    public <P extends AnyPatch> SyncDelta beforeUpdate(
+    public <P extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity,
             final P anyPatch) throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeDelete(
+    public void beforeDelete(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeAssign(
+    public void beforeAssign(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeLink(
+    public void beforeLink(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeUnassign(
+    public void beforeUnassign(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeDeprovision(
+    public void beforeDeprovision(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeUnlink(
+    public void beforeUnlink(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
-        return delta;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
index d4a54e7..b3b12ea 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
@@ -153,12 +153,11 @@ public class DefaultRealmPullResultHandler
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeAssign(profile, actionedDelta, realmTO);
+                action.beforeAssign(profile, delta, realmTO);
             }
 
-            create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
+            create(realmTO, delta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
         }
 
         return Collections.singletonList(result);
@@ -192,12 +191,11 @@ public class DefaultRealmPullResultHandler
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeProvision(profile, actionedDelta, realmTO);
+                action.beforeProvision(profile, delta, realmTO);
             }
 
-            create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
+            create(realmTO, delta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
         }
 
         return Collections.singletonList(result);
@@ -286,7 +284,6 @@ public class DefaultRealmPullResultHandler
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to update {}", key);
 
@@ -315,7 +312,7 @@ public class DefaultRealmPullResultHandler
                 } else {
                     try {
                         for (PullActions action : profile.getActions()) {
-                            workingDelta = action.beforeUpdate(profile, workingDelta, before, null);
+                            action.beforeUpdate(profile, delta, before, null);
                         }
 
                         PropagationByResource propByRes = binder.update(realm, before);
@@ -326,7 +323,7 @@ public class DefaultRealmPullResultHandler
                         taskExecutor.execute(tasks, false);
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, updated, result);
+                            action.after(profile, delta, updated, result);
                         }
 
                         output = updated;
@@ -337,20 +334,20 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
-                        LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not update Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
-                finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, workingDelta);
+                finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, delta);
             }
             results.add(result);
         }
@@ -373,7 +370,6 @@ public class DefaultRealmPullResultHandler
 
         final List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to unassign resource {}", key);
 
@@ -403,11 +399,11 @@ public class DefaultRealmPullResultHandler
                     try {
                         if (unlink) {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeUnassign(profile, workingDelta, before);
+                                action.beforeUnassign(profile, delta, before);
                             }
                         } else {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeDeprovision(profile, workingDelta, before);
+                                action.beforeDeprovision(profile, delta, before);
                             }
                         }
 
@@ -423,7 +419,7 @@ public class DefaultRealmPullResultHandler
                         }
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+                            action.after(profile, delta, RealmTO.class.cast(output), result);
                         }
 
                         resultStatus = Result.SUCCESS;
@@ -432,11 +428,11 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
@@ -470,7 +466,6 @@ public class DefaultRealmPullResultHandler
 
         final List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to unassign resource {}", key);
 
@@ -499,11 +494,11 @@ public class DefaultRealmPullResultHandler
                     try {
                         if (unlink) {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeUnlink(profile, workingDelta, before);
+                                action.beforeUnlink(profile, delta, before);
                             }
                         } else {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeLink(profile, workingDelta, before);
+                                action.beforeLink(profile, delta, before);
                             }
                         }
 
@@ -512,10 +507,10 @@ public class DefaultRealmPullResultHandler
                         } else {
                             realm.add(profile.getTask().getResource());
                         }
-                        output = update(workingDelta, Collections.singletonList(key));
+                        output = update(delta, Collections.singletonList(key));
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+                            action.after(profile, delta, RealmTO.class.cast(output), result);
                         }
 
                         resultStatus = Result.SUCCESS;
@@ -524,22 +519,22 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
-                        LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not update Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
                 finalize(unlink
                         ? MatchingRule.toEventName(MatchingRule.UNLINK)
-                        : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, workingDelta);
+                        : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, delta);
             }
             results.add(result);
         }
@@ -560,7 +555,6 @@ public class DefaultRealmPullResultHandler
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             Object output;
             Result resultStatus = Result.FAILURE;
@@ -584,7 +578,7 @@ public class DefaultRealmPullResultHandler
 
                 if (!profile.isDryRun()) {
                     for (PullActions action : profile.getActions()) {
-                        workingDelta = action.beforeDelete(profile, workingDelta, before);
+                        action.beforeDelete(profile, delta, before);
                     }
 
                     try {
@@ -622,10 +616,10 @@ public class DefaultRealmPullResultHandler
                         resultStatus = Result.SUCCESS;
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, before, result);
+                            action.after(profile, delta, before, result);
                         }
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
@@ -633,7 +627,7 @@ public class DefaultRealmPullResultHandler
                         output = e;
                     }
 
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
                 }
 
                 results.add(result);
@@ -675,13 +669,21 @@ public class DefaultRealmPullResultHandler
         LOG.debug("Process {} for {} as {}",
                 delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
 
-        String uid = delta.getPreviousUid() == null
-                ? delta.getUid().getUidValue()
-                : delta.getPreviousUid().getUidValue();
+        SyncDelta processed = delta;
+        for (PullActions action : profile.getActions()) {
+            processed = action.preprocess(processed);
+        }
+
+        LOG.debug("Transformed {} for {} as {}",
+                processed.getDeltaType(), processed.getUid().getUidValue(), processed.getObject().getObjectClass());
+
+        String uid = processed.getPreviousUid() == null
+                ? processed.getUid().getUidValue()
+                : processed.getPreviousUid().getUidValue();
 
-        List<String> keys = pullUtils.findExisting(uid, delta.getObject(), orgUnit);
+        List<String> keys = pullUtils.findExisting(uid, processed.getObject(), orgUnit);
         LOG.debug("Match found for {} as {}: {}",
-                delta.getUid().getUidValue(), delta.getObject().getObjectClass(), keys);
+                processed.getUid().getUidValue(), processed.getObject().getObjectClass(), keys);
 
         if (keys.size() > 1) {
             switch (profile.getResAct()) {
@@ -702,19 +704,19 @@ public class DefaultRealmPullResultHandler
         }
 
         try {
-            if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+            if (SyncDeltaType.CREATE_OR_UPDATE == processed.getDeltaType()) {
                 if (keys.isEmpty()) {
                     switch (profile.getTask().getUnmatchingRule()) {
                         case ASSIGN:
-                            profile.getResults().addAll(assign(delta, orgUnit));
+                            profile.getResults().addAll(assign(processed, orgUnit));
                             break;
 
                         case PROVISION:
-                            profile.getResults().addAll(provision(delta, orgUnit));
+                            profile.getResults().addAll(provision(processed, orgUnit));
                             break;
 
                         case IGNORE:
-                            profile.getResults().add(ignore(delta, false));
+                            profile.getResults().add(ignore(processed, false));
                             break;
 
                         default:
@@ -723,39 +725,39 @@ public class DefaultRealmPullResultHandler
                 } else {
                     switch (profile.getTask().getMatchingRule()) {
                         case UPDATE:
-                            profile.getResults().addAll(update(delta, keys));
+                            profile.getResults().addAll(update(processed, keys));
                             break;
 
                         case DEPROVISION:
-                            profile.getResults().addAll(deprovision(delta, keys, false));
+                            profile.getResults().addAll(deprovision(processed, keys, false));
                             break;
 
                         case UNASSIGN:
-                            profile.getResults().addAll(deprovision(delta, keys, true));
+                            profile.getResults().addAll(deprovision(processed, keys, true));
                             break;
 
                         case LINK:
-                            profile.getResults().addAll(link(delta, keys, false));
+                            profile.getResults().addAll(link(processed, keys, false));
                             break;
 
                         case UNLINK:
-                            profile.getResults().addAll(link(delta, keys, true));
+                            profile.getResults().addAll(link(processed, keys, true));
                             break;
 
                         case IGNORE:
-                            profile.getResults().add(ignore(delta, true));
+                            profile.getResults().add(ignore(processed, true));
                             break;
 
                         default:
                         // do nothing
                     }
                 }
-            } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+            } else if (SyncDeltaType.DELETE == processed.getDeltaType()) {
                 if (keys.isEmpty()) {
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, processed);
                     LOG.debug("No match found for deletion");
                 } else {
-                    profile.getResults().addAll(delete(delta, keys));
+                    profile.getResults().addAll(delete(processed, keys));
                 }
             }
         } catch (IllegalStateException | IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
index 67d2e73..2a95b43 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
@@ -80,41 +80,33 @@ public class GoogleAppsPullActions extends DefaultPullActions {
     }
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
 
-        if (!(entity instanceof UserTO)) {
-            return delta;
-        }
-
-        UserTO userTO = (UserTO) entity;
-        if (userTO.getUsername() == null) {
-            userTO.setUsername(delta.getObject().getName().getNameValue());
+        if (entity instanceof UserTO) {
+            UserTO userTO = (UserTO) entity;
+            if (userTO.getUsername() == null) {
+                userTO.setUsername(delta.getObject().getName().getNameValue());
+            }
         }
-
-        return delta;
     }
 
     @Override
-    public <P extends AnyPatch> SyncDelta beforeUpdate(
+    public <P extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity,
             final P anyPatch) throws JobExecutionException {
 
-        if (!(anyPatch instanceof UserPatch)) {
-            return delta;
-        }
-
-        UserPatch userPatch = (UserPatch) anyPatch;
-        if (userPatch.getUsername() == null) {
-            userPatch.setUsername(new StringReplacePatchItem.Builder().
-                    value(delta.getObject().getName().getNameValue()).build());
+        if (anyPatch instanceof UserPatch) {
+            UserPatch userPatch = (UserPatch) anyPatch;
+            if (userPatch.getUsername() == null) {
+                userPatch.setUsername(new StringReplacePatchItem.Builder().
+                        value(delta.getObject().getName().getNameValue()).build());
+            }
         }
-
-        return delta;
     }
 
     @Transactional

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
index f11a20e..0879cd9 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
@@ -54,7 +54,7 @@ public class LDAPPasswordPullActions extends DefaultPullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
@@ -63,13 +63,11 @@ public class LDAPPasswordPullActions extends DefaultPullActions {
             String password = ((UserTO) entity).getPassword();
             parseEncodedPassword(password);
         }
-
-        return delta;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -79,8 +77,6 @@ public class LDAPPasswordPullActions extends DefaultPullActions {
             PasswordPatch modPassword = ((UserPatch) anyPatch).getPassword();
             parseEncodedPassword(modPassword == null ? null : modPassword.getValue());
         }
-
-        return delta;
     }
 
     private void parseEncodedPassword(final String password) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/460bd265/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
index 72fa798..7972c34 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
@@ -40,7 +40,7 @@ public class TestPullActions extends DefaultPullActions {
     private int counter;
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
@@ -62,24 +62,20 @@ public class TestPullActions extends DefaultPullActions {
             attrTO.getValues().clear();
             attrTO.getValues().add(String.valueOf(counter++));
         }
-
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeAssign(
+    public void beforeAssign(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
         if (entity instanceof UserTO && "test2".equals(UserTO.class.cast(entity).getUsername())) {
             throw new IgnoreProvisionException();
         }
-
-        return delta;
     }
 
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -100,7 +96,5 @@ public class TestPullActions extends DefaultPullActions {
 
         fullnamePatch.getAttrTO().getValues().clear();
         fullnamePatch.getAttrTO().getValues().add(String.valueOf(counter++));
-
-        return delta;
     }
 }


[2/2] syncope git commit: [SYNCOPE-1234] Pre-processing method added

Posted by il...@apache.org.
[SYNCOPE-1234] Pre-processing method added


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e3ac8999
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e3ac8999
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e3ac8999

Branch: refs/heads/master
Commit: e3ac8999d2ffe6fc87b4558453a59d797a8c61c0
Parents: e7f03f4
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 13 16:23:48 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 13 16:32:21 2017 +0100

----------------------------------------------------------------------
 .../implementations/MyPullActions.groovy        |  29 +++---
 .../core/migration/MigrationPullActions.java    |   4 +-
 .../provisioning/api/pushpull/PullActions.java  |  50 ++++-----
 .../pushpull/AbstractPullResultHandler.java     |  78 +++++++-------
 .../java/pushpull/DBPasswordPullActions.java    |   8 +-
 .../pushpull/DefaultRealmPullResultHandler.java | 104 ++++++++++---------
 .../java/pushpull/GoogleAppsPullActions.java    |  34 +++---
 .../java/pushpull/LDAPPasswordPullActions.java  |   8 +-
 .../fit/core/reference/TestPullActions.java     |  12 +--
 9 files changed, 146 insertions(+), 181 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
index 4d50971..893e7a9 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
@@ -32,76 +32,73 @@ import org.quartz.JobExecutionException
 class MyPullActions implements PullActions {
   
   @Override
-  SyncDelta beforeProvision(
+  SyncDelta preprocess(SyncDelta delta) {
+    return delta;
+  }
+  
+  @Override
+  void beforeProvision(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeAssign(
+  void beforeAssign(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeUnassign(
+  void beforeUnassign(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeDeprovision(
+  void beforeDeprovision(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeUnlink(
+  void beforeUnlink(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeLink(
+  void beforeLink(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  <P extends AnyPatch> SyncDelta beforeUpdate(
+  <P extends AnyPatch> void beforeUpdate(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity,
     P anyPatch) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override
-  SyncDelta beforeDelete(
+  void beforeDelete(
     ProvisioningProfile profile,
     SyncDelta delta,
     EntityTO entity) throws JobExecutionException {
 
-    return delta;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
----------------------------------------------------------------------
diff --git a/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java b/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
index e626215..00cf2e9 100644
--- a/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
+++ b/core/migration/src/main/java/org/apache/syncope/core/migration/MigrationPullActions.java
@@ -61,7 +61,7 @@ public class MigrationPullActions extends SchedulingPullActions {
     private final Map<String, Set<String>> memberships = new HashMap<>();
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
@@ -74,8 +74,6 @@ public class MigrationPullActions extends SchedulingPullActions {
             ((AnyTO) entity).getResources().addAll(
                     resourcesAttr.getValue().stream().map(Object::toString).collect(Collectors.toList()));
         }
-
-        return delta;
     }
 
     @Transactional

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
index f6e5af1..bcf20c3 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
@@ -31,6 +31,16 @@ import org.quartz.JobExecutionException;
 public interface PullActions extends ProvisioningActions {
 
     /**
+     * Pre-process the pull information received by the underlying connector, before any internal activity occurs.
+     *
+     * @param delta retrieved pull information
+     * @return pull information, possibly altered.
+     */
+    default SyncDelta preprocess(final SyncDelta delta) {
+        return delta;
+    }
+
+    /**
      * Action to be executed before to create a pulled entity locally.
      * The entity is created locally upon pull in case of the un-matching rule
      * {@link org.apache.syncope.common.lib.types.UnmatchingRule#PROVISION} (default un-matching rule) is applied.
@@ -38,15 +48,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeProvision(
+    default void beforeProvision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -57,15 +64,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeAssign(
+    default void beforeAssign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -76,15 +80,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeUnassign(
+    default void beforeUnassign(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -95,15 +96,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeDeprovision(
+    default void beforeDeprovision(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -114,15 +112,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeUnlink(
+    default void beforeUnlink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -133,15 +128,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information, possibly altered.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeLink(
+    default void beforeLink(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -154,16 +146,13 @@ public interface PullActions extends ProvisioningActions {
      * @param delta retrieved pull information
      * @param entity entity
      * @param anyPatch modification
-     * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure.
      */
-    default <P extends AnyPatch> SyncDelta beforeUpdate(
+    default <P extends AnyPatch> void beforeUpdate(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity,
             P anyPatch) throws JobExecutionException {
-
-        return delta;
     }
 
     /**
@@ -172,15 +161,12 @@ public interface PullActions extends ProvisioningActions {
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
      * @param entity entity
-     * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure
      */
-    default SyncDelta beforeDelete(
+    default void beforeDelete(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
             EntityTO entity) throws JobExecutionException {
-
-        return delta;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index 9ec7edb..dd7e4ef 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -191,12 +191,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeAssign(profile, actionedDelta, anyTO);
+                action.beforeAssign(profile, delta, anyTO);
             }
 
-            create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
+            create(anyTO, delta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
         }
 
         return Collections.singletonList(result);
@@ -224,12 +223,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeProvision(profile, actionedDelta, anyTO);
+                action.beforeProvision(profile, delta, anyTO);
             }
 
-            create(anyTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
+            create(anyTO, delta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
         }
 
         return Collections.singletonList(result);
@@ -307,7 +305,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : anyKeys) {
             LOG.debug("About to update {}", key);
 
@@ -337,21 +334,21 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                     try {
                         AnyPatch anyPatch = connObjectUtils.getAnyPatch(
                                 before.getKey(),
-                                workingDelta.getObject(),
+                                delta.getObject(),
                                 before,
                                 profile.getTask(),
                                 provision,
                                 getAnyUtils());
 
                         for (PullActions action : profile.getActions()) {
-                            workingDelta = action.beforeUpdate(profile, workingDelta, before, anyPatch);
+                            action.beforeUpdate(profile, delta, before, anyPatch);
                         }
 
-                        effectivePatch = doUpdate(before, anyPatch, workingDelta, result);
+                        effectivePatch = doUpdate(before, anyPatch, delta, result);
                         AnyTO updated = AnyOperations.patch(before, effectivePatch);
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, updated, result);
+                            action.after(profile, delta, updated, result);
                         }
 
                         output = updated;
@@ -363,7 +360,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
                         LOG.error("Could not propagate {} {}",
-                                provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
+                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
@@ -372,13 +369,13 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                         LOG.error("Could not update {} {}",
-                                provision.getAnyType().getKey(), workingDelta.getUid().getUidValue(), e);
+                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
                 finalize(MatchingRule.toEventName(MatchingRule.UPDATE),
-                        resultStatus, before, output, workingDelta, effectivePatch);
+                        resultStatus, before, output, delta, effectivePatch);
             }
             results.add(result);
         }
@@ -615,7 +612,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : anyKeys) {
             Object output;
             Result resultStatus = Result.FAILURE;
@@ -633,7 +629,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
                 if (!profile.isDryRun()) {
                     for (PullActions action : profile.getActions()) {
-                        workingDelta = action.beforeDelete(profile, workingDelta, before);
+                        action.beforeDelete(profile, delta, before);
                     }
 
                     try {
@@ -642,7 +638,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         resultStatus = Result.SUCCESS;
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, before, result);
+                            action.after(profile, delta, before, result);
                         }
                     } catch (Exception e) {
                         throwIgnoreProvisionException(delta, e);
@@ -653,7 +649,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         output = e;
                     }
 
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
                 }
 
                 results.add(result);
@@ -729,14 +725,22 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
         LOG.debug("Process {} for {} as {}",
                 delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
 
-        String uid = delta.getPreviousUid() == null
-                ? delta.getUid().getUidValue()
-                : delta.getPreviousUid().getUidValue();
+        SyncDelta processed = delta;
+        for (PullActions action : profile.getActions()) {
+            processed = action.preprocess(processed);
+        }
+
+        LOG.debug("Transformed {} for {} as {}",
+                processed.getDeltaType(), processed.getUid().getUidValue(), processed.getObject().getObjectClass());
+
+        String uid = processed.getPreviousUid() == null
+                ? processed.getUid().getUidValue()
+                : processed.getPreviousUid().getUidValue();
 
         try {
-            List<String> anyKeys = pullUtils.findExisting(uid, delta.getObject(), provision, anyUtils);
+            List<String> anyKeys = pullUtils.findExisting(uid, processed.getObject(), provision, anyUtils);
             LOG.debug("Match(es) found for {} as {}: {}",
-                    delta.getUid().getUidValue(), delta.getObject().getObjectClass(), anyKeys);
+                    processed.getUid().getUidValue(), processed.getObject().getObjectClass(), anyKeys);
 
             if (anyKeys.size() > 1) {
                 switch (profile.getResAct()) {
@@ -756,19 +760,19 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 }
             }
 
-            if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+            if (SyncDeltaType.CREATE_OR_UPDATE == processed.getDeltaType()) {
                 if (anyKeys.isEmpty()) {
                     switch (profile.getTask().getUnmatchingRule()) {
                         case ASSIGN:
-                            profile.getResults().addAll(assign(delta, provision, anyUtils));
+                            profile.getResults().addAll(assign(processed, provision, anyUtils));
                             break;
 
                         case PROVISION:
-                            profile.getResults().addAll(provision(delta, provision, anyUtils));
+                            profile.getResults().addAll(provision(processed, provision, anyUtils));
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, null, provision, false));
+                            profile.getResults().addAll(ignore(processed, null, provision, false));
                             break;
 
                         default:
@@ -777,7 +781,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 } else {
                     // update VirAttrCache
                     for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
-                        Attribute attr = delta.getObject().getAttributeByName(virSchema.getExtAttrName());
+                        Attribute attr = processed.getObject().getAttributeByName(virSchema.getExtAttrName());
                         for (String anyKey : anyKeys) {
                             if (attr == null) {
                                 virAttrCache.expire(
@@ -798,39 +802,39 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
                     switch (profile.getTask().getMatchingRule()) {
                         case UPDATE:
-                            profile.getResults().addAll(update(delta, anyKeys, provision));
+                            profile.getResults().addAll(update(processed, anyKeys, provision));
                             break;
 
                         case DEPROVISION:
-                            profile.getResults().addAll(deprovision(delta, anyKeys, provision, false));
+                            profile.getResults().addAll(deprovision(processed, anyKeys, provision, false));
                             break;
 
                         case UNASSIGN:
-                            profile.getResults().addAll(deprovision(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(deprovision(processed, anyKeys, provision, true));
                             break;
 
                         case LINK:
-                            profile.getResults().addAll(link(delta, anyKeys, provision, false));
+                            profile.getResults().addAll(link(processed, anyKeys, provision, false));
                             break;
 
                         case UNLINK:
-                            profile.getResults().addAll(link(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(link(processed, anyKeys, provision, true));
                             break;
 
                         case IGNORE:
-                            profile.getResults().addAll(ignore(delta, anyKeys, provision, true));
+                            profile.getResults().addAll(ignore(processed, anyKeys, provision, true));
                             break;
 
                         default:
                         // do nothing
                     }
                 }
-            } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+            } else if (SyncDeltaType.DELETE == processed.getDeltaType()) {
                 if (anyKeys.isEmpty()) {
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, processed);
                     LOG.debug("No match found for deletion");
                 } else {
-                    profile.getResults().addAll(delete(delta, anyKeys, provision));
+                    profile.getResults().addAll(delete(processed, anyKeys, provision));
                 }
             }
         } catch (IllegalStateException | IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
index c0a7eb4..5805543 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
@@ -60,7 +60,7 @@ public class DBPasswordPullActions implements PullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO any) throws JobExecutionException {
@@ -69,13 +69,11 @@ public class DBPasswordPullActions implements PullActions {
             String password = ((UserTO) any).getPassword();
             parseEncodedPassword(password, profile.getConnector());
         }
-
-        return delta;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -85,8 +83,6 @@ public class DBPasswordPullActions implements PullActions {
             PasswordPatch modPassword = ((UserPatch) anyPatch).getPassword();
             parseEncodedPassword(modPassword == null ? null : modPassword.getValue(), profile.getConnector());
         }
-
-        return delta;
     }
 
     private void parseEncodedPassword(final String password, final Connector connector) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
index d4a54e7..b3b12ea 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
@@ -153,12 +153,11 @@ public class DefaultRealmPullResultHandler
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeAssign(profile, actionedDelta, realmTO);
+                action.beforeAssign(profile, delta, realmTO);
             }
 
-            create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
+            create(realmTO, delta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
         }
 
         return Collections.singletonList(result);
@@ -192,12 +191,11 @@ public class DefaultRealmPullResultHandler
             result.setKey(null);
             finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
         } else {
-            SyncDelta actionedDelta = delta;
             for (PullActions action : profile.getActions()) {
-                actionedDelta = action.beforeProvision(profile, actionedDelta, realmTO);
+                action.beforeProvision(profile, delta, realmTO);
             }
 
-            create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
+            create(realmTO, delta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
         }
 
         return Collections.singletonList(result);
@@ -286,7 +284,6 @@ public class DefaultRealmPullResultHandler
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to update {}", key);
 
@@ -315,7 +312,7 @@ public class DefaultRealmPullResultHandler
                 } else {
                     try {
                         for (PullActions action : profile.getActions()) {
-                            workingDelta = action.beforeUpdate(profile, workingDelta, before, null);
+                            action.beforeUpdate(profile, delta, before, null);
                         }
 
                         PropagationByResource propByRes = binder.update(realm, before);
@@ -326,7 +323,7 @@ public class DefaultRealmPullResultHandler
                         taskExecutor.execute(tasks, false);
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, updated, result);
+                            action.after(profile, delta, updated, result);
                         }
 
                         output = updated;
@@ -337,20 +334,20 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
-                        LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not update Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
-                finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, workingDelta);
+                finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, delta);
             }
             results.add(result);
         }
@@ -373,7 +370,6 @@ public class DefaultRealmPullResultHandler
 
         final List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to unassign resource {}", key);
 
@@ -403,11 +399,11 @@ public class DefaultRealmPullResultHandler
                     try {
                         if (unlink) {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeUnassign(profile, workingDelta, before);
+                                action.beforeUnassign(profile, delta, before);
                             }
                         } else {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeDeprovision(profile, workingDelta, before);
+                                action.beforeDeprovision(profile, delta, before);
                             }
                         }
 
@@ -423,7 +419,7 @@ public class DefaultRealmPullResultHandler
                         }
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+                            action.after(profile, delta, RealmTO.class.cast(output), result);
                         }
 
                         resultStatus = Result.SUCCESS;
@@ -432,11 +428,11 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
@@ -470,7 +466,6 @@ public class DefaultRealmPullResultHandler
 
         final List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             LOG.debug("About to unassign resource {}", key);
 
@@ -499,11 +494,11 @@ public class DefaultRealmPullResultHandler
                     try {
                         if (unlink) {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeUnlink(profile, workingDelta, before);
+                                action.beforeUnlink(profile, delta, before);
                             }
                         } else {
                             for (PullActions action : profile.getActions()) {
-                                workingDelta = action.beforeLink(profile, workingDelta, before);
+                                action.beforeLink(profile, delta, before);
                             }
                         }
 
@@ -512,10 +507,10 @@ public class DefaultRealmPullResultHandler
                         } else {
                             realm.add(profile.getTask().getResource());
                         }
-                        output = update(workingDelta, Collections.singletonList(key));
+                        output = update(delta, Collections.singletonList(key));
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+                            action.after(profile, delta, RealmTO.class.cast(output), result);
                         }
 
                         resultStatus = Result.SUCCESS;
@@ -524,22 +519,22 @@ public class DefaultRealmPullResultHandler
                     } catch (PropagationException e) {
                         // A propagation failure doesn't imply a pull failure.
                         // The propagation exception status will be reported into the propagation task execution.
-                        LOG.error("Could not propagate Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
-                        LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+                        LOG.error("Could not update Realm {}", delta.getUid().getUidValue(), e);
                         output = e;
                         resultStatus = Result.FAILURE;
                     }
                 }
                 finalize(unlink
                         ? MatchingRule.toEventName(MatchingRule.UNLINK)
-                        : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, workingDelta);
+                        : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, delta);
             }
             results.add(result);
         }
@@ -560,7 +555,6 @@ public class DefaultRealmPullResultHandler
 
         List<ProvisioningReport> results = new ArrayList<>();
 
-        SyncDelta workingDelta = delta;
         for (String key : keys) {
             Object output;
             Result resultStatus = Result.FAILURE;
@@ -584,7 +578,7 @@ public class DefaultRealmPullResultHandler
 
                 if (!profile.isDryRun()) {
                     for (PullActions action : profile.getActions()) {
-                        workingDelta = action.beforeDelete(profile, workingDelta, before);
+                        action.beforeDelete(profile, delta, before);
                     }
 
                     try {
@@ -622,10 +616,10 @@ public class DefaultRealmPullResultHandler
                         resultStatus = Result.SUCCESS;
 
                         for (PullActions action : profile.getActions()) {
-                            action.after(profile, workingDelta, before, result);
+                            action.after(profile, delta, before, result);
                         }
                     } catch (Exception e) {
-                        throwIgnoreProvisionException(workingDelta, e);
+                        throwIgnoreProvisionException(delta, e);
 
                         result.setStatus(ProvisioningReport.Status.FAILURE);
                         result.setMessage(ExceptionUtils.getRootCauseMessage(e));
@@ -633,7 +627,7 @@ public class DefaultRealmPullResultHandler
                         output = e;
                     }
 
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
                 }
 
                 results.add(result);
@@ -675,13 +669,21 @@ public class DefaultRealmPullResultHandler
         LOG.debug("Process {} for {} as {}",
                 delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
 
-        String uid = delta.getPreviousUid() == null
-                ? delta.getUid().getUidValue()
-                : delta.getPreviousUid().getUidValue();
+        SyncDelta processed = delta;
+        for (PullActions action : profile.getActions()) {
+            processed = action.preprocess(processed);
+        }
+
+        LOG.debug("Transformed {} for {} as {}",
+                processed.getDeltaType(), processed.getUid().getUidValue(), processed.getObject().getObjectClass());
+
+        String uid = processed.getPreviousUid() == null
+                ? processed.getUid().getUidValue()
+                : processed.getPreviousUid().getUidValue();
 
-        List<String> keys = pullUtils.findExisting(uid, delta.getObject(), orgUnit);
+        List<String> keys = pullUtils.findExisting(uid, processed.getObject(), orgUnit);
         LOG.debug("Match found for {} as {}: {}",
-                delta.getUid().getUidValue(), delta.getObject().getObjectClass(), keys);
+                processed.getUid().getUidValue(), processed.getObject().getObjectClass(), keys);
 
         if (keys.size() > 1) {
             switch (profile.getResAct()) {
@@ -702,19 +704,19 @@ public class DefaultRealmPullResultHandler
         }
 
         try {
-            if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+            if (SyncDeltaType.CREATE_OR_UPDATE == processed.getDeltaType()) {
                 if (keys.isEmpty()) {
                     switch (profile.getTask().getUnmatchingRule()) {
                         case ASSIGN:
-                            profile.getResults().addAll(assign(delta, orgUnit));
+                            profile.getResults().addAll(assign(processed, orgUnit));
                             break;
 
                         case PROVISION:
-                            profile.getResults().addAll(provision(delta, orgUnit));
+                            profile.getResults().addAll(provision(processed, orgUnit));
                             break;
 
                         case IGNORE:
-                            profile.getResults().add(ignore(delta, false));
+                            profile.getResults().add(ignore(processed, false));
                             break;
 
                         default:
@@ -723,39 +725,39 @@ public class DefaultRealmPullResultHandler
                 } else {
                     switch (profile.getTask().getMatchingRule()) {
                         case UPDATE:
-                            profile.getResults().addAll(update(delta, keys));
+                            profile.getResults().addAll(update(processed, keys));
                             break;
 
                         case DEPROVISION:
-                            profile.getResults().addAll(deprovision(delta, keys, false));
+                            profile.getResults().addAll(deprovision(processed, keys, false));
                             break;
 
                         case UNASSIGN:
-                            profile.getResults().addAll(deprovision(delta, keys, true));
+                            profile.getResults().addAll(deprovision(processed, keys, true));
                             break;
 
                         case LINK:
-                            profile.getResults().addAll(link(delta, keys, false));
+                            profile.getResults().addAll(link(processed, keys, false));
                             break;
 
                         case UNLINK:
-                            profile.getResults().addAll(link(delta, keys, true));
+                            profile.getResults().addAll(link(processed, keys, true));
                             break;
 
                         case IGNORE:
-                            profile.getResults().add(ignore(delta, true));
+                            profile.getResults().add(ignore(processed, true));
                             break;
 
                         default:
                         // do nothing
                     }
                 }
-            } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+            } else if (SyncDeltaType.DELETE == processed.getDeltaType()) {
                 if (keys.isEmpty()) {
-                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+                    finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, processed);
                     LOG.debug("No match found for deletion");
                 } else {
-                    profile.getResults().addAll(delete(delta, keys));
+                    profile.getResults().addAll(delete(processed, keys));
                 }
             }
         } catch (IllegalStateException | IllegalArgumentException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
index 7afbada..9de3f2f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/GoogleAppsPullActions.java
@@ -81,41 +81,33 @@ public class GoogleAppsPullActions implements PullActions {
     }
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
 
-        if (!(entity instanceof UserTO)) {
-            return delta;
-        }
-
-        UserTO userTO = (UserTO) entity;
-        if (userTO.getUsername() == null) {
-            userTO.setUsername(delta.getObject().getName().getNameValue());
+        if (entity instanceof UserTO) {
+            UserTO userTO = (UserTO) entity;
+            if (userTO.getUsername() == null) {
+                userTO.setUsername(delta.getObject().getName().getNameValue());
+            }
         }
-
-        return delta;
     }
 
     @Override
-    public <P extends AnyPatch> SyncDelta beforeUpdate(
+    public <P extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity,
             final P anyPatch) throws JobExecutionException {
 
-        if (!(anyPatch instanceof UserPatch)) {
-            return delta;
-        }
-
-        UserPatch userPatch = (UserPatch) anyPatch;
-        if (userPatch.getUsername() == null) {
-            userPatch.setUsername(new StringReplacePatchItem.Builder().
-                    value(delta.getObject().getName().getNameValue()).build());
+        if (anyPatch instanceof UserPatch) {
+            UserPatch userPatch = (UserPatch) anyPatch;
+            if (userPatch.getUsername() == null) {
+                userPatch.setUsername(new StringReplacePatchItem.Builder().
+                        value(delta.getObject().getName().getNameValue()).build());
+            }
         }
-
-        return delta;
     }
 
     @Transactional

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
index 0761e09..22c83ec 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
@@ -55,7 +55,7 @@ public class LDAPPasswordPullActions implements PullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entity) throws JobExecutionException {
@@ -64,13 +64,11 @@ public class LDAPPasswordPullActions implements PullActions {
             String password = ((UserTO) entity).getPassword();
             parseEncodedPassword(password);
         }
-
-        return delta;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -80,8 +78,6 @@ public class LDAPPasswordPullActions implements PullActions {
             PasswordPatch modPassword = ((UserPatch) anyPatch).getPassword();
             parseEncodedPassword(modPassword == null ? null : modPassword.getValue());
         }
-
-        return delta;
     }
 
     private void parseEncodedPassword(final String password) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e3ac8999/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
index a32a1be..54e9510 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPullActions.java
@@ -40,7 +40,7 @@ public class TestPullActions implements PullActions {
     private int counter;
 
     @Override
-    public SyncDelta beforeProvision(
+    public void beforeProvision(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
@@ -56,24 +56,20 @@ public class TestPullActions implements PullActions {
             attrTO.get().getValues().clear();
             attrTO.get().getValues().add(String.valueOf(counter++));
         }
-
-        return delta;
     }
 
     @Override
-    public SyncDelta beforeAssign(
+    public void beforeAssign(
             final ProvisioningProfile<?, ?> profile, final SyncDelta delta, final EntityTO entity)
             throws JobExecutionException {
 
         if (entity instanceof UserTO && "test2".equals(UserTO.class.cast(entity).getUsername())) {
             throw new IgnoreProvisionException();
         }
-
-        return delta;
     }
 
     @Override
-    public <M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> void beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final EntityTO entityTO,
@@ -94,7 +90,5 @@ public class TestPullActions implements PullActions {
 
         fullnamePatch.getAttrTO().getValues().clear();
         fullnamePatch.getAttrTO().getValues().add(String.valueOf(counter++));
-
-        return delta;
     }
 }