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/09/22 08:15:57 UTC
[6/6] syncope git commit: [SYNCOPE-1212] Clearing and refactoring for
easier extensions
[SYNCOPE-1212] Clearing and refactoring for easier extensions
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/9c289134
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/9c289134
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/9c289134
Branch: refs/heads/master
Commit: 9c289134b3452874d279e83ef300dc8c313d44f9
Parents: 9e24b8e
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Sep 22 10:12:45 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Sep 22 10:15:38 2017 +0200
----------------------------------------------------------------------
.../jpa/content/ContentLoaderHandler.java | 2 +-
.../entity/task/AbstractProvisioningTask.java | 10 -
.../api/pushpull/RealmPullResultHandler.java | 23 +
.../api/pushpull/RealmPushResultHandler.java | 23 +
.../java/data/TaskDataBinderImpl.java | 8 +-
.../provisioning/java/job/JobManagerImpl.java | 21 +-
.../pushpull/AbstractPullResultHandler.java | 14 +-
.../pushpull/AbstractPushResultHandler.java | 10 +-
.../AnyObjectPullResultHandlerImpl.java | 112 ---
.../AnyObjectPushResultHandlerImpl.java | 70 --
.../DefaultAnyObjectPullResultHandler.java | 112 +++
.../DefaultAnyObjectPushResultHandler.java | 70 ++
.../pushpull/DefaultGroupPullResultHandler.java | 138 ++++
.../pushpull/DefaultGroupPushResultHandler.java | 70 ++
.../pushpull/DefaultRealmPullResultHandler.java | 795 +++++++++++++++++++
.../pushpull/DefaultRealmPushResultHandler.java | 450 +++++++++++
.../pushpull/DefaultUserPullResultHandler.java | 134 ++++
.../pushpull/DefaultUserPushResultHandler.java | 99 +++
.../pushpull/GroupPullResultHandlerImpl.java | 138 ----
.../pushpull/GroupPushResultHandlerImpl.java | 70 --
.../java/pushpull/PullJobDelegate.java | 87 +-
.../java/pushpull/PushJobDelegate.java | 81 +-
.../pushpull/RealmPullResultHandlerImpl.java | 795 -------------------
.../pushpull/RealmPushResultHandlerImpl.java | 450 -----------
.../pushpull/UserPullResultHandlerImpl.java | 134 ----
.../pushpull/UserPushResultHandlerImpl.java | 99 ---
26 files changed, 2063 insertions(+), 1952 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
index 72f5967..713fee0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
@@ -189,7 +189,7 @@ public class ContentLoaderHandler extends DefaultHandler {
try {
jdbcTemplate.update(query.toString(), getParameters(qName, atts));
} catch (DataAccessException e) {
- LOG.error("While trying to perform {}", query, e);
+ LOG.error("While trying to perform {} with params {}", query, getParameters(qName, atts), e);
if (!continueOnError) {
throw e;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java
index 0441eb3..dc35f9d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java
@@ -80,16 +80,6 @@ public abstract class AbstractProvisioningTask extends JPASchedTask implements P
protected MatchingRule matchingRule;
@Override
- public String getJobDelegateClassName() {
- return null;
- }
-
- @Override
- public void setJobDelegateClassName(final String jobDelegateClassName) {
- // fixed, cannot be changed
- }
-
- @Override
public ExternalResource getResource() {
return resource;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPullResultHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPullResultHandler.java
new file mode 100644
index 0000000..6f38692
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPullResultHandler.java
@@ -0,0 +1,23 @@
+/*
+ * 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.api.pushpull;
+
+public interface RealmPullResultHandler extends SyncopePullResultHandler {
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPushResultHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPushResultHandler.java
new file mode 100644
index 0000000..e994213
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/RealmPushResultHandler.java
@@ -0,0 +1,23 @@
+/*
+ * 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.api.pushpull;
+
+public interface RealmPushResultHandler extends SyncopePushResultHandler {
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index 646e950..2066cb2 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -110,7 +110,9 @@ public class TaskDataBinderImpl implements TaskDataBinder {
PushTask pushTask = (PushTask) task;
final PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
- pushTask.setJobDelegateClassName(PushJobDelegate.class.getName());
+ pushTask.setJobDelegateClassName(pushTaskTO.getJobDelegateClassName() == null
+ ? PushJobDelegate.class.getName()
+ : pushTaskTO.getJobDelegateClassName());
pushTask.setSourceRealm(realmDAO.findByFullPath(pushTaskTO.getSourceRealm()));
@@ -148,7 +150,9 @@ public class TaskDataBinderImpl implements TaskDataBinder {
pullTask.setDestinationRealm(realmDAO.findByFullPath(pullTaskTO.getDestinationRealm()));
- pullTask.setJobDelegateClassName(PullJobDelegate.class.getName());
+ pullTask.setJobDelegateClassName(pullTaskTO.getJobDelegateClassName() == null
+ ? PullJobDelegate.class.getName()
+ : pullTaskTO.getJobDelegateClassName());
pullTask.setMatchingRule(pullTaskTO.getMatchingRule() == null
? MatchingRule.UPDATE : pullTaskTO.getMatchingRule());
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
index f82c243..42daca5 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
@@ -46,8 +46,6 @@ import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.apache.syncope.core.spring.ApplicationContextProvider;
import org.apache.syncope.core.persistence.api.SyncopeLoader;
import org.apache.syncope.core.persistence.api.DomainsHolder;
-import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
-import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
@@ -69,8 +67,11 @@ import org.identityconnectors.common.IOUtil;
import org.quartz.impl.jdbcjobstore.Constants;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
import org.apache.syncope.core.provisioning.java.job.report.ReportJob;
+import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
+import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
public class JobManagerImpl implements JobManager, SyncopeLoader {
@@ -214,11 +215,17 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
TaskJob job = createSpringBean(TaskJob.class);
job.setTaskKey(task.getKey());
- String jobDelegateClassName = task instanceof PullTask
- ? PullJobDelegate.class.getName()
- : task instanceof PushTask
- ? PushJobDelegate.class.getName()
- : task.getJobDelegateClassName();
+ String jobDelegateClassName = task.getJobDelegateClassName() == null
+ ? task instanceof PullTask
+ ? PullJobDelegate.class.getName()
+ : task instanceof PushTask
+ ? PushJobDelegate.class.getName()
+ : null
+ : task.getJobDelegateClassName();
+ if (jobDelegateClassName == null) {
+ throw new IllegalArgumentException("Task " + task
+ + " does not provide any " + SchedTaskJobDelegate.class.getSimpleName());
+ }
Map<String, Object> jobMap = new HashMap<>();
jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/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 b6fe9ac..d545994 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
@@ -69,23 +69,23 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
protected PullUtils pullUtils;
@Autowired
- private NotificationManager notificationManager;
+ protected NotificationManager notificationManager;
@Autowired
- private AuditManager auditManager;
+ protected AuditManager auditManager;
@Autowired
- private ConnObjectUtils connObjectUtils;
+ protected ConnObjectUtils connObjectUtils;
@Autowired
- private VirSchemaDAO virSchemaDAO;
+ protected VirSchemaDAO virSchemaDAO;
@Autowired
- private VirAttrCache virAttrCache;
+ protected VirAttrCache virAttrCache;
- private SyncopePullExecutor executor;
+ protected SyncopePullExecutor executor;
- private Result latestResult;
+ protected Result latestResult;
protected abstract String getName(AnyTO anyTO);
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
index 395ec3e..cfbd325 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
@@ -96,7 +96,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
}
}
- private void update(final Any<?> any, final ProvisioningReport result) {
+ protected void update(final Any<?> any, final ProvisioningReport result) {
boolean changepwd;
Collection<String> resourceKeys;
if (any instanceof User) {
@@ -241,7 +241,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
}
}
- private void doHandle(final Any<?> any) throws JobExecutionException {
+ protected void doHandle(final Any<?> any) throws JobExecutionException {
AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
ProvisioningReport result = new ProvisioningReport();
@@ -473,7 +473,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
}
}
- private ResourceOperation toResourceOperation(final UnmatchingRule rule) {
+ protected ResourceOperation toResourceOperation(final UnmatchingRule rule) {
switch (rule) {
case ASSIGN:
case PROVISION:
@@ -483,7 +483,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
}
}
- private ResourceOperation toResourceOperation(final MatchingRule rule) {
+ protected ResourceOperation toResourceOperation(final MatchingRule rule) {
switch (rule) {
case UPDATE:
return ResourceOperation.UPDATE;
@@ -495,7 +495,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
}
}
- private ProvisioningReport.Status toProvisioningReportStatus(final PropagationTaskExecStatus status) {
+ protected ProvisioningReport.Status toProvisioningReportStatus(final PropagationTaskExecStatus status) {
switch (status) {
case FAILURE:
return ProvisioningReport.Status.FAILURE;
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPullResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPullResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPullResultHandlerImpl.java
deleted file mode 100644
index 3e652ee..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPullResultHandlerImpl.java
+++ /dev/null
@@ -1,112 +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.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.AnyObjectPatch;
-import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.PropagationStatus;
-import org.apache.syncope.common.lib.to.AnyObjectTO;
-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.AnyObjectProvisioningManager;
-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.AnyObjectPullResultHandler;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class AnyObjectPullResultHandlerImpl extends AbstractPullResultHandler implements AnyObjectPullResultHandler {
-
- @Autowired
- private AnyObjectProvisioningManager anyObjectProvisioningManager;
-
- @Override
- protected AnyUtils getAnyUtils() {
- return anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
- }
-
- @Override
- protected String getName(final AnyTO anyTO) {
- return AnyObjectTO.class.cast(anyTO).getName();
- }
-
- @Override
- protected ProvisioningManager<?, ?> getProvisioningManager() {
- return anyObjectProvisioningManager;
- }
-
- @Override
- protected Any<?> getAny(final String key) {
- try {
- return anyObjectDAO.authFind(key);
- } catch (Exception e) {
- LOG.warn("Error retrieving anyObject {}", key, e);
- return null;
- }
- }
-
- @Override
- protected AnyTO getAnyTO(final String key) {
- return anyObjectDataBinder.getAnyObjectTO(key);
- }
-
- @Override
- protected AnyPatch newPatch(final String key) {
- AnyObjectPatch patch = new AnyObjectPatch();
- patch.setKey(key);
- return patch;
- }
-
- @Override
- protected WorkflowResult<? extends AnyPatch> update(final AnyPatch patch) {
- return awfAdapter.update((AnyObjectPatch) patch);
- }
-
- @Override
- protected AnyTO doCreate(final AnyTO anyTO, final SyncDelta delta) {
- AnyObjectTO anyObjectTO = AnyObjectTO.class.cast(anyTO);
-
- Map.Entry<String, List<PropagationStatus>> created = anyObjectProvisioningManager.create(
- anyObjectTO, Collections.singleton(profile.getTask().getResource().getKey()), true);
-
- return getAnyTO(created.getKey());
- }
-
- @Override
- protected AnyPatch doUpdate(
- final AnyTO before,
- final AnyPatch anyPatch,
- final SyncDelta delta,
- final ProvisioningReport result) {
-
- AnyObjectPatch anyObjectPatch = AnyObjectPatch.class.cast(anyPatch);
-
- Pair<AnyObjectPatch, List<PropagationStatus>> updated = anyObjectProvisioningManager.update(
- anyObjectPatch, Collections.singleton(profile.getTask().getResource().getKey()), true);
-
- return anyPatch;
- }
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPushResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPushResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPushResultHandlerImpl.java
deleted file mode 100644
index 48f464a..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AnyObjectPushResultHandlerImpl.java
+++ /dev/null
@@ -1,70 +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.pushpull;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.patch.AnyObjectPatch;
-import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
-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.WorkflowResult;
-import org.apache.syncope.core.provisioning.api.pushpull.AnyObjectPushResultHandler;
-
-public class AnyObjectPushResultHandlerImpl extends AbstractPushResultHandler implements AnyObjectPushResultHandler {
-
- @Override
- protected AnyUtils getAnyUtils() {
- return anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
- }
-
- @Override
- protected String getName(final Any<?> any) {
- return StringUtils.EMPTY;
- }
-
- @Override
- protected Any<?> getAny(final String key) {
- try {
- return anyObjectDAO.authFind(key);
- } catch (Exception e) {
- LOG.warn("Error retrieving anyObject {}", key, e);
- return null;
- }
- }
-
- @Override
- protected AnyTO getAnyTO(final String key) {
- return anyObjectDataBinder.getAnyObjectTO(key);
- }
-
- @Override
- protected AnyPatch newPatch(final String key) {
- AnyObjectPatch patch = new AnyObjectPatch();
- patch.setKey(key);
- return patch;
- }
-
- @Override
- protected WorkflowResult<? extends AnyObjectPatch> update(final AnyPatch patch) {
- return awfAdapter.update((AnyObjectPatch) patch);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPullResultHandler.java
new file mode 100644
index 0000000..8d71a2d
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPullResultHandler.java
@@ -0,0 +1,112 @@
+/*
+ * 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.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+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.AnyObjectProvisioningManager;
+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.AnyObjectPullResultHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DefaultAnyObjectPullResultHandler extends AbstractPullResultHandler implements AnyObjectPullResultHandler {
+
+ @Autowired
+ private AnyObjectProvisioningManager anyObjectProvisioningManager;
+
+ @Override
+ protected AnyUtils getAnyUtils() {
+ return anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
+ }
+
+ @Override
+ protected String getName(final AnyTO anyTO) {
+ return AnyObjectTO.class.cast(anyTO).getName();
+ }
+
+ @Override
+ protected ProvisioningManager<?, ?> getProvisioningManager() {
+ return anyObjectProvisioningManager;
+ }
+
+ @Override
+ protected Any<?> getAny(final String key) {
+ try {
+ return anyObjectDAO.authFind(key);
+ } catch (Exception e) {
+ LOG.warn("Error retrieving anyObject {}", key, e);
+ return null;
+ }
+ }
+
+ @Override
+ protected AnyTO getAnyTO(final String key) {
+ return anyObjectDataBinder.getAnyObjectTO(key);
+ }
+
+ @Override
+ protected AnyPatch newPatch(final String key) {
+ AnyObjectPatch patch = new AnyObjectPatch();
+ patch.setKey(key);
+ return patch;
+ }
+
+ @Override
+ protected WorkflowResult<? extends AnyPatch> update(final AnyPatch patch) {
+ return awfAdapter.update((AnyObjectPatch) patch);
+ }
+
+ @Override
+ protected AnyTO doCreate(final AnyTO anyTO, final SyncDelta delta) {
+ AnyObjectTO anyObjectTO = AnyObjectTO.class.cast(anyTO);
+
+ Map.Entry<String, List<PropagationStatus>> created = anyObjectProvisioningManager.create(
+ anyObjectTO, Collections.singleton(profile.getTask().getResource().getKey()), true);
+
+ return getAnyTO(created.getKey());
+ }
+
+ @Override
+ protected AnyPatch doUpdate(
+ final AnyTO before,
+ final AnyPatch anyPatch,
+ final SyncDelta delta,
+ final ProvisioningReport result) {
+
+ AnyObjectPatch anyObjectPatch = AnyObjectPatch.class.cast(anyPatch);
+
+ Pair<AnyObjectPatch, List<PropagationStatus>> updated = anyObjectProvisioningManager.update(
+ anyObjectPatch, Collections.singleton(profile.getTask().getResource().getKey()), true);
+
+ return anyPatch;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPushResultHandler.java
new file mode 100644
index 0000000..3c401ae
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultAnyObjectPushResultHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+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.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.pushpull.AnyObjectPushResultHandler;
+
+public class DefaultAnyObjectPushResultHandler extends AbstractPushResultHandler implements AnyObjectPushResultHandler {
+
+ @Override
+ protected AnyUtils getAnyUtils() {
+ return anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
+ }
+
+ @Override
+ protected String getName(final Any<?> any) {
+ return StringUtils.EMPTY;
+ }
+
+ @Override
+ protected Any<?> getAny(final String key) {
+ try {
+ return anyObjectDAO.authFind(key);
+ } catch (Exception e) {
+ LOG.warn("Error retrieving anyObject {}", key, e);
+ return null;
+ }
+ }
+
+ @Override
+ protected AnyTO getAnyTO(final String key) {
+ return anyObjectDataBinder.getAnyObjectTO(key);
+ }
+
+ @Override
+ protected AnyPatch newPatch(final String key) {
+ AnyObjectPatch patch = new AnyObjectPatch();
+ patch.setKey(key);
+ return patch;
+ }
+
+ @Override
+ protected WorkflowResult<? extends AnyObjectPatch> update(final AnyPatch patch) {
+ return awfAdapter.update((AnyObjectPatch) patch);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPullResultHandler.java
new file mode 100644
index 0000000..451659b
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPullResultHandler.java
@@ -0,0 +1,138 @@
+/*
+ * 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.HashMap;
+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.AttrPatch;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PatchOperation;
+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.GroupProvisioningManager;
+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.GroupPullResultHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DefaultGroupPullResultHandler extends AbstractPullResultHandler implements GroupPullResultHandler {
+
+ @Autowired
+ private GroupProvisioningManager groupProvisioningManager;
+
+ private final Map<String, String> groupOwnerMap = new HashMap<>();
+
+ @Override
+ public Map<String, String> getGroupOwnerMap() {
+ return this.groupOwnerMap;
+ }
+
+ @Override
+ protected AnyUtils getAnyUtils() {
+ return anyUtilsFactory.getInstance(AnyTypeKind.GROUP);
+ }
+
+ @Override
+ protected String getName(final AnyTO anyTO) {
+ return GroupTO.class.cast(anyTO).getName();
+ }
+
+ @Override
+ protected ProvisioningManager<?, ?> getProvisioningManager() {
+ return groupProvisioningManager;
+ }
+
+ @Override
+ protected Any<?> getAny(final String key) {
+ try {
+ return groupDAO.authFind(key);
+ } catch (Exception e) {
+ LOG.warn("Error retrieving group {}", key, e);
+ return null;
+ }
+ }
+
+ @Override
+ protected AnyTO getAnyTO(final String key) {
+ return groupDataBinder.getGroupTO(key);
+ }
+
+ @Override
+ protected AnyPatch newPatch(final String key) {
+ GroupPatch patch = new GroupPatch();
+ patch.setKey(key);
+ return patch;
+ }
+
+ @Override
+ protected WorkflowResult<? extends AnyPatch> update(final AnyPatch patch) {
+ return gwfAdapter.update((GroupPatch) patch);
+ }
+
+ @Override
+ protected AnyTO doCreate(final AnyTO anyTO, final SyncDelta delta) {
+ GroupTO groupTO = GroupTO.class.cast(anyTO);
+
+ Map.Entry<String, List<PropagationStatus>> created = groupProvisioningManager.create(
+ groupTO,
+ groupOwnerMap,
+ Collections.singleton(profile.getTask().getResource().getKey()),
+ true);
+
+ return getAnyTO(created.getKey());
+ }
+
+ @Override
+ protected AnyPatch doUpdate(
+ final AnyTO before,
+ final AnyPatch anyPatch,
+ final SyncDelta delta,
+ final ProvisioningReport result) {
+
+ GroupPatch groupPatch = GroupPatch.class.cast(anyPatch);
+
+ Pair<GroupPatch, List<PropagationStatus>> updated = groupProvisioningManager.update(
+ groupPatch, Collections.singleton(profile.getTask().getResource().getKey()), true);
+
+ String groupOwner = null;
+ for (AttrPatch attrPatch : groupPatch.getPlainAttrs()) {
+ if (attrPatch.getOperation() == PatchOperation.ADD_REPLACE && attrPatch.getAttrTO() != null
+ && attrPatch.getAttrTO().getSchema().isEmpty() && !attrPatch.getAttrTO().getValues().isEmpty()) {
+
+ groupOwner = attrPatch.getAttrTO().getValues().get(0);
+ }
+ }
+ if (groupOwner != null) {
+ groupOwnerMap.put(updated.getLeft().getKey(), groupOwner);
+ }
+
+ return anyPatch;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPushResultHandler.java
new file mode 100644
index 0000000..993f747
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultGroupPushResultHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+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.persistence.api.entity.group.Group;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.pushpull.GroupPushResultHandler;
+
+public class DefaultGroupPushResultHandler extends AbstractPushResultHandler implements GroupPushResultHandler {
+
+ @Override
+ protected AnyUtils getAnyUtils() {
+ return anyUtilsFactory.getInstance(AnyTypeKind.GROUP);
+ }
+
+ @Override
+ protected String getName(final Any<?> any) {
+ return Group.class.cast(any).getName();
+ }
+
+ @Override
+ protected Any<?> getAny(final String key) {
+ try {
+ return groupDAO.authFind(key);
+ } catch (Exception e) {
+ LOG.warn("Error retrieving group {}", key, e);
+ return null;
+ }
+ }
+
+ @Override
+ protected AnyTO getAnyTO(final String key) {
+ return groupDataBinder.getGroupTO(key);
+ }
+
+ @Override
+ protected AnyPatch newPatch(final String key) {
+ GroupPatch patch = new GroupPatch();
+ patch.setKey(key);
+ return patch;
+ }
+
+ @Override
+ protected WorkflowResult<? extends AnyPatch> update(final AnyPatch patch) {
+ return gwfAdapter.update((GroupPatch) patch);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/9c289134/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
new file mode 100644
index 0000000..69c0604
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultRealmPullResultHandler.java
@@ -0,0 +1,795 @@
+/*
+ * 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 java.util.Set;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.AuditElements.Result;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.core.provisioning.api.PropagationByResource;
+import org.apache.syncope.common.lib.types.PullMode;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
+import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
+import org.apache.syncope.core.provisioning.api.pushpull.RealmPullResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullExecutor;
+import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
+import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
+import org.identityconnectors.framework.common.objects.SyncDelta;
+import org.identityconnectors.framework.common.objects.SyncDeltaType;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(rollbackFor = Throwable.class)
+public class DefaultRealmPullResultHandler
+ extends AbstractRealmResultHandler<PullTask, PullActions>
+ implements RealmPullResultHandler {
+
+ @Autowired
+ private PullUtils pullUtils;
+
+ @Autowired
+ private ConnObjectUtils connObjectUtils;
+
+ @Autowired
+ private AnySearchDAO searchDAO;
+
+ private SyncopePullExecutor executor;
+
+ private Result latestResult;
+
+ @Override
+ public void setPullExecutor(final SyncopePullExecutor executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public boolean handle(final SyncDelta delta) {
+ try {
+ OrgUnit orgUnit = profile.getTask().getResource().getOrgUnit();
+ if (orgUnit == null) {
+ throw new JobExecutionException("No orgUnit found on " + profile.getTask().getResource() + " for "
+ + delta.getObject().getObjectClass());
+ }
+
+ doHandle(delta, orgUnit);
+
+ LOG.debug("Successfully handled {}", delta);
+
+ if (profile.getTask().getPullMode() != PullMode.INCREMENTAL) {
+ return true;
+ }
+
+ boolean shouldContinue;
+ synchronized (this) {
+ shouldContinue = latestResult == Result.SUCCESS;
+ this.latestResult = null;
+ }
+ if (shouldContinue) {
+ executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
+ }
+ return shouldContinue;
+ } catch (IgnoreProvisionException e) {
+ ProvisioningReport ignoreResult = new ProvisioningReport();
+ ignoreResult.setOperation(ResourceOperation.NONE);
+ ignoreResult.setStatus(ProvisioningReport.Status.IGNORE);
+ ignoreResult.setAnyType(REALM_TYPE);
+ ignoreResult.setKey(null);
+ ignoreResult.setName(delta.getObject().getName().getNameValue());
+ profile.getResults().add(ignoreResult);
+
+ LOG.warn("Ignoring during pull", e);
+
+ executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
+
+ return true;
+ } catch (JobExecutionException e) {
+ LOG.error("Pull failed", e);
+
+ return false;
+ }
+ }
+
+ private List<ProvisioningReport> assign(final SyncDelta delta, final OrgUnit orgUnit) throws JobExecutionException {
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("PullTask not configured for create");
+ finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ RealmTO realmTO = connObjectUtils.getRealmTO(delta.getObject(), profile.getTask(), orgUnit);
+ if (realmTO.getFullPath() == null) {
+ if (realmTO.getParent() == null) {
+ realmTO.setParent(profile.getTask().getDestinatioRealm().getFullPath());
+ }
+
+ realmTO.setFullPath(realmTO.getParent() + "/" + realmTO.getName());
+ }
+ realmTO.getResources().add(profile.getTask().getResource().getKey());
+
+ ProvisioningReport result = new ProvisioningReport();
+ result.setOperation(ResourceOperation.CREATE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+ result.setName(realmTO.getFullPath());
+
+ if (profile.isDryRun()) {
+ result.setKey(null);
+ finalize(UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), Result.SUCCESS, null, null, delta);
+ } else {
+ SyncDelta actionedDelta = delta;
+ for (PullActions action : profile.getActions()) {
+ actionedDelta = action.beforeAssign(profile, actionedDelta, realmTO);
+ }
+
+ create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.ASSIGN), result);
+ }
+
+ return Collections.singletonList(result);
+ }
+
+ private List<ProvisioningReport> provision(final SyncDelta delta, final OrgUnit orgUnit)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformCreate()) {
+ LOG.debug("PullTask not configured for create");
+ finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ RealmTO realmTO = connObjectUtils.getRealmTO(delta.getObject(), profile.getTask(), orgUnit);
+ if (realmTO.getFullPath() == null) {
+ if (realmTO.getParent() == null) {
+ realmTO.setParent(profile.getTask().getDestinatioRealm().getFullPath());
+ }
+
+ realmTO.setFullPath(realmTO.getParent() + "/" + realmTO.getName());
+ }
+
+ ProvisioningReport result = new ProvisioningReport();
+ result.setOperation(ResourceOperation.CREATE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+ result.setName(realmTO.getFullPath());
+
+ if (profile.isDryRun()) {
+ result.setKey(null);
+ finalize(UnmatchingRule.toEventName(UnmatchingRule.PROVISION), Result.SUCCESS, null, null, delta);
+ } else {
+ SyncDelta actionedDelta = delta;
+ for (PullActions action : profile.getActions()) {
+ actionedDelta = action.beforeProvision(profile, actionedDelta, realmTO);
+ }
+
+ create(realmTO, actionedDelta, UnmatchingRule.toEventName(UnmatchingRule.PROVISION), result);
+ }
+
+ return Collections.singletonList(result);
+ }
+
+ private void throwIgnoreProvisionException(final SyncDelta delta, final Exception exception)
+ throws JobExecutionException {
+
+ if (exception instanceof IgnoreProvisionException) {
+ throw IgnoreProvisionException.class.cast(exception);
+ }
+
+ IgnoreProvisionException ipe = null;
+ for (PullActions action : profile.getActions()) {
+ if (ipe == null) {
+ ipe = action.onError(profile, delta, exception);
+ }
+ }
+ if (ipe != null) {
+ throw ipe;
+ }
+ }
+
+ private void create(
+ final RealmTO realmTO,
+ final SyncDelta delta,
+ final String operation,
+ final ProvisioningReport result)
+ throws JobExecutionException {
+
+ Object output;
+ Result resultStatus;
+
+ try {
+ Realm realm = realmDAO.save(binder.create(profile.getTask().getDestinatioRealm().getFullPath(), realmTO));
+
+ PropagationByResource propByRes = new PropagationByResource();
+ for (String resource : realm.getResourceKeys()) {
+ propByRes.add(ResourceOperation.CREATE, resource);
+ }
+ List<PropagationTask> tasks = propagationManager.createTasks(realm, propByRes, null);
+ taskExecutor.execute(tasks, false);
+
+ RealmTO actual = binder.getRealmTO(realm, true);
+
+ result.setKey(actual.getKey());
+ result.setName(profile.getTask().getDestinatioRealm().getFullPath() + "/" + actual.getName());
+
+ output = actual;
+ resultStatus = Result.SUCCESS;
+
+ for (PullActions action : profile.getActions()) {
+ action.after(profile, delta, actual, result);
+ }
+
+ LOG.debug("Realm {} successfully created", actual.getKey());
+ } catch (PropagationException e) {
+ // A propagation failure doesn't imply a pull failure.
+ // The propagation exception status will be reported into the propagation task execution.
+ LOG.error("Could not propagate Realm {}", delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ throwIgnoreProvisionException(delta, e);
+
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not create Realm {} ", delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+
+ finalize(operation, resultStatus, null, output, delta);
+ }
+
+ private List<ProvisioningReport> update(final SyncDelta delta, final List<String> keys)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PullTask not configured for update");
+ finalize(MatchingRule.toEventName(MatchingRule.UPDATE), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ LOG.debug("About to update {}", keys);
+
+ List<ProvisioningReport> results = new ArrayList<>();
+
+ SyncDelta workingDelta = delta;
+ for (String key : keys) {
+ LOG.debug("About to update {}", key);
+
+ ProvisioningReport result = new ProvisioningReport();
+ result.setOperation(ResourceOperation.UPDATE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+ result.setKey(key);
+
+ Realm realm = realmDAO.find(key);
+ RealmTO before = binder.getRealmTO(realm, true);
+ if (before == null) {
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(String.format("Realm '%s' not found", key));
+ } else {
+ result.setName(before.getFullPath());
+ }
+
+ if (!profile.isDryRun()) {
+ Result resultStatus;
+ Object output;
+
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ try {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeUpdate(profile, workingDelta, before, null);
+ }
+
+ PropagationByResource propByRes = binder.update(realm, before);
+ realm = realmDAO.save(realm);
+ RealmTO updated = binder.getRealmTO(realm, true);
+
+ List<PropagationTask> tasks = propagationManager.createTasks(realm, propByRes, null);
+ taskExecutor.execute(tasks, false);
+
+ for (PullActions action : profile.getActions()) {
+ action.after(profile, workingDelta, updated, result);
+ }
+
+ output = updated;
+ resultStatus = Result.SUCCESS;
+ result.setName(updated.getFullPath());
+
+ LOG.debug("{} successfully updated", updated);
+ } 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);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ throwIgnoreProvisionException(workingDelta, e);
+
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ finalize(MatchingRule.toEventName(MatchingRule.UPDATE), resultStatus, before, output, workingDelta);
+ }
+ results.add(result);
+ }
+
+ return results;
+ }
+
+ private List<ProvisioningReport> deprovision(final SyncDelta delta, final List<String> keys, final boolean unlink)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PullTask not configured for update");
+ finalize(unlink
+ ? MatchingRule.toEventName(MatchingRule.UNASSIGN)
+ : MatchingRule.toEventName(MatchingRule.DEPROVISION), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ LOG.debug("About to deprovision {}", keys);
+
+ final List<ProvisioningReport> results = new ArrayList<>();
+
+ SyncDelta workingDelta = delta;
+ for (String key : keys) {
+ LOG.debug("About to unassign resource {}", key);
+
+ ProvisioningReport result = new ProvisioningReport();
+ result.setOperation(ResourceOperation.DELETE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+ result.setKey(key);
+
+ Realm realm = realmDAO.find(key);
+ RealmTO before = binder.getRealmTO(realm, true);
+ if (before == null) {
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(String.format("Realm '%s' not found", key));
+ } else {
+ result.setName(before.getFullPath());
+ }
+
+ if (!profile.isDryRun()) {
+ Object output;
+ Result resultStatus;
+
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ try {
+ if (unlink) {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeUnassign(profile, workingDelta, before);
+ }
+ } else {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeDeprovision(profile, workingDelta, before);
+ }
+ }
+
+ PropagationByResource propByRes = new PropagationByResource();
+ propByRes.add(ResourceOperation.DELETE, profile.getTask().getResource().getKey());
+ taskExecutor.execute(propagationManager.createTasks(realm, propByRes, null), false);
+
+ if (unlink) {
+ realm.getResources().remove(profile.getTask().getResource());
+ output = binder.getRealmTO(realmDAO.save(realm), true);
+ } else {
+ output = binder.getRealmTO(realm, true);
+ }
+
+ for (PullActions action : profile.getActions()) {
+ action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+ }
+
+ resultStatus = Result.SUCCESS;
+
+ LOG.debug("{} successfully updated", realm);
+ } 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);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ throwIgnoreProvisionException(workingDelta, e);
+
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update Realm {}", delta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ finalize(unlink
+ ? MatchingRule.toEventName(MatchingRule.UNASSIGN)
+ : MatchingRule.toEventName(MatchingRule.DEPROVISION), resultStatus, before, output, delta);
+ }
+ results.add(result);
+ }
+
+ return results;
+ }
+
+ private List<ProvisioningReport> link(final SyncDelta delta, final List<String> keys, final boolean unlink)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformUpdate()) {
+ LOG.debug("PullTask not configured for update");
+ finalize(unlink
+ ? MatchingRule.toEventName(MatchingRule.UNLINK)
+ : MatchingRule.toEventName(MatchingRule.LINK), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ LOG.debug("About to link {}", keys);
+
+ final List<ProvisioningReport> results = new ArrayList<>();
+
+ SyncDelta workingDelta = delta;
+ for (String key : keys) {
+ LOG.debug("About to unassign resource {}", key);
+
+ ProvisioningReport result = new ProvisioningReport();
+ result.setOperation(ResourceOperation.NONE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+ result.setKey(key);
+
+ Realm realm = realmDAO.find(key);
+ RealmTO before = binder.getRealmTO(realm, true);
+ if (before == null) {
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(String.format("Realm '%s' not found", key));
+ } else {
+ result.setName(before.getFullPath());
+ }
+
+ Object output;
+ Result resultStatus;
+ if (!profile.isDryRun()) {
+ if (before == null) {
+ resultStatus = Result.FAILURE;
+ output = null;
+ } else {
+ try {
+ if (unlink) {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeUnlink(profile, workingDelta, before);
+ }
+ } else {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeLink(profile, workingDelta, before);
+ }
+ }
+
+ if (unlink) {
+ realm.getResources().remove(profile.getTask().getResource());
+ } else {
+ realm.add(profile.getTask().getResource());
+ }
+ output = update(workingDelta, Collections.singletonList(key));
+
+ for (PullActions action : profile.getActions()) {
+ action.after(profile, workingDelta, RealmTO.class.cast(output), result);
+ }
+
+ resultStatus = Result.SUCCESS;
+
+ LOG.debug("{} successfully updated", realm);
+ } 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);
+ output = e;
+ resultStatus = Result.FAILURE;
+ } catch (Exception e) {
+ throwIgnoreProvisionException(workingDelta, e);
+
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not update Realm {}", workingDelta.getUid().getUidValue(), e);
+ output = e;
+ resultStatus = Result.FAILURE;
+ }
+ }
+ finalize(unlink
+ ? MatchingRule.toEventName(MatchingRule.UNLINK)
+ : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, workingDelta);
+ }
+ results.add(result);
+ }
+
+ return results;
+ }
+
+ private List<ProvisioningReport> delete(final SyncDelta delta, final List<String> keys)
+ throws JobExecutionException {
+
+ if (!profile.getTask().isPerformDelete()) {
+ LOG.debug("PullTask not configured for delete");
+ finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+ return Collections.<ProvisioningReport>emptyList();
+ }
+
+ LOG.debug("About to delete {}", keys);
+
+ List<ProvisioningReport> results = new ArrayList<>();
+
+ SyncDelta workingDelta = delta;
+ for (String key : keys) {
+ Object output;
+ Result resultStatus = Result.FAILURE;
+
+ ProvisioningReport result = new ProvisioningReport();
+
+ try {
+ result.setKey(key);
+ result.setOperation(ResourceOperation.DELETE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+
+ Realm realm = realmDAO.find(key);
+ RealmTO before = binder.getRealmTO(realm, true);
+ if (before == null) {
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(String.format("Realm '%s' not found", key));
+ } else {
+ result.setName(before.getFullPath());
+ }
+
+ if (!profile.isDryRun()) {
+ for (PullActions action : profile.getActions()) {
+ workingDelta = action.beforeDelete(profile, workingDelta, before);
+ }
+
+ try {
+ if (!realmDAO.findChildren(realm).isEmpty()) {
+ throw SyncopeClientException.build(ClientExceptionType.HasChildren);
+ }
+
+ Set<String> adminRealms = Collections.singleton(realm.getFullPath());
+ AnyCond keyCond = new AnyCond(AttributeCond.Type.ISNOTNULL);
+ keyCond.setSchema("key");
+ SearchCond allMatchingCond = SearchCond.getLeafCond(keyCond);
+ int users = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.USER);
+ int groups = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.GROUP);
+ int anyObjects = searchDAO.count(adminRealms, allMatchingCond, AnyTypeKind.ANY_OBJECT);
+
+ if (users + groups + anyObjects > 0) {
+ SyncopeClientException containedAnys = SyncopeClientException.build(
+ ClientExceptionType.AssociatedAnys);
+ containedAnys.getElements().add(users + " user(s)");
+ containedAnys.getElements().add(groups + " group(s)");
+ containedAnys.getElements().add(anyObjects + " anyObject(s)");
+ throw containedAnys;
+ }
+
+ PropagationByResource propByRes = new PropagationByResource();
+ for (String resource : realm.getResourceKeys()) {
+ propByRes.add(ResourceOperation.DELETE, resource);
+ }
+ List<PropagationTask> tasks = propagationManager.createTasks(realm, propByRes, null);
+ taskExecutor.execute(tasks, false);
+
+ realmDAO.delete(realm);
+
+ output = null;
+ resultStatus = Result.SUCCESS;
+
+ for (PullActions action : profile.getActions()) {
+ action.after(profile, workingDelta, before, result);
+ }
+ } catch (Exception e) {
+ throwIgnoreProvisionException(workingDelta, e);
+
+ result.setStatus(ProvisioningReport.Status.FAILURE);
+ result.setMessage(ExceptionUtils.getRootCauseMessage(e));
+ LOG.error("Could not delete {}", realm, e);
+ output = e;
+ }
+
+ finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
+ }
+
+ results.add(result);
+ } catch (DelegatedAdministrationException e) {
+ LOG.error("Not allowed to read Realm {}", key, e);
+ } catch (Exception e) {
+ LOG.error("Could not delete Realm {}", key, e);
+ }
+ }
+
+ return results;
+ }
+
+ private ProvisioningReport ignore(
+ final SyncDelta delta,
+ final boolean matching)
+ throws JobExecutionException {
+
+ LOG.debug("Any to ignore {}", delta.getObject().getUid().getUidValue());
+
+ ProvisioningReport result = new ProvisioningReport();
+
+ result.setKey(null);
+ result.setName(delta.getObject().getUid().getUidValue());
+ result.setOperation(ResourceOperation.NONE);
+ result.setAnyType(REALM_TYPE);
+ result.setStatus(ProvisioningReport.Status.SUCCESS);
+
+ if (!profile.isDryRun()) {
+ finalize(matching
+ ? MatchingRule.toEventName(MatchingRule.IGNORE)
+ : UnmatchingRule.toEventName(UnmatchingRule.IGNORE), Result.SUCCESS, null, null, delta);
+ }
+
+ return result;
+ }
+
+ private void doHandle(final SyncDelta delta, final OrgUnit orgUnit) throws JobExecutionException {
+ LOG.debug("Process {} for {} as {}",
+ delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());
+
+ String uid = delta.getPreviousUid() == null
+ ? delta.getUid().getUidValue()
+ : delta.getPreviousUid().getUidValue();
+
+ List<String> keys = pullUtils.findExisting(uid, delta.getObject(), orgUnit);
+ LOG.debug("Match found for {} as {}: {}",
+ delta.getUid().getUidValue(), delta.getObject().getObjectClass(), keys);
+
+ if (keys.size() > 1) {
+ switch (profile.getResAct()) {
+ case IGNORE:
+ throw new IllegalStateException("More than one match " + keys);
+
+ case FIRSTMATCH:
+ keys = keys.subList(0, 1);
+ break;
+
+ case LASTMATCH:
+ keys = keys.subList(keys.size() - 1, keys.size());
+ break;
+
+ default:
+ // keep keys unmodified
+ }
+ }
+
+ try {
+ if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
+ if (keys.isEmpty()) {
+ switch (profile.getTask().getUnmatchingRule()) {
+ case ASSIGN:
+ profile.getResults().addAll(assign(delta, orgUnit));
+ break;
+
+ case PROVISION:
+ profile.getResults().addAll(provision(delta, orgUnit));
+ break;
+
+ case IGNORE:
+ profile.getResults().add(ignore(delta, false));
+ break;
+
+ default:
+ // do nothing
+ }
+ } else {
+ switch (profile.getTask().getMatchingRule()) {
+ case UPDATE:
+ profile.getResults().addAll(update(delta, keys));
+ break;
+
+ case DEPROVISION:
+ profile.getResults().addAll(deprovision(delta, keys, false));
+ break;
+
+ case UNASSIGN:
+ profile.getResults().addAll(deprovision(delta, keys, true));
+ break;
+
+ case LINK:
+ profile.getResults().addAll(link(delta, keys, false));
+ break;
+
+ case UNLINK:
+ profile.getResults().addAll(link(delta, keys, true));
+ break;
+
+ case IGNORE:
+ profile.getResults().add(ignore(delta, true));
+ break;
+
+ default:
+ // do nothing
+ }
+ }
+ } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
+ if (keys.isEmpty()) {
+ finalize(ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
+ LOG.debug("No match found for deletion");
+ } else {
+ profile.getResults().addAll(delete(delta, keys));
+ }
+ }
+ } catch (IllegalStateException | IllegalArgumentException e) {
+ LOG.warn(e.getMessage());
+ }
+ }
+
+ private void finalize(
+ final String event,
+ final Result result,
+ final Object before,
+ final Object output,
+ final SyncDelta delta) {
+
+ synchronized (this) {
+ this.latestResult = result;
+ }
+
+ notificationManager.createTasks(AuditElements.EventCategoryType.PULL,
+ REALM_TYPE.toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ event,
+ result,
+ before,
+ output,
+ delta);
+
+ auditManager.audit(AuditElements.EventCategoryType.PULL,
+ REALM_TYPE.toLowerCase(),
+ profile.getTask().getResource().getKey(),
+ event,
+ result,
+ before,
+ output,
+ delta);
+ }
+}