Repository: syncope Updated Branches: refs/heads/2_0_X 6fd572119 -> a07f3b948 refs/heads/master 24f789932 -> 44a5e1da7
[SYNCOPE-1299] Reworking REST service definition to allow more flexibility Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/a07f3b94 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/a07f3b94 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/a07f3b94 Branch: refs/heads/2_0_X Commit: a07f3b948c34222d98509d1f11b20f054b392b02 Parents: 6fd5721 Author: Francesco Chicchiriccò <ilgro...@apache.org> Authored: Fri Apr 13 11:14:56 2018 +0200 Committer: Francesco Chicchiriccò <ilgro...@apache.org> Committed: Fri Apr 13 11:14:56 2018 +0200 ---------------------------------------------------------------------- .../common/lib/to/ReconciliationRequest.java | 90 -------------------- .../common/lib/types/ReconciliationAction.java | 28 ------ .../rest/api/service/ReconciliationService.java | 44 ++++++++-- .../syncope/core/logic/ReconciliationLogic.java | 72 +++++++++------- .../api/pushpull/SyncopeSinglePullExecutor.java | 3 +- .../api/pushpull/SyncopeSinglePushExecutor.java | 3 +- .../pushpull/AbstractSyncopeResultHandler.java | 1 + .../java/pushpull/SinglePullJobDelegate.java | 44 ++++++++-- .../java/pushpull/SinglePushJobDelegate.java | 16 ++-- .../cxf/service/ReconciliationServiceImpl.java | 32 +++++-- .../syncope/fit/core/ReconciliationITCase.java | 24 +++--- 11 files changed, 171 insertions(+), 186 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java deleted file mode 100644 index d6cae93..0000000 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java +++ /dev/null @@ -1,90 +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.common.lib.to; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import org.apache.syncope.common.lib.AbstractBaseBean; -import org.apache.syncope.common.lib.types.AnyTypeKind; -import org.apache.syncope.common.lib.types.ReconciliationAction; - -public class ReconciliationRequest extends AbstractBaseBean { - - private static final long serialVersionUID = -2592156800185957182L; - - private AnyTypeKind anyTypeKind; - - private String anyKey; - - private String resourceKey; - - private ReconciliationAction action; - - private final List<String> actionsClassNames = new ArrayList<>(); - - @JsonProperty(required = true) - @XmlElement(required = true) - public AnyTypeKind getAnyTypeKind() { - return anyTypeKind; - } - - public void setAnyTypeKind(final AnyTypeKind anyTypeKind) { - this.anyTypeKind = anyTypeKind; - } - - @JsonProperty(required = true) - @XmlElement(required = true) - public String getAnyKey() { - return anyKey; - } - - public void setAnyKey(final String anyKey) { - this.anyKey = anyKey; - } - - @JsonProperty(required = true) - @XmlElement(required = true) - public String getResourceKey() { - return resourceKey; - } - - public void setResourceKey(final String resourceKey) { - this.resourceKey = resourceKey; - } - - @JsonProperty(required = true) - @XmlElement(required = true) - public ReconciliationAction getAction() { - return action; - } - - public void setAction(final ReconciliationAction action) { - this.action = action; - } - - @XmlElementWrapper(name = "actionsClassNames") - @XmlElement(name = "actionsClassName") - @JsonProperty("actionsClassNames") - public List<String> getActionsClassNames() { - return actionsClassNames; - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java deleted file mode 100644 index 19b68c2..0000000 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java +++ /dev/null @@ -1,28 +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.common.lib.types; - -import javax.xml.bind.annotation.XmlEnum; - -@XmlEnum -public enum ReconciliationAction { - PUSH, - PULL - -} http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java index ddbbd5d..bfec63c 100644 --- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java @@ -19,6 +19,8 @@ package org.apache.syncope.common.rest.api.service; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import io.swagger.annotations.Authorization; import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; @@ -29,7 +31,8 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.syncope.common.lib.SyncopeConstants; -import org.apache.syncope.common.lib.to.ReconciliationRequest; +import org.apache.syncope.common.lib.to.PullTaskTO; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.common.lib.to.ReconciliationStatus; import org.apache.syncope.common.lib.types.AnyTypeKind; @@ -60,13 +63,44 @@ public interface ReconciliationService extends JAXRSService { @NotNull @QueryParam("resourceKey") String resourceKey); /** - * Perform the required reconciliation action (PUSH or PULL) to the given user, group or any object and - * External Resource. + * Pushes the given user, group or any object in Syncope onto the External Resource. * - * @param request reconciliation request + * @param anyTypeKind anyTypeKind + * @param anyKey user, group or any object: if value looks like a UUID then it is interpreted as key, otherwise as + * a (user)name + * @param resourceKey resource key + * @param pushTask push specification */ + @ApiResponses( + @ApiResponse(code = 204, message = "Operation was successful")) @POST + @Path("push") @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML }) - void reconcile(@NotNull ReconciliationRequest request); + void push( + @NotNull @QueryParam("anyTypeKind") AnyTypeKind anyTypeKind, + @NotNull @QueryParam("anyKey") String anyKey, + @NotNull @QueryParam("resourceKey") String resourceKey, + @NotNull PushTaskTO pushTask); + + /** + * Pulls the given user, group or any object from the External Resource into Syncope. + * + * @param anyTypeKind anyTypeKind + * @param anyKey user, group or any object: if value looks like a UUID then it is interpreted as key, otherwise as + * a (user)name + * @param resourceKey resource key + * @param pullTask pull specification + */ + @ApiResponses( + @ApiResponse(code = 204, message = "Operation was successful")) + @POST + @Path("pull") + @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML }) + void pull( + @NotNull @QueryParam("anyTypeKind") AnyTypeKind anyTypeKind, + @NotNull @QueryParam("anyKey") String anyKey, + @NotNull @QueryParam("resourceKey") String resourceKey, + @NotNull PullTaskTO pullTask); } http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java index 7dee27b..58fd708 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java @@ -29,14 +29,14 @@ import org.apache.syncope.common.lib.AbstractBaseBean; import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.AttrTO; import org.apache.syncope.common.lib.to.ConnObjectTO; -import org.apache.syncope.common.lib.to.ReconciliationRequest; +import org.apache.syncope.common.lib.to.PullTaskTO; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.common.lib.to.ReconciliationStatus; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO; import org.apache.syncope.core.persistence.api.dao.NotFoundException; -import org.apache.syncope.core.persistence.api.dao.RealmDAO; import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO; import org.apache.syncope.core.persistence.api.entity.Any; import org.apache.syncope.core.persistence.api.entity.AnyUtils; @@ -77,9 +77,6 @@ public class ReconciliationLogic extends AbstractTransactionalLogic<AbstractBase private VirSchemaDAO virSchemaDAO; @Autowired - private RealmDAO realmDAO; - - @Autowired private MappingManager mappingManager; @Autowired @@ -187,37 +184,52 @@ public class ReconciliationLogic extends AbstractTransactionalLogic<AbstractBase } @PreAuthorize("hasRole('" + StandardEntitlement.TASK_EXECUTE + "')") - public void reconcile(final ReconciliationRequest request) { - Pair<Any<?>, Provision> init = init(request.getAnyTypeKind(), request.getAnyKey(), request.getResourceKey()); + public void push( + final AnyTypeKind anyTypeKind, + final String anyKey, + final String resourceKey, + final PushTaskTO pushTask) { + + Pair<Any<?>, Provision> init = init(anyTypeKind, anyKey, resourceKey); SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Reconciliation); try { - List<ProvisioningReport> results = null; - switch (request.getAction()) { - case PUSH: - results = singlePushExecutor.push( - init.getRight(), - connFactory.getConnector(init.getRight().getResource()), - init.getLeft(), - request.getActionsClassNames()); - break; - - case PULL: - results = singlePullExecutor.pull( - init.getRight(), - connFactory.getConnector(init.getRight().getResource()), - init.getRight().getMapping().getConnObjectKeyItem().getExtAttrName(), - mappingManager.getConnObjectKeyValue(init.getLeft(), init.getRight()), - realmDAO.findByFullPath(init.getLeft().getRealm().getFullPath()), - request.getActionsClassNames()); - break; - - default: + List<ProvisioningReport> results = singlePushExecutor.push( + init.getRight(), + connFactory.getConnector(init.getRight().getResource()), + init.getLeft(), + pushTask); + if (!results.isEmpty() && results.get(0).getStatus() == ProvisioningReport.Status.FAILURE) { + sce.getElements().add(results.get(0).getMessage()); } + } catch (JobExecutionException e) { + sce.getElements().add(e.getMessage()); + } + + if (!sce.isEmpty()) { + throw sce; + } + } - if (results != null && !results.isEmpty() - && results.get(0).getStatus() == ProvisioningReport.Status.FAILURE) { + @PreAuthorize("hasRole('" + StandardEntitlement.TASK_EXECUTE + "')") + public void pull( + final AnyTypeKind anyTypeKind, + final String anyKey, + final String resourceKey, + final PullTaskTO pullTask) { + Pair<Any<?>, Provision> init = init(anyTypeKind, anyKey, resourceKey); + + SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Reconciliation); + try { + List<ProvisioningReport> results = singlePullExecutor.pull( + init.getRight(), + connFactory.getConnector(init.getRight().getResource()), + init.getRight().getMapping().getConnObjectKeyItem().getExtAttrName(), + mappingManager.getConnObjectKeyValue(init.getLeft(), init.getRight()), + init.getLeft().getRealm(), + pullTask); + if (!results.isEmpty() && results.get(0).getStatus() == ProvisioningReport.Status.FAILURE) { sce.getElements().add(results.get(0).getMessage()); } } catch (JobExecutionException e) { http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java ---------------------------------------------------------------------- diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java index ba4d160..000ee45 100644 --- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java @@ -19,6 +19,7 @@ package org.apache.syncope.core.provisioning.api.pushpull; import java.util.List; +import org.apache.syncope.common.lib.to.PullTaskTO; import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.resource.Provision; import org.apache.syncope.core.provisioning.api.Connector; @@ -32,5 +33,5 @@ public interface SyncopeSinglePullExecutor { String connObjectKey, String connObjectValue, Realm realm, - List<String> actionsClassNames) throws JobExecutionException; + PullTaskTO pullTaskTO) throws JobExecutionException; } http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java ---------------------------------------------------------------------- diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java index eb18f00..a8256cd 100644 --- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java @@ -19,6 +19,7 @@ package org.apache.syncope.core.provisioning.api.pushpull; import java.util.List; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.core.persistence.api.entity.Any; import org.apache.syncope.core.persistence.api.entity.resource.Provision; import org.apache.syncope.core.provisioning.api.Connector; @@ -30,5 +31,5 @@ public interface SyncopeSinglePushExecutor { Provision provision, Connector connector, Any<?> any, - List<String> actionsClassNames) throws JobExecutionException; + PushTaskTO pushTaskTO) throws JobExecutionException; } http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java index 76bfe3e..53c4258 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java @@ -69,6 +69,7 @@ public abstract class AbstractSyncopeResultHandler<T extends ProvisioningTask, A @Autowired protected PropagationTaskExecutor taskExecutor; + @Autowired protected AnyObjectWorkflowAdapter awfAdapter; /** http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java index 7df7f23..542f92d 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java @@ -22,16 +22,22 @@ 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.syncope.common.lib.to.AnyTO; +import org.apache.syncope.common.lib.to.PullTaskTO; +import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.ConflictResolutionAction; import org.apache.syncope.common.lib.types.MatchingRule; import org.apache.syncope.common.lib.types.PullMode; import org.apache.syncope.common.lib.types.UnmatchingRule; +import org.apache.syncope.core.persistence.api.entity.AnyType; import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.VirSchema; 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.AnyTemplatePullTask; import org.apache.syncope.core.persistence.api.entity.task.PullTask; import org.apache.syncope.core.provisioning.api.Connector; import org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler; @@ -41,18 +47,23 @@ import org.apache.syncope.core.provisioning.api.pushpull.PullActions; import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandler; import org.apache.syncope.core.provisioning.api.pushpull.SyncopeSinglePullExecutor; import org.apache.syncope.core.provisioning.java.utils.MappingUtils; +import org.apache.syncope.core.provisioning.java.utils.TemplateUtils; import org.apache.syncope.core.spring.ApplicationContextProvider; import org.identityconnectors.framework.common.objects.AttributeBuilder; import org.identityconnectors.framework.common.objects.OperationOptions; import org.identityconnectors.framework.common.objects.filter.Filter; import org.identityconnectors.framework.common.objects.filter.FilterBuilder; import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.stereotype.Component; @Component public class SinglePullJobDelegate extends PullJobDelegate implements SyncopeSinglePullExecutor { + @Autowired + private TemplateUtils templateUtils; + @Override public List<ProvisioningReport> pull( final Provision provision, @@ -60,12 +71,12 @@ public class SinglePullJobDelegate extends PullJobDelegate implements SyncopeSin final String connObjectKey, final String connObjectValue, final Realm realm, - final List<String> actionsClassNames) throws JobExecutionException { + final PullTaskTO pullTaskTO) throws JobExecutionException { LOG.debug("Executing pull on {}", provision.getResource()); List<PullActions> actions = new ArrayList<>(); - for (String className : actionsClassNames) { + for (String className : pullTaskTO.getActionsClassNames()) { try { Class<?> actionsClass = Class.forName(className); PullActions pullActions = (PullActions) ApplicationContextProvider.getBeanFactory(). @@ -89,12 +100,33 @@ public class SinglePullJobDelegate extends PullJobDelegate implements SyncopeSin PullTask pullTask = entityFactory.newEntity(PullTask.class); pullTask.setResource(provision.getResource()); - pullTask.setMatchingRule(MatchingRule.UPDATE); - pullTask.setUnmatchingRule(UnmatchingRule.PROVISION); + pullTask.setMatchingRule(pullTaskTO.getMatchingRule() == null + ? MatchingRule.UPDATE : pullTaskTO.getMatchingRule()); + pullTask.setUnmatchingRule(pullTaskTO.getUnmatchingRule() == null + ? UnmatchingRule.PROVISION : pullTaskTO.getUnmatchingRule()); pullTask.setPullMode(PullMode.FILTERED_RECONCILIATION); - pullTask.setPerformCreate(true); - pullTask.setPerformUpdate(true); + pullTask.setPerformCreate(pullTaskTO.isPerformCreate()); + pullTask.setPerformUpdate(pullTaskTO.isPerformUpdate()); + pullTask.setPerformDelete(pullTaskTO.isPerformDelete()); pullTask.setDestinationRealm(realm); + // validate JEXL expressions from templates and proceed if fine + templateUtils.check(pullTaskTO.getTemplates(), ClientExceptionType.InvalidPullTask); + for (Map.Entry<String, AnyTO> entry : pullTaskTO.getTemplates().entrySet()) { + AnyType type = anyTypeDAO.find(entry.getKey()); + if (type == null) { + LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey()); + } else { + AnyTemplatePullTask anyTemplate = pullTask.getTemplate(type); + if (anyTemplate == null) { + anyTemplate = entityFactory.newEntity(AnyTemplatePullTask.class); + anyTemplate.setAnyType(type); + anyTemplate.setPullTask(pullTask); + + pullTask.add(anyTemplate); + } + anyTemplate.set(entry.getValue()); + } + } profile = new ProvisioningProfile<>(connector, pullTask); profile.setDryRun(false); http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java index eceb4fb..3f1e655 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java @@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.java.pushpull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.common.lib.types.MatchingRule; import org.apache.syncope.common.lib.types.UnmatchingRule; import org.apache.syncope.core.persistence.api.entity.Any; @@ -45,12 +46,12 @@ public class SinglePushJobDelegate extends PushJobDelegate implements SyncopeSin final Provision provision, final Connector connector, final Any<?> any, - final List<String> actionsClassNames) throws JobExecutionException { + final PushTaskTO pushTaskTO) throws JobExecutionException { LOG.debug("Executing push on {}", provision.getResource()); List<PushActions> actions = new ArrayList<>(); - for (String className : actionsClassNames) { + for (String className : pushTaskTO.getActionsClassNames()) { try { Class<?> actionsClass = Class.forName(className); @@ -65,10 +66,13 @@ public class SinglePushJobDelegate extends PushJobDelegate implements SyncopeSin try { PushTask pushTask = entityFactory.newEntity(PushTask.class); pushTask.setResource(provision.getResource()); - pushTask.setMatchingRule(MatchingRule.UPDATE); - pushTask.setUnmatchingRule(UnmatchingRule.PROVISION); - pushTask.setPerformCreate(true); - pushTask.setPerformUpdate(true); + pushTask.setMatchingRule(pushTaskTO.getMatchingRule() == null + ? MatchingRule.LINK : pushTaskTO.getMatchingRule()); + pushTask.setUnmatchingRule(pushTaskTO.getUnmatchingRule() == null + ? UnmatchingRule.ASSIGN : pushTaskTO.getUnmatchingRule()); + pushTask.setPerformCreate(pushTaskTO.isPerformCreate()); + pushTask.setPerformUpdate(pushTaskTO.isPerformUpdate()); + pushTask.setPerformDelete(pushTaskTO.isPerformDelete()); profile = new ProvisioningProfile<>(connector, pushTask); profile.getActions().addAll(actions); http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java index 80d89d5..ad460cb 100644 --- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java +++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java @@ -18,7 +18,8 @@ */ package org.apache.syncope.core.rest.cxf.service; -import org.apache.syncope.common.lib.to.ReconciliationRequest; +import org.apache.syncope.common.lib.to.PullTaskTO; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.common.lib.to.ReconciliationStatus; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.rest.api.service.ReconciliationService; @@ -45,9 +46,30 @@ public class ReconciliationServiceImpl extends AbstractServiceImpl implements Re } @Override - public void reconcile(final ReconciliationRequest request) { - request.setAnyKey( - getActualKey(anyUtilsFactory.getInstance(request.getAnyTypeKind()).dao(), request.getAnyKey())); - logic.reconcile(request); + public void push( + final AnyTypeKind anyTypeKind, + final String anyKey, + final String resourceKey, + final PushTaskTO pushTask) { + + logic.push( + anyTypeKind, + getActualKey(anyUtilsFactory.getInstance(anyTypeKind).dao(), anyKey), + resourceKey, + pushTask); + } + + @Override + public void pull( + final AnyTypeKind anyTypeKind, + final String anyKey, + final String resourceKey, + final PullTaskTO pullTask) { + + logic.pull( + anyTypeKind, + getActualKey(anyUtilsFactory.getInstance(anyTypeKind).dao(), anyKey), + resourceKey, + pullTask); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/a07f3b94/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java index d6cd241..8fd8680 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java @@ -28,10 +28,11 @@ import java.util.Date; import javax.sql.DataSource; import org.apache.syncope.common.lib.to.AnyObjectTO; import org.apache.syncope.common.lib.to.AttrTO; -import org.apache.syncope.common.lib.to.ReconciliationRequest; +import org.apache.syncope.common.lib.to.PullTaskTO; +import org.apache.syncope.common.lib.to.PushTaskTO; import org.apache.syncope.common.lib.to.ReconciliationStatus; import org.apache.syncope.common.lib.types.AnyTypeKind; -import org.apache.syncope.common.lib.types.ReconciliationAction; +import org.apache.syncope.common.lib.types.UnmatchingRule; import org.apache.syncope.fit.AbstractITCase; import org.identityconnectors.framework.common.objects.OperationalAttributes; import org.junit.Test; @@ -69,12 +70,10 @@ public class ReconciliationITCase extends AbstractITCase { assertNull(status.getOnResource()); // 4. push - ReconciliationRequest request = new ReconciliationRequest(); - request.setAction(ReconciliationAction.PUSH); - request.setAnyKey(printer.getKey()); - request.setAnyTypeKind(AnyTypeKind.ANY_OBJECT); - request.setResourceKey("resource-db-scripted"); - reconciliationService.reconcile(request); + PushTaskTO pushTask = new PushTaskTO(); + pushTask.setPerformCreate(true); + pushTask.setUnmatchingRule(UnmatchingRule.PROVISION); + reconciliationService.push(AnyTypeKind.ANY_OBJECT, printer.getKey(), "resource-db-scripted", pushTask); // 5. verify that printer is now propagated assertEquals(1, jdbcTemplate.queryForList( @@ -122,12 +121,9 @@ public class ReconciliationITCase extends AbstractITCase { assertNotEquals(status.getOnSyncope().getAttr("LOCATION"), status.getOnResource().getAttr("LOCATION")); // 4. pull - ReconciliationRequest request = new ReconciliationRequest(); - request.setAction(ReconciliationAction.PULL); - request.setAnyKey(printer.getKey()); - request.setAnyTypeKind(AnyTypeKind.ANY_OBJECT); - request.setResourceKey("resource-db-scripted"); - reconciliationService.reconcile(request); + PullTaskTO pullTask = new PullTaskTO(); + pullTask.setPerformUpdate(true); + reconciliationService.pull(AnyTypeKind.ANY_OBJECT, printer.getName(), "resource-db-scripted", pullTask); // 5. verify reconciliation result (and resource is still not assigned) printer = anyObjectService.read(printer.getKey());