http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
new file mode 100644
index 0000000..ed1a702
--- /dev/null
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.pushpull;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.IteratorUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.policy.PullPolicySpec;
+import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile;
+import org.identityconnectors.framework.common.objects.SyncResultsHandler;
+import org.identityconnectors.framework.common.objects.SyncToken;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import 
org.apache.syncope.core.provisioning.api.pushpull.ReconciliationFilterBuilder;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import 
org.apache.syncope.core.provisioning.api.pushpull.AnyObjectPullResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
+import 
org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.UserPullResultHandler;
+
+public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> 
{
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private GroupDAO groupDAO;
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    protected PullUtils pullUtils;
+
+    protected void setGroupOwners(final GroupPullResultHandler ghandler) {
+        for (Map.Entry<Long, String> entry : 
ghandler.getGroupOwnerMap().entrySet()) {
+            Group group = groupDAO.find(entry.getKey());
+            if (group == null) {
+                throw new NotFoundException("Group " + entry.getKey());
+            }
+
+            if (StringUtils.isBlank(entry.getValue())) {
+                group.setGroupOwner(null);
+                group.setUserOwner(null);
+            } else {
+                Long userKey = pullUtils.findMatchingAnyKey(
+                        anyTypeDAO.findUser(),
+                        entry.getValue(),
+                        ghandler.getProfile().getTask().getResource(),
+                        ghandler.getProfile().getConnector());
+
+                if (userKey == null) {
+                    Long groupKey = pullUtils.findMatchingAnyKey(
+                            anyTypeDAO.findGroup(),
+                            entry.getValue(),
+                            ghandler.getProfile().getTask().getResource(),
+                            ghandler.getProfile().getConnector());
+
+                    if (groupKey != null) {
+                        group.setGroupOwner(groupDAO.find(groupKey));
+                    }
+                } else {
+                    group.setUserOwner(userDAO.find(userKey));
+                }
+            }
+
+            groupDAO.save(group);
+        }
+    }
+
+    @Override
+    protected String doExecuteProvisioning(
+            final PullTask pullTask,
+            final Connector connector,
+            final boolean dryRun) throws JobExecutionException {
+
+        LOG.debug("Executing pull on {}", pullTask.getResource());
+
+        List<PullActions> actions = new ArrayList<>();
+        for (String className : pullTask.getActionsClassNames()) {
+            try {
+                Class<?> actionsClass = Class.forName(className);
+                PullActions pullActions = (PullActions) 
ApplicationContextProvider.getBeanFactory().
+                        createBean(actionsClass, 
AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+
+                actions.add(pullActions);
+            } catch (Exception e) {
+                LOG.warn("Class '{}' not found", className, e);
+            }
+        }
+
+        ProvisioningProfile<PullTask, PullActions> profile = new 
ProvisioningProfile<>(connector, pullTask);
+        profile.getActions().addAll(actions);
+        profile.setDryRun(dryRun);
+        
profile.setResAct(getPullPolicySpec(pullTask).getConflictResolutionAction());
+
+        // Prepare handler for SyncDelta objects (any objects)
+        AnyObjectPullResultHandler ahandler = (AnyObjectPullResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(AnyObjectPullResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        ahandler.setProfile(profile);
+
+        // Prepare handler for SyncDelta objects (users)
+        UserPullResultHandler uhandler = (UserPullResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(UserPullResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        uhandler.setProfile(profile);
+
+        // Prepare handler for SyncDelta objects (groups)
+        GroupPullResultHandler ghandler = (GroupPullResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(GroupPullResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        ghandler.setProfile(profile);
+
+        if (!profile.isDryRun()) {
+            for (PullActions action : actions) {
+                action.beforeAll(profile);
+            }
+        }
+
+        for (Provision provision : pullTask.getResource().getProvisions()) {
+            if (provision.getMapping() != null) {
+                SyncResultsHandler handler;
+                switch (provision.getAnyType().getKind()) {
+                    case USER:
+                        handler = uhandler;
+                        break;
+
+                    case GROUP:
+                        handler = ghandler;
+                        break;
+
+                    case ANY_OBJECT:
+                    default:
+                        handler = ahandler;
+                }
+
+                try {
+                    Set<MappingItem> linkinMappingItems = new HashSet<>();
+                    for (VirSchema virSchema : 
virSchemaDAO.findByProvision(provision)) {
+                        
linkinMappingItems.add(virSchema.asLinkingMappingItem());
+                    }
+                    Iterator<MappingItem> mapItems = 
IteratorUtils.chainedIterator(
+                            provision.getMapping().getItems().iterator(),
+                            linkinMappingItems.iterator());
+
+                    switch (pullTask.getPullMode()) {
+                        case INCREMENTAL:
+                            SyncToken latestSyncToken = 
connector.getLatestSyncToken(provision.getObjectClass());
+                            connector.sync(provision.getObjectClass(),
+                                    provision.getSyncToken(),
+                                    handler,
+                                    
MappingManagerImpl.buildOperationOptions(mapItems));
+                            if (!dryRun) {
+                                provision.setSyncToken(latestSyncToken);
+                                resourceDAO.save(provision.getResource());
+                            }
+                            break;
+
+                        case FILTERED_RECONCILIATION:
+                            ReconciliationFilterBuilder filterBuilder =
+                                    (ReconciliationFilterBuilder) 
ApplicationContextProvider.getBeanFactory().
+                                    
createBean(Class.forName(pullTask.getReconciliationFilterBuilderClassName()),
+                                            
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+                            
connector.filteredReconciliation(provision.getObjectClass(),
+                                    filterBuilder,
+                                    handler,
+                                    
MappingManagerImpl.buildOperationOptions(mapItems));
+                            break;
+
+                        case FULL_RECONCILIATION:
+                        default:
+                            
connector.fullReconciliation(provision.getObjectClass(),
+                                    handler,
+                                    
MappingManagerImpl.buildOperationOptions(mapItems));
+                            break;
+                    }
+                } catch (Throwable t) {
+                    throw new JobExecutionException("While pulling from 
connector", t);
+                }
+            }
+        }
+
+        try {
+            setGroupOwners(ghandler);
+        } catch (Exception e) {
+            LOG.error("While setting group owners", e);
+        }
+
+        if (!profile.isDryRun()) {
+            for (PullActions action : actions) {
+                action.afterAll(profile);
+            }
+        }
+
+        String result = createReport(profile.getResults(), 
pullTask.getResource().getPullTraceLevel(), dryRun);
+
+        LOG.debug("Pull result: {}", result);
+
+        return result;
+    }
+
+    private PullPolicySpec getPullPolicySpec(final ProvisioningTask task) {
+        PullPolicySpec pullPolicySpec;
+
+        if (task instanceof PullTask) {
+            pullPolicySpec = task.getResource().getPullPolicy() == null
+                    ? null
+                    : task.getResource().getPullPolicy().getSpecification();
+        } else {
+            pullPolicySpec = null;
+        }
+
+        // step required because the call <policy>.getSpecification() could 
return a null value
+        return pullPolicySpec == null ? new PullPolicySpec() : pullPolicySpec;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
new file mode 100644
index 0000000..a0f558c
--- /dev/null
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.pushpull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.policy.PullPolicySpec;
+import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import 
org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import 
org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
+import org.identityconnectors.framework.common.objects.ResultsHandler;
+import org.identityconnectors.framework.common.objects.filter.EqualsFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+
+@Transactional(readOnly = true)
+@Component
+public class PullUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PullUtils.class);
+
+    /**
+     * Schema DAO.
+     */
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    /**
+     * Any Object DAO.
+     */
+    @Autowired
+    private AnyObjectDAO anyObjectDAO;
+
+    /**
+     * User DAO.
+     */
+    @Autowired
+    private UserDAO userDAO;
+
+    /**
+     * Group DAO.
+     */
+    @Autowired
+    private GroupDAO groupDAO;
+
+    /**
+     * Search DAO.
+     */
+    @Autowired
+    private AnySearchDAO searchDAO;
+
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
+    public Long findMatchingAnyKey(
+            final AnyType anyType,
+            final String name,
+            final ExternalResource resource,
+            final Connector connector) {
+
+        Provision provision = resource.getProvision(anyType);
+        if (provision == null) {
+            return null;
+        }
+
+        Long result = null;
+
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(anyType.getKind());
+
+        final List<ConnectorObject> found = new ArrayList<>();
+        connector.search(provision.getObjectClass(),
+                new EqualsFilter(new Name(name)),
+                new ResultsHandler() {
+
+            @Override
+            public boolean handle(final ConnectorObject obj) {
+                return found.add(obj);
+            }
+        },
+                
MappingManagerImpl.buildOperationOptions(MappingManagerImpl.getPullMappingItems(provision).iterator()));
+
+        if (found.isEmpty()) {
+            LOG.debug("No {} found on {} with __NAME__ {}", 
provision.getObjectClass(), resource, name);
+        } else {
+            if (found.size() > 1) {
+                LOG.warn("More than one {} found on {} with __NAME__ {} - 
taking first only",
+                        provision.getObjectClass(), resource, name);
+            }
+
+            ConnectorObject connObj = found.iterator().next();
+            try {
+                List<Long> anyKeys = 
findExisting(connObj.getUid().getUidValue(), connObj, provision, anyUtils);
+                if (anyKeys.isEmpty()) {
+                    LOG.debug("No matching {} found for {}, aborting", 
anyUtils.getAnyTypeKind(), connObj);
+                } else {
+                    if (anyKeys.size() > 1) {
+                        LOG.warn("More than one {} found {} - taking first 
only", anyUtils.getAnyTypeKind(), anyKeys);
+                    }
+
+                    result = anyKeys.iterator().next();
+                }
+            } catch (IllegalArgumentException e) {
+                LOG.warn(e.getMessage());
+            }
+        }
+
+        return result;
+    }
+
+    private AnyDAO<?> getAnyDAO(final MappingItem connObjectKeyItem) {
+        return AnyTypeKind.USER == 
connObjectKeyItem.getIntMappingType().getAnyTypeKind()
+                ? userDAO
+                : AnyTypeKind.ANY_OBJECT == 
connObjectKeyItem.getIntMappingType().getAnyTypeKind()
+                        ? anyObjectDAO
+                        : groupDAO;
+    }
+
+    private List<Long> findByConnObjectKeyItem(
+            final String uid, final Provision provision, final AnyUtils 
anyUtils) {
+
+        List<Long> result = new ArrayList<>();
+
+        MappingItem connObjectKeyItem = 
MappingManagerImpl.getConnObjectKeyItem(provision);
+
+        String transfUid = uid;
+        for (MappingItemTransformer transformer : 
MappingManagerImpl.getMappingItemTransformers(connObjectKeyItem)) {
+            List<Object> output = 
transformer.beforePull(Collections.<Object>singletonList(transfUid));
+            if (output != null && !output.isEmpty()) {
+                transfUid = output.get(0).toString();
+            }
+        }
+
+        switch (connObjectKeyItem.getIntMappingType()) {
+            case UserPlainSchema:
+            case GroupPlainSchema:
+            case AnyObjectPlainSchema:
+                PlainAttrValue value = anyUtils.newPlainAttrValue();
+
+                PlainSchema schema = 
plainSchemaDAO.find(connObjectKeyItem.getIntAttrName());
+                if (schema == null) {
+                    value.setStringValue(transfUid);
+                } else {
+                    try {
+                        value.parseValue(schema, transfUid);
+                    } catch (ParsingValidationException e) {
+                        LOG.error("While parsing provided __UID__ {}", 
transfUid, e);
+                        value.setStringValue(transfUid);
+                    }
+                }
+
+                List<? extends Any<?>> anys =
+                        
getAnyDAO(connObjectKeyItem).findByAttrValue(connObjectKeyItem.getIntAttrName(),
 value);
+                for (Any<?> any : anys) {
+                    result.add(any.getKey());
+                }
+                break;
+
+            case UserDerivedSchema:
+            case GroupDerivedSchema:
+            case AnyObjectDerivedSchema:
+                anys = 
getAnyDAO(connObjectKeyItem).findByDerAttrValue(connObjectKeyItem.getIntAttrName(),
 transfUid);
+                for (Any<?> any : anys) {
+                    result.add(any.getKey());
+                }
+                break;
+
+            case UserKey:
+            case GroupKey:
+            case AnyObjectKey:
+                Any<?> any = 
getAnyDAO(connObjectKeyItem).find(Long.parseLong(transfUid));
+                if (any != null) {
+                    result.add(any.getKey());
+                }
+                break;
+
+            case Username:
+                User user = userDAO.find(transfUid);
+                if (user != null) {
+                    result.add(user.getKey());
+                }
+                break;
+
+            case GroupName:
+                Group group = groupDAO.find(transfUid);
+                if (group != null) {
+                    result.add(group.getKey());
+                }
+                break;
+
+            default:
+                LOG.error("Invalid connObjectKey type '{}'", 
connObjectKeyItem.getIntMappingType());
+        }
+
+        return result;
+    }
+
+    private List<Long> findByCorrelationRule(
+            final ConnectorObject connObj, final PullCorrelationRule rule, 
final AnyTypeKind type) {
+
+        List<Long> result = new ArrayList<>();
+        for (Any<?> any : searchDAO.search(rule.getSearchCond(connObj), type)) 
{
+            result.add(any.getKey());
+        }
+
+        return result;
+    }
+
+    private PullCorrelationRule getCorrelationRule(final Provision provision, 
final PullPolicySpec policySpec) {
+        PullCorrelationRule result = null;
+
+        String pullCorrelationRule = 
policySpec.getCorrelationRules().get(provision.getAnyType().getKey());
+        if (StringUtils.isNotBlank(pullCorrelationRule)) {
+            if (pullCorrelationRule.charAt(0) == '[') {
+                result = new PlainAttrsPullCorrelationRule(
+                        POJOHelper.deserialize(pullCorrelationRule, 
String[].class), provision);
+            } else {
+                try {
+                    result = (PullCorrelationRule) 
Class.forName(pullCorrelationRule).newInstance();
+                } catch (Exception e) {
+                    LOG.error("Failure instantiating correlation rule class 
'{}'", pullCorrelationRule, e);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Find any objects based on mapped uid value (or previous uid value, if 
updated).
+     *
+     * @param uid for finding by connObjectKey
+     * @param connObj for finding by attribute value
+     * @param provision external resource
+     * @param anyUtils any util
+     * @return list of matching users / groups
+     */
+    public List<Long> findExisting(
+            final String uid,
+            final ConnectorObject connObj,
+            final Provision provision,
+            final AnyUtils anyUtils) {
+
+        PullPolicySpec pullPolicySpec = null;
+        if (provision.getResource().getPullPolicy() != null) {
+            pullPolicySpec = 
provision.getResource().getPullPolicy().getSpecification();
+        }
+
+        PullCorrelationRule pullRule = null;
+        if (pullPolicySpec != null) {
+            pullRule = getCorrelationRule(provision, pullPolicySpec);
+        }
+
+        return pullRule == null
+                ? findByConnObjectKeyItem(uid, provision, anyUtils)
+                : findByCorrelationRule(connObj, pullRule, 
anyUtils.getAnyTypeKind());
+    }
+
+    public Boolean readEnabled(final ConnectorObject connectorObject, final 
ProvisioningTask task) {
+        Boolean enabled = null;
+        if (task.isPullStatus()) {
+            Attribute status = 
AttributeUtil.find(OperationalAttributes.ENABLE_NAME, 
connectorObject.getAttributes());
+            if (status != null && status.getValue() != null && 
!status.getValue().isEmpty()) {
+                enabled = (Boolean) status.getValue().get(0);
+            }
+        }
+
+        return enabled;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
new file mode 100644
index 0000000..563c64a
--- /dev/null
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.pushpull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import 
org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.task.PushTask;
+import org.apache.syncope.core.provisioning.api.Connector;
+import 
org.apache.syncope.core.provisioning.api.pushpull.AnyObjectPushResultHandler;
+import 
org.apache.syncope.core.provisioning.api.pushpull.GroupPushResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile;
+import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
+import 
org.apache.syncope.core.provisioning.api.pushpull.SyncopePushResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.UserPushResultHandler;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+
+public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> 
{
+
+    private static final int PAGE_SIZE = 1000;
+
+    /**
+     * User DAO.
+     */
+    @Autowired
+    private UserDAO userDAO;
+
+    /**
+     * Search DAO.
+     */
+    @Autowired
+    private AnySearchDAO searchDAO;
+
+    /**
+     * Group DAO.
+     */
+    @Autowired
+    private GroupDAO groupDAO;
+
+    @Autowired
+    private AnyObjectDAO anyObjectDAO;
+
+    private AnyDAO<?> getAnyDAO(final AnyTypeKind anyTypeKind) {
+        AnyDAO<?> result;
+        switch (anyTypeKind) {
+            case USER:
+                result = userDAO;
+                break;
+
+            case GROUP:
+                result = groupDAO;
+                break;
+
+            case ANY_OBJECT:
+            default:
+                result = anyObjectDAO;
+        }
+
+        return result;
+    }
+
+    protected void handle(
+            final List<? extends Any<?>> anys,
+            final SyncopePushResultHandler handler,
+            final ExternalResource resource)
+            throws JobExecutionException {
+
+        for (Any<?> any : anys) {
+            try {
+                handler.handle(any.getKey());
+            } catch (Exception e) {
+                LOG.warn("Failure pushing '{}' on '{}'", any, resource, e);
+                throw new JobExecutionException("While pushing " + any + " on 
" + resource, e);
+            }
+        }
+    }
+
+    @Override
+    protected String doExecuteProvisioning(
+            final PushTask pushTask,
+            final Connector connector,
+            final boolean dryRun) throws JobExecutionException {
+
+        LOG.debug("Executing push on {}", pushTask.getResource());
+
+        List<PushActions> actions = new ArrayList<>();
+        for (String className : pushTask.getActionsClassNames()) {
+            try {
+                Class<?> actionsClass = Class.forName(className);
+
+                PushActions pushActions = (PushActions) 
ApplicationContextProvider.getBeanFactory().
+                        createBean(actionsClass, 
AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+                actions.add(pushActions);
+            } catch (Exception e) {
+                LOG.info("Class '{}' not found", className, e);
+            }
+        }
+
+        ProvisioningProfile<PushTask, PushActions> profile = new 
ProvisioningProfile<>(connector, pushTask);
+        profile.setDryRun(dryRun);
+        profile.setResAct(null);
+
+        AnyObjectPushResultHandler ahandler =
+                (AnyObjectPushResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(AnyObjectPushResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        ahandler.setProfile(profile);
+
+        UserPushResultHandler uhandler =
+                (UserPushResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(UserPushResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        uhandler.setProfile(profile);
+
+        GroupPushResultHandler ghandler =
+                (GroupPushResultHandler) 
ApplicationContextProvider.getBeanFactory().
+                createBean(GroupPushResultHandlerImpl.class, 
AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        ghandler.setProfile(profile);
+
+        if (!profile.isDryRun()) {
+            for (PushActions action : actions) {
+                action.beforeAll(profile);
+            }
+        }
+
+        for (Provision provision : pushTask.getResource().getProvisions()) {
+            if (provision.getMapping() != null) {
+                AnyDAO<?> anyDAO = getAnyDAO(provision.getAnyType().getKind());
+
+                SyncopePushResultHandler handler;
+                switch (provision.getAnyType().getKind()) {
+                    case USER:
+                        handler = uhandler;
+                        break;
+
+                    case GROUP:
+                        handler = ghandler;
+                        break;
+
+                    case ANY_OBJECT:
+                    default:
+                        handler = ahandler;
+                }
+
+                String filter = pushTask.getFilter(provision.getAnyType()) == 
null
+                        ? null
+                        : 
pushTask.getFilter(provision.getAnyType()).getFIQLCond();
+                if (StringUtils.isBlank(filter)) {
+                    handle(anyDAO.findAll(), handler, pushTask.getResource());
+                } else {
+                    int count = 
anyDAO.count(SyncopeConstants.FULL_ADMIN_REALMS);
+                    for (int page = 1; page <= (count / PAGE_SIZE) + 1; 
page++) {
+                        List<? extends Any<?>> anys = searchDAO.search(
+                                SyncopeConstants.FULL_ADMIN_REALMS,
+                                SearchCondConverter.convert(filter),
+                                page,
+                                PAGE_SIZE,
+                                Collections.<OrderByClause>emptyList(),
+                                provision.getAnyType().getKind());
+                        handle(anys, handler, pushTask.getResource());
+                    }
+                }
+            }
+        }
+
+        if (!profile.isDryRun()) {
+            for (PushActions action : actions) {
+                action.afterAll(profile);
+            }
+        }
+
+        String result = createReport(profile.getResults(), 
pushTask.getResource().getPullTraceLevel(), dryRun);
+        LOG.debug("Sync result: {}", result);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPullResultHandlerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPullResultHandlerImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPullResultHandlerImpl.java
new file mode 100644
index 0000000..ddc01fb
--- /dev/null
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPullResultHandlerImpl.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.pushpull;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.provisioning.api.ProvisioningManager;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
+import org.identityconnectors.framework.common.objects.SyncDelta;
+import org.apache.syncope.core.provisioning.api.pushpull.UserPullResultHandler;
+
+public class UserPullResultHandlerImpl extends AbstractPullResultHandler 
implements UserPullResultHandler {
+
+    @Override
+    protected AnyUtils getAnyUtils() {
+        return anyUtilsFactory.getInstance(AnyTypeKind.USER);
+    }
+
+    @Override
+    protected String getName(final AnyTO anyTO) {
+        return UserTO.class.cast(anyTO).getUsername();
+    }
+
+    @Override
+    protected ProvisioningManager<?, ?> getProvisioningManager() {
+        return userProvisioningManager;
+    }
+
+    @Override
+    protected Any<?> getAny(final long key) {
+        try {
+            return userDAO.authFind(key);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", key, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected AnyTO getAnyTO(final long key) {
+        return userDataBinder.getUserTO(key);
+    }
+
+    @Override
+    protected AnyPatch newPatch(final long key) {
+        UserPatch patch = new UserPatch();
+        patch.setKey(key);
+        return patch;
+    }
+
+    @Override
+    protected WorkflowResult<Long> update(final AnyPatch patch) {
+        WorkflowResult<Pair<UserPatch, Boolean>> update = 
uwfAdapter.update((UserPatch) patch);
+        return new WorkflowResult<>(
+                update.getResult().getLeft().getKey(), update.getPropByRes(), 
update.getPerformedTasks());
+    }
+
+    @Override
+    protected AnyTO doCreate(final AnyTO anyTO, final SyncDelta delta, final 
ProvisioningReport result) {
+        UserTO userTO = UserTO.class.cast(anyTO);
+
+        Boolean enabled = pullUtils.readEnabled(delta.getObject(), 
profile.getTask());
+        Map.Entry<Long, List<PropagationStatus>> created =
+                userProvisioningManager.create(userTO, true, true, enabled,
+                        
Collections.singleton(profile.getTask().getResource().getKey()), true);
+
+        result.setKey(created.getKey());
+        result.setName(getName(anyTO));
+
+        return getAnyTO(created.getKey());
+    }
+
+    @Override
+    protected AnyTO doUpdate(
+            final AnyTO before,
+            final AnyPatch anyPatch,
+            final SyncDelta delta,
+            final ProvisioningReport result) {
+
+        UserPatch userPatch = UserPatch.class.cast(anyPatch);
+        Boolean enabled = pullUtils.readEnabled(delta.getObject(), 
profile.getTask());
+
+        Map.Entry<Long, List<PropagationStatus>> updated = 
userProvisioningManager.update(
+                userPatch,
+                result,
+                enabled,
+                
Collections.singleton(profile.getTask().getResource().getKey()),
+                true);
+
+        return getAnyTO(updated.getKey());
+    }
+
+    @Override
+    protected void doDelete(final AnyTypeKind kind, final Long key) {
+        try {
+            userProvisioningManager.delete(
+                    key, 
Collections.<String>singleton(profile.getTask().getResource().getKey()), true);
+        } catch (Exception e) {
+            // A propagation failure doesn't imply a pull failure.
+            // The propagation exception status will be reported into the 
propagation task execution.
+            LOG.error("Could not propagate user " + key, e);
+        }
+
+        uwfAdapter.delete(key);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPushResultHandlerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPushResultHandlerImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPushResultHandlerImpl.java
new file mode 100644
index 0000000..bc63845
--- /dev/null
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/UserPushResultHandlerImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.pushpull;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.pushpull.UserPushResultHandler;
+
+public class UserPushResultHandlerImpl extends AbstractPushResultHandler 
implements UserPushResultHandler {
+
+    @Override
+    protected AnyUtils getAnyUtils() {
+        return anyUtilsFactory.getInstance(AnyTypeKind.USER);
+    }
+
+    @Override
+    protected void provision(final Any<?> any, final Boolean enabled) {
+        AnyTO before = getAnyTO(any.getKey());
+
+        List<String> noPropResources = new ArrayList<>(before.getResources());
+        noPropResources.remove(profile.getTask().getResource().getKey());
+
+        PropagationByResource propByRes = new PropagationByResource();
+        propByRes.add(ResourceOperation.CREATE, 
profile.getTask().getResource().getKey());
+
+        taskExecutor.execute(propagationManager.getUserCreateTasks(
+                before.getKey(),
+                null,
+                enabled,
+                propByRes,
+                before.getVirAttrs(),
+                noPropResources));
+    }
+
+    @Override
+    protected String getName(final Any<?> any) {
+        return User.class.cast(any).getUsername();
+    }
+
+    @Override
+    protected Any<?> getAny(final long key) {
+        try {
+            return userDAO.authFind(key);
+        } catch (Exception e) {
+            LOG.warn("Error retrieving user {}", key, e);
+            return null;
+        }
+    }
+
+    @Override
+    protected AnyTO getAnyTO(final long key) {
+        return userDataBinder.getUserTO(key);
+    }
+
+    @Override
+    protected AnyPatch newPatch(final long key) {
+        UserPatch patch = new UserPatch();
+        patch.setKey(key);
+        return patch;
+    }
+
+    @Override
+    protected WorkflowResult<Long> update(final AnyPatch patch) {
+        WorkflowResult<Pair<UserPatch, Boolean>> update = 
uwfAdapter.update((UserPatch) patch);
+        return new WorkflowResult<>(
+                update.getResult().getLeft().getKey(), update.getPropByRes(), 
update.getPerformedTasks());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractProvisioningJobDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractProvisioningJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractProvisioningJobDelegate.java
deleted file mode 100644
index bd13365..0000000
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractProvisioningJobDelegate.java
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.java.syncpull;
-
-import java.lang.reflect.ParameterizedType;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import javax.annotation.Resource;
-import org.apache.syncope.common.lib.types.TraceLevel;
-import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
-import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
-import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
-import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
-import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
-import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
-import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.provisioning.api.syncpull.ProvisioningReport;
-import 
org.apache.syncope.core.provisioning.java.job.AbstractSchedTaskJobDelegate;
-import org.apache.syncope.core.provisioning.java.job.TaskJob;
-import org.quartz.JobExecutionException;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public abstract class AbstractProvisioningJobDelegate<T extends 
ProvisioningTask>
-        extends AbstractSchedTaskJobDelegate {
-
-    @Resource(name = "adminUser")
-    protected String adminUser;
-
-    /**
-     * ConnInstance loader.
-     */
-    @Autowired
-    protected ConnectorFactory connFactory;
-
-    @Autowired
-    protected AnyTypeDAO anyTypeDAO;
-
-    /**
-     * Resource DAO.
-     */
-    @Autowired
-    protected ExternalResourceDAO resourceDAO;
-
-    /**
-     * Policy DAO.
-     */
-    @Autowired
-    protected PolicyDAO policyDAO;
-
-    /**
-     * Create a textual report of the synchronization, based on the trace 
level.
-     *
-     * @param provResults Sync results
-     * @param syncTraceLevel Sync trace level
-     * @param dryRun dry run?
-     * @return report as string
-     */
-    protected String createReport(final Collection<ProvisioningReport> 
provResults, final TraceLevel syncTraceLevel,
-            final boolean dryRun) {
-
-        if (syncTraceLevel == TraceLevel.NONE) {
-            return null;
-        }
-
-        StringBuilder report = new StringBuilder();
-
-        if (dryRun) {
-            report.append("==>Dry run only, no modifications were 
made<==\n\n");
-        }
-
-        List<ProvisioningReport> uSuccCreate = new ArrayList<>();
-        List<ProvisioningReport> uFailCreate = new ArrayList<>();
-        List<ProvisioningReport> uSuccUpdate = new ArrayList<>();
-        List<ProvisioningReport> uFailUpdate = new ArrayList<>();
-        List<ProvisioningReport> uSuccDelete = new ArrayList<>();
-        List<ProvisioningReport> uFailDelete = new ArrayList<>();
-        List<ProvisioningReport> uSuccNone = new ArrayList<>();
-        List<ProvisioningReport> uIgnore = new ArrayList<>();
-        List<ProvisioningReport> gSuccCreate = new ArrayList<>();
-        List<ProvisioningReport> gFailCreate = new ArrayList<>();
-        List<ProvisioningReport> gSuccUpdate = new ArrayList<>();
-        List<ProvisioningReport> gFailUpdate = new ArrayList<>();
-        List<ProvisioningReport> gSuccDelete = new ArrayList<>();
-        List<ProvisioningReport> gFailDelete = new ArrayList<>();
-        List<ProvisioningReport> gSuccNone = new ArrayList<>();
-        List<ProvisioningReport> gIgnore = new ArrayList<>();
-        List<ProvisioningReport> aSuccCreate = new ArrayList<>();
-        List<ProvisioningReport> aFailCreate = new ArrayList<>();
-        List<ProvisioningReport> aSuccUpdate = new ArrayList<>();
-        List<ProvisioningReport> aFailUpdate = new ArrayList<>();
-        List<ProvisioningReport> aSuccDelete = new ArrayList<>();
-        List<ProvisioningReport> aFailDelete = new ArrayList<>();
-        List<ProvisioningReport> aSuccNone = new ArrayList<>();
-        List<ProvisioningReport> aIgnore = new ArrayList<>();
-
-        for (ProvisioningReport provResult : provResults) {
-            AnyType anyType = anyTypeDAO.find(provResult.getAnyType());
-
-            switch (provResult.getStatus()) {
-                case SUCCESS:
-                    switch (provResult.getOperation()) {
-                        case CREATE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uSuccCreate.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gSuccCreate.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aSuccCreate.add(provResult);
-                            }
-                            break;
-
-                        case UPDATE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uSuccUpdate.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gSuccUpdate.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aSuccUpdate.add(provResult);
-                            }
-                            break;
-
-                        case DELETE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uSuccDelete.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gSuccDelete.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aSuccDelete.add(provResult);
-                            }
-                            break;
-
-                        case NONE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uSuccNone.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gSuccNone.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aSuccNone.add(provResult);
-                            }
-                            break;
-
-                        default:
-                    }
-                    break;
-
-                case FAILURE:
-                    switch (provResult.getOperation()) {
-                        case CREATE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uFailCreate.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gFailCreate.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aFailCreate.add(provResult);
-                            }
-                            break;
-
-                        case UPDATE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uFailUpdate.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gFailUpdate.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aFailUpdate.add(provResult);
-                            }
-                            break;
-
-                        case DELETE:
-                            switch (anyType.getKind()) {
-                                case USER:
-                                    uFailDelete.add(provResult);
-                                    break;
-
-                                case GROUP:
-                                    gFailDelete.add(provResult);
-                                    break;
-
-                                case ANY_OBJECT:
-                                default:
-                                    aFailDelete.add(provResult);
-                            }
-                            break;
-
-                        default:
-                    }
-                    break;
-
-                case IGNORE:
-                    switch (anyType.getKind()) {
-                        case USER:
-                            uIgnore.add(provResult);
-                            break;
-
-                        case GROUP:
-                            gIgnore.add(provResult);
-                            break;
-
-                        case ANY_OBJECT:
-                        default:
-                            aIgnore.add(provResult);
-                    }
-                    break;
-
-                default:
-            }
-        }
-
-        // Summary, also to be included for FAILURE and ALL, so create it 
anyway.
-        report.append("Users ").
-                append("[created/failures]: 
").append(uSuccCreate.size()).append('/').append(uFailCreate.size()).
-                append(' ').
-                append("[updated/failures]: 
").append(uSuccUpdate.size()).append('/').append(uFailUpdate.size()).
-                append(' ').
-                append("[deleted/failures]: 
").append(uSuccDelete.size()).append('/').append(uFailDelete.size()).
-                append(' ').
-                append("[no operation/ignored]: 
").append(uSuccNone.size()).append('/').append(uIgnore.size()).
-                append('\n');
-        report.append("Groups ").
-                append("[created/failures]: 
").append(gSuccCreate.size()).append('/').append(gFailCreate.size()).
-                append(' ').
-                append("[updated/failures]: 
").append(gSuccUpdate.size()).append('/').append(gFailUpdate.size()).
-                append(' ').
-                append("[deleted/failures]: 
").append(gSuccDelete.size()).append('/').append(gFailDelete.size()).
-                append(' ').
-                append("[no operation/ignored]: 
").append(gSuccNone.size()).append('/').append(gIgnore.size()).
-                append('\n');
-        report.append("Any objects ").
-                append("[created/failures]: 
").append(aSuccCreate.size()).append('/').append(aFailCreate.size()).
-                append(' ').
-                append("[updated/failures]: 
").append(aSuccUpdate.size()).append('/').append(aFailUpdate.size()).
-                append(' ').
-                append("[deleted/failures]: 
").append(aSuccDelete.size()).append('/').append(aFailDelete.size()).
-                append(' ').
-                append("[no operation/ignored]: 
").append(aSuccNone.size()).append('/').append(aIgnore.size());
-
-        // Failures
-        if (syncTraceLevel == TraceLevel.FAILURES || syncTraceLevel == 
TraceLevel.ALL) {
-            if (!uFailCreate.isEmpty()) {
-                report.append("\n\nUsers failed to create: ");
-                report.append(ProvisioningReport.produceReport(uFailCreate, 
syncTraceLevel));
-            }
-            if (!uFailUpdate.isEmpty()) {
-                report.append("\nUsers failed to update: ");
-                report.append(ProvisioningReport.produceReport(uFailUpdate, 
syncTraceLevel));
-            }
-            if (!uFailDelete.isEmpty()) {
-                report.append("\nUsers failed to delete: ");
-                report.append(ProvisioningReport.produceReport(uFailDelete, 
syncTraceLevel));
-            }
-
-            if (!gFailCreate.isEmpty()) {
-                report.append("\n\nGroups failed to create: ");
-                report.append(ProvisioningReport.produceReport(gFailCreate, 
syncTraceLevel));
-            }
-            if (!gFailUpdate.isEmpty()) {
-                report.append("\nGroups failed to update: ");
-                report.append(ProvisioningReport.produceReport(gFailUpdate, 
syncTraceLevel));
-            }
-            if (!gFailDelete.isEmpty()) {
-                report.append("\nGroups failed to delete: ");
-                report.append(ProvisioningReport.produceReport(gFailDelete, 
syncTraceLevel));
-            }
-
-            if (!aFailCreate.isEmpty()) {
-                report.append("\nAny objects failed to create: ");
-                report.append(ProvisioningReport.produceReport(aFailCreate, 
syncTraceLevel));
-            }
-            if (!aFailUpdate.isEmpty()) {
-                report.append("\nAny objects failed to update: ");
-                report.append(ProvisioningReport.produceReport(aFailUpdate, 
syncTraceLevel));
-            }
-            if (!aFailDelete.isEmpty()) {
-                report.append("\nAny objects failed to delete: ");
-                report.append(ProvisioningReport.produceReport(aFailDelete, 
syncTraceLevel));
-            }
-        }
-
-        // Succeeded, only if on 'ALL' level
-        if (syncTraceLevel == TraceLevel.ALL) {
-            report.append("\n\nUsers created:\n").
-                    append(ProvisioningReport.produceReport(uSuccCreate, 
syncTraceLevel)).
-                    append("\nUsers updated:\n").
-                    append(ProvisioningReport.produceReport(uSuccUpdate, 
syncTraceLevel)).
-                    append("\nUsers deleted:\n").
-                    append(ProvisioningReport.produceReport(uSuccDelete, 
syncTraceLevel)).
-                    append("\nUsers no operation:\n").
-                    append(ProvisioningReport.produceReport(uSuccNone, 
syncTraceLevel)).
-                    append("\nUsers ignored:\n").
-                    append(ProvisioningReport.produceReport(uIgnore, 
syncTraceLevel));
-            report.append("\n\nGroups created:\n").
-                    append(ProvisioningReport.produceReport(gSuccCreate, 
syncTraceLevel)).
-                    append("\nGroups updated:\n").
-                    append(ProvisioningReport.produceReport(gSuccUpdate, 
syncTraceLevel)).
-                    append("\nGroups deleted:\n").
-                    append(ProvisioningReport.produceReport(gSuccDelete, 
syncTraceLevel)).
-                    append("\nGroups no operation:\n").
-                    append(ProvisioningReport.produceReport(gSuccNone, 
syncTraceLevel)).
-                    append("\nGroups ignored:\n").
-                    append(ProvisioningReport.produceReport(gSuccNone, 
syncTraceLevel));
-            report.append("\n\nAny objects created:\n").
-                    append(ProvisioningReport.produceReport(aSuccCreate, 
syncTraceLevel)).
-                    append("\nAny objects updated:\n").
-                    append(ProvisioningReport.produceReport(aSuccUpdate, 
syncTraceLevel)).
-                    append("\nAny objects deleted:\n").
-                    append(ProvisioningReport.produceReport(aSuccDelete, 
syncTraceLevel)).
-                    append("\nAny objects no operation:\n").
-                    append(ProvisioningReport.produceReport(aSuccNone, 
syncTraceLevel)).
-                    append("\nAny objects ignored:\n").
-                    append(ProvisioningReport.produceReport(aSuccNone, 
syncTraceLevel));
-        }
-
-        return report.toString();
-    }
-
-    @Override
-    protected String doExecute(final boolean dryRun) throws 
JobExecutionException {
-        try {
-            Class<T> clazz = getTaskClassReference();
-            if (!clazz.isAssignableFrom(task.getClass())) {
-                throw new JobExecutionException("Task " + task.getKey() + " 
isn't a ProvisioningTask");
-            }
-
-            T provisioningTask = clazz.cast(task);
-
-            Connector connector;
-            try {
-                connector = 
connFactory.getConnector(provisioningTask.getResource());
-            } catch (Exception e) {
-                String msg = String.format("Connector instance bean for 
resource %s and connInstance %s not found",
-                        provisioningTask.getResource(), 
provisioningTask.getResource().getConnector());
-                throw new JobExecutionException(msg, e);
-            }
-
-            boolean noMapping = true;
-            for (Provision provision : 
provisioningTask.getResource().getProvisions()) {
-                Mapping mapping = provision.getMapping();
-                if (mapping != null) {
-                    noMapping = false;
-                    if (mapping.getConnObjectKeyItem() == null) {
-                        throw new JobExecutionException(
-                                "Invalid ConnObjectKey mapping for provision " 
+ provision);
-                    }
-                }
-            }
-            if (noMapping) {
-                return "No mapping configured for both users and groups: 
aborting...";
-            }
-
-            return doExecuteProvisioning(
-                    provisioningTask,
-                    connector,
-                    dryRun);
-        } catch (Throwable t) {
-            LOG.error("While executing provisioning job {}", 
getClass().getName(), t);
-            throw t;
-        }
-    }
-
-    protected abstract String doExecuteProvisioning(
-            final T task,
-            final Connector connector,
-            final boolean dryRun) throws JobExecutionException;
-
-    @Override
-    protected boolean hasToBeRegistered(final TaskExec execution) {
-        final ProvisioningTask provTask = (ProvisioningTask) task;
-
-        // True if either failed and failures have to be registered, or if ALL 
has to be registered.
-        return (TaskJob.Status.valueOf(execution.getStatus()) == 
TaskJob.Status.FAILURE
-                && provTask.getResource().getSyncTraceLevel().ordinal() >= 
TraceLevel.FAILURES.ordinal())
-                || provTask.getResource().getSyncTraceLevel().ordinal() >= 
TraceLevel.SUMMARY.ordinal();
-    }
-
-    @SuppressWarnings("unchecked")
-    private Class<T> getTaskClassReference() {
-        return (Class<T>) ((ParameterizedType) 
this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/61a7fdd3/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractPushResultHandler.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractPushResultHandler.java
deleted file mode 100644
index 258e106..0000000
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/syncpull/AbstractPushResultHandler.java
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.java.syncpull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.apache.commons.collections4.IteratorUtils;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.patch.StringPatchItem;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.AuditElements.Result;
-import org.apache.syncope.common.lib.types.MatchingRule;
-import org.apache.syncope.common.lib.types.PatchOperation;
-import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.common.lib.types.UnmatchingRule;
-import org.apache.syncope.core.persistence.api.entity.task.PushTask;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.syncpull.ProvisioningReport;
-import org.apache.syncope.core.provisioning.api.syncpull.PushActions;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.provisioning.api.MappingManager;
-import org.apache.syncope.core.provisioning.api.TimeoutException;
-import 
org.apache.syncope.core.provisioning.api.syncpull.IgnoreProvisionException;
-import 
org.apache.syncope.core.provisioning.api.syncpull.SyncopePushResultHandler;
-import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.identityconnectors.framework.common.objects.ObjectClass;
-import org.identityconnectors.framework.common.objects.Uid;
-import org.quartz.JobExecutionException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
-
-public abstract class AbstractPushResultHandler extends 
AbstractSyncopeResultHandler<PushTask, PushActions>
-        implements SyncopePushResultHandler {
-
-    @Autowired
-    protected MappingManager mappingManager;
-
-    protected abstract String getName(Any<?> any);
-
-    protected void deprovision(final Any<?> any) {
-        AnyTO before = getAnyTO(any.getKey());
-
-        List<String> noPropResources = new ArrayList<>(before.getResources());
-        noPropResources.remove(profile.getTask().getResource().getKey());
-
-        taskExecutor.execute(propagationManager.getDeleteTasks(
-                any.getType().getKind(),
-                any.getKey(),
-                null,
-                noPropResources));
-    }
-
-    protected void provision(final Any<?> any, final Boolean enabled) {
-        AnyTO before = getAnyTO(any.getKey());
-
-        List<String> noPropResources = new ArrayList<>(before.getResources());
-        noPropResources.remove(profile.getTask().getResource().getKey());
-
-        PropagationByResource propByRes = new PropagationByResource();
-        propByRes.add(ResourceOperation.CREATE, 
profile.getTask().getResource().getKey());
-
-        taskExecutor.execute(propagationManager.getCreateTasks(
-                any.getType().getKind(),
-                any.getKey(),
-                propByRes,
-                before.getVirAttrs(),
-                noPropResources));
-    }
-
-    @SuppressWarnings("unchecked")
-    protected void link(final Any<?> any, final Boolean unlink) {
-        AnyPatch patch = newPatch(any.getKey());
-        patch.getResources().add(new StringPatchItem.Builder().
-                operation(unlink ? PatchOperation.DELETE : 
PatchOperation.ADD_REPLACE).
-                value(profile.getTask().getResource().getKey()).build());
-
-        update(patch);
-    }
-
-    @SuppressWarnings("unchecked")
-    protected void unassign(final Any<?> any) {
-        AnyPatch patch = newPatch(any.getKey());
-        patch.getResources().add(new StringPatchItem.Builder().
-                operation(PatchOperation.DELETE).
-                value(profile.getTask().getResource().getKey()).build());
-
-        update(patch);
-
-        deprovision(any);
-    }
-
-    protected void assign(final Any<?> any, final Boolean enabled) {
-        AnyPatch patch = newPatch(any.getKey());
-        patch.getResources().add(new StringPatchItem.Builder().
-                operation(PatchOperation.ADD_REPLACE).
-                value(profile.getTask().getResource().getKey()).build());
-
-        update(patch);
-
-        provision(any, enabled);
-    }
-
-    protected ConnectorObject getRemoteObject(final String connObjectKey, 
final ObjectClass objectClass) {
-        ConnectorObject obj = null;
-        try {
-            Uid uid = new Uid(connObjectKey);
-
-            obj = profile.getConnector().getObject(objectClass,
-                    uid,
-                    
MappingManagerImpl.buildOperationOptions(IteratorUtils.<MappingItem>emptyIterator()));
-        } catch (TimeoutException toe) {
-            LOG.debug("Request timeout", toe);
-            throw toe;
-        } catch (RuntimeException ignore) {
-            LOG.debug("While resolving {}", connObjectKey, ignore);
-        }
-
-        return obj;
-    }
-
-    @Transactional(propagation = Propagation.REQUIRES_NEW)
-    @Override
-    public boolean handle(final long anyKey) {
-        Any<?> any = null;
-        try {
-            any = getAny(anyKey);
-            doHandle(any);
-            return true;
-        } catch (IgnoreProvisionException e) {
-            ProvisioningReport result = new ProvisioningReport();
-            result.setOperation(ResourceOperation.NONE);
-            result.setAnyType(any == null ? null : any.getType().getKey());
-            result.setStatus(ProvisioningReport.Status.IGNORE);
-            result.setKey(anyKey);
-            profile.getResults().add(result);
-
-            LOG.warn("Ignoring during push", e);
-            return true;
-        } catch (JobExecutionException e) {
-            LOG.error("Push failed", e);
-            return false;
-        }
-    }
-
-    protected final void doHandle(final Any<?> any) throws 
JobExecutionException {
-        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-
-        ProvisioningReport result = new ProvisioningReport();
-        profile.getResults().add(result);
-
-        result.setKey(any.getKey());
-        result.setAnyType(any.getType().getKey());
-        result.setName(getName(any));
-
-        Boolean enabled = any instanceof User && 
profile.getTask().isSyncStatus()
-                ? ((User) any).isSuspended() ? Boolean.FALSE : Boolean.TRUE
-                : null;
-
-        LOG.debug("Propagating {} with key {} towards {}",
-                anyUtils.getAnyTypeKind(), any.getKey(), 
profile.getTask().getResource());
-
-        Object output = null;
-        Result resultStatus = null;
-        String operation = null;
-
-        // Try to read remote object BEFORE any actual operation
-        Provision provision = 
profile.getTask().getResource().getProvision(any.getType());
-        String connObjecKey = mappingManager.getConnObjectKeyValue(any, 
provision);
-
-        ConnectorObject beforeObj = getRemoteObject(connObjecKey, 
provision.getObjectClass());
-
-        Boolean status = profile.getTask().isSyncStatus() ? enabled : null;
-
-        if (profile.isDryRun()) {
-            if (beforeObj == null) {
-                
result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
-            } else {
-                
result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
-            }
-            result.setStatus(ProvisioningReport.Status.SUCCESS);
-        } else {
-            try {
-                if (beforeObj == null) {
-                    operation = 
UnmatchingRule.toEventName(profile.getTask().getUnmatchingRule());
-                    
result.setOperation(getResourceOperation(profile.getTask().getUnmatchingRule()));
-
-                    switch (profile.getTask().getUnmatchingRule()) {
-                        case ASSIGN:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeAssign(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformCreate()) {
-                                LOG.debug("PushTask not configured for 
create");
-                            } else {
-                                assign(any, status);
-                            }
-
-                            break;
-
-                        case PROVISION:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeProvision(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformCreate()) {
-                                LOG.debug("PushTask not configured for 
create");
-                            } else {
-                                provision(any, status);
-                            }
-
-                            break;
-
-                        case UNLINK:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeUnlink(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformUpdate()) {
-                                LOG.debug("PushTask not configured for 
update");
-                            } else {
-                                link(any, true);
-                            }
-
-                            break;
-
-                        case IGNORE:
-                            LOG.debug("Ignored any: {}", any);
-                            break;
-                        default:
-                        // do nothing
-                    }
-                } else {
-                    operation = 
MatchingRule.toEventName(profile.getTask().getMatchingRule());
-                    
result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));
-
-                    switch (profile.getTask().getMatchingRule()) {
-                        case UPDATE:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeUpdate(this.getProfile(), any);
-                            }
-                            if (!profile.getTask().isPerformUpdate()) {
-                                LOG.debug("PushTask not configured for 
update");
-                            } else {
-                                update(any, status);
-                            }
-
-                            break;
-
-                        case DEPROVISION:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeDeprovision(this.getProfile(), 
any);
-                            }
-
-                            if (!profile.getTask().isPerformDelete()) {
-                                LOG.debug("PushTask not configured for 
delete");
-                            } else {
-                                deprovision(any);
-                            }
-
-                            break;
-
-                        case UNASSIGN:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeUnassign(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformDelete()) {
-                                LOG.debug("PushTask not configured for 
delete");
-                            } else {
-                                unassign(any);
-                            }
-
-                            break;
-
-                        case LINK:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeLink(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformUpdate()) {
-                                LOG.debug("PushTask not configured for 
update");
-                            } else {
-                                link(any, false);
-                            }
-
-                            break;
-
-                        case UNLINK:
-                            for (PushActions action : profile.getActions()) {
-                                action.beforeUnlink(this.getProfile(), any);
-                            }
-
-                            if (!profile.getTask().isPerformUpdate()) {
-                                LOG.debug("PushTask not configured for 
update");
-                            } else {
-                                link(any, true);
-                            }
-
-                            break;
-
-                        case IGNORE:
-                            LOG.debug("Ignored any: {}", any);
-                            break;
-                        default:
-                        // do nothing
-                    }
-                }
-
-                for (PushActions action : profile.getActions()) {
-                    action.after(this.getProfile(), any, result);
-                }
-
-                result.setStatus(ProvisioningReport.Status.SUCCESS);
-                resultStatus = AuditElements.Result.SUCCESS;
-                output = getRemoteObject(connObjecKey, 
provision.getObjectClass());
-            } catch (IgnoreProvisionException e) {
-                throw e;
-            } catch (Exception e) {
-                result.setStatus(ProvisioningReport.Status.FAILURE);
-                result.setMessage(ExceptionUtils.getRootCauseMessage(e));
-                resultStatus = AuditElements.Result.FAILURE;
-                output = e;
-
-                LOG.warn("Error pushing {} towards {}", any, 
profile.getTask().getResource(), e);
-
-                for (PushActions action : profile.getActions()) {
-                    action.onError(this.getProfile(), any, result, e);
-                }
-
-                throw new JobExecutionException(e);
-            } finally {
-                
notificationManager.createTasks(AuditElements.EventCategoryType.PUSH,
-                        any.getType().getKind().name().toLowerCase(),
-                        profile.getTask().getResource().getKey(),
-                        operation,
-                        resultStatus,
-                        beforeObj,
-                        output,
-                        any);
-                auditManager.audit(AuditElements.EventCategoryType.PUSH,
-                        any.getType().getKind().name().toLowerCase(),
-                        profile.getTask().getResource().getKey(),
-                        operation,
-                        resultStatus,
-                        connObjectUtils.getConnObjectTO(beforeObj),
-                        output instanceof ConnectorObject
-                                ? 
connObjectUtils.getConnObjectTO((ConnectorObject) output) : output,
-                        any);
-            }
-        }
-    }
-
-    private ResourceOperation getResourceOperation(final UnmatchingRule rule) {
-        switch (rule) {
-            case ASSIGN:
-            case PROVISION:
-                return ResourceOperation.CREATE;
-            default:
-                return ResourceOperation.NONE;
-        }
-    }
-
-    private ResourceOperation getResourceOperation(final MatchingRule rule) {
-        switch (rule) {
-            case UPDATE:
-                return ResourceOperation.UPDATE;
-            case DEPROVISION:
-            case UNASSIGN:
-                return ResourceOperation.DELETE;
-            default:
-                return ResourceOperation.NONE;
-        }
-    }
-
-    protected Any<?> update(final Any<?> any, final Boolean enabled) {
-        boolean changepwd;
-        Collection<String> resourceNames;
-        if (any instanceof User) {
-            changepwd = true;
-            resourceNames = userDAO.findAllResourceNames((User) any);
-        } else if (any instanceof AnyObject) {
-            changepwd = false;
-            resourceNames = anyObjectDAO.findAllResourceNames((AnyObject) any);
-        } else {
-            changepwd = false;
-            resourceNames = ((Group) any).getResourceNames();
-        }
-
-        List<String> noPropResources = new ArrayList<>(resourceNames);
-        noPropResources.remove(profile.getTask().getResource().getKey());
-
-        PropagationByResource propByRes = new PropagationByResource();
-        propByRes.add(ResourceOperation.CREATE, 
profile.getTask().getResource().getKey());
-
-        taskExecutor.execute(propagationManager.getUpdateTasks(
-                any.getType().getKind(),
-                any.getKey(),
-                changepwd,
-                null,
-                propByRes,
-                null,
-                noPropResources));
-
-        return getAny(any.getKey());
-    }
-}

Reply via email to