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 2018/04/12 10:42:09 UTC
[6/6] syncope git commit: [SYNCOPE-1299] Core implementation
[SYNCOPE-1299] Core implementation
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e5860a76
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e5860a76
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e5860a76
Branch: refs/heads/master
Commit: e5860a76a5584edf780df180eb9229ddf44de684
Parents: 3c4a351
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Apr 12 11:50:16 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Apr 12 12:41:49 2018 +0200
----------------------------------------------------------------------
.../common/lib/to/ProvisioningTaskTO.java | 3 +-
.../common/lib/to/ReconciliationRequest.java | 100 ++++++++
.../common/lib/to/ReconciliationStatus.java | 56 +++++
.../common/lib/types/ClientExceptionType.java | 1 +
.../common/lib/types/ReconciliationAction.java | 28 +++
.../rest/api/service/ReconciliationService.java | 78 +++++++
.../syncope/core/logic/ReconciliationLogic.java | 232 +++++++++++++++++++
.../core/persistence/api/entity/AnyUtils.java | 7 +-
.../persistence/jpa/dao/JPAAnyObjectDAO.java | 4 +-
.../persistence/jpa/entity/JPAAnyUtils.java | 26 ++-
.../api/pushpull/SyncopeSinglePullExecutor.java | 37 +++
.../api/pushpull/SyncopeSinglePushExecutor.java | 34 +++
.../provisioning/java/MappingManagerImpl.java | 2 +-
.../pushpull/AbstractPullResultHandler.java | 6 +-
.../pushpull/AbstractPushResultHandler.java | 2 +-
.../java/pushpull/PullJobDelegate.java | 49 ++--
.../provisioning/java/pushpull/PullUtils.java | 23 +-
.../java/pushpull/PushJobDelegate.java | 86 ++-----
.../java/pushpull/SinglePullJobDelegate.java | 174 ++++++++++++++
.../java/pushpull/SinglePushJobDelegate.java | 117 ++++++++++
.../java/utils/ConnObjectUtils.java | 4 +-
.../rest/cxf/service/AbstractAnyService.java | 26 +--
.../rest/cxf/service/AbstractServiceImpl.java | 15 ++
.../rest/cxf/service/AnyObjectServiceImpl.java | 2 +-
.../core/rest/cxf/service/GroupServiceImpl.java | 2 +-
.../cxf/service/ReconciliationServiceImpl.java | 53 +++++
.../core/rest/cxf/service/UserServiceImpl.java | 2 +-
.../org/apache/syncope/fit/AbstractITCase.java | 4 +
.../syncope/fit/core/ReconciliationITCase.java | 134 +++++++++++
29 files changed, 1151 insertions(+), 156 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisioningTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisioningTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisioningTaskTO.java
index 27d4f9b..cdef683 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisioningTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisioningTaskTO.java
@@ -33,8 +33,7 @@ import org.apache.syncope.common.lib.types.UnmatchingRule;
@XmlRootElement(name = "provisioningTask")
@XmlType
@XmlSeeAlso({ PushTaskTO.class, PullTaskTO.class })
-@Schema(
- allOf = { SchedTaskTO.class },
+@Schema(allOf = { SchedTaskTO.class },
subTypes = { PushTaskTO.class, PullTaskTO.class }, discriminatorProperty = "@class")
public abstract class ProvisioningTaskTO extends SchedTaskTO {
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..2ebf699
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 boolean remediation;
+
+ private final List<String> actions = 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;
+ }
+
+ public boolean isRemediation() {
+ return remediation;
+ }
+
+ public void setRemediation(final boolean remediation) {
+ this.remediation = remediation;
+ }
+
+ @XmlElementWrapper(name = "actions")
+ @XmlElement(name = "action")
+ @JsonProperty("actions")
+ public List<String> getActions() {
+ return actions;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationStatus.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationStatus.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationStatus.java
new file mode 100644
index 0000000..2d7af98
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationStatus.java
@@ -0,0 +1,56 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Reconciliation status.
+ */
+@XmlRootElement(name = "reconciliationStatus")
+@XmlType
+public class ReconciliationStatus extends AbstractBaseBean {
+
+ private static final long serialVersionUID = -8516345256596521490L;
+
+ private ConnObjectTO onSyncope;
+
+ private ConnObjectTO onResource;
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public ConnObjectTO getOnSyncope() {
+ return onSyncope;
+ }
+
+ public void setOnSyncope(final ConnObjectTO onSyncope) {
+ this.onSyncope = onSyncope;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public ConnObjectTO getOnResource() {
+ return onResource;
+ }
+
+ public void setOnResource(final ConnObjectTO onResource) {
+ this.onResource = onResource;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index ada4a1e..8a8f744 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -74,6 +74,7 @@ public enum ClientExceptionType {
InUse(Response.Status.BAD_REQUEST),
Scheduling(Response.Status.BAD_REQUEST),
DelegatedAdministration(Response.Status.FORBIDDEN),
+ Reconciliation(Response.Status.BAD_REQUEST),
Unknown(Response.Status.BAD_REQUEST),
Workflow(Response.Status.BAD_REQUEST);
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..19b68c2
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java
@@ -0,0 +1,28 @@
+/*
+ * 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/e5860a76/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
new file mode 100644
index 0000000..77eb840
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
@@ -0,0 +1,78 @@
+/*
+ * 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.rest.api.service;
+
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+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.ReconciliationStatus;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+
+/**
+ * REST operations for tasks.
+ */
+@Tag(name = "Reconciliation")
+@SecurityRequirements({
+ @SecurityRequirement(name = "BasicAuthentication"),
+ @SecurityRequirement(name = "Bearer") })
+@Path("reconciliation")
+public interface ReconciliationService extends JAXRSService {
+
+ /**
+ * Gets current attributes on Syncope and on the given External Resource, related to given user, group or
+ * any object.
+ *
+ * @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
+ * @return reconciliation status
+ */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ ReconciliationStatus status(
+ @NotNull @QueryParam("anyTypeKind") AnyTypeKind anyTypeKind,
+ @NotNull @QueryParam("anyKey") String anyKey,
+ @NotNull @QueryParam("resourceKey") String resourceKey);
+
+ /**
+ * Perform the required reconciliation action (PUSH or PULL) to the given user, group or any object and
+ * External Resource.
+ *
+ * @param request reconciliation request
+ */
+ @ApiResponses(
+ @ApiResponse(responseCode = "204", description = "Operation was successful"))
+ @POST
+ @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);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..a36c159
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -0,0 +1,232 @@
+/*
+ * 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.logic;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.collections.IteratorChain;
+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.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;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.ConnectorFactory;
+import org.apache.syncope.core.provisioning.api.MappingManager;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
+import org.apache.syncope.core.provisioning.api.pushpull.SyncopeSinglePullExecutor;
+import org.apache.syncope.core.provisioning.api.pushpull.SyncopeSinglePushExecutor;
+import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ReconciliationLogic extends AbstractTransactionalLogic<AbstractBaseBean> {
+
+ @Autowired
+ private AnyUtilsFactory anyUtilsFactory;
+
+ @Autowired
+ private ExternalResourceDAO resourceDAO;
+
+ @Autowired
+ private VirSchemaDAO virSchemaDAO;
+
+ @Autowired
+ private RealmDAO realmDAO;
+
+ @Autowired
+ private MappingManager mappingManager;
+
+ @Autowired
+ private ConnectorFactory connFactory;
+
+ @Autowired
+ private SyncopeSinglePullExecutor singlePullExecutor;
+
+ @Autowired
+ private SyncopeSinglePushExecutor singlePushExecutor;
+
+ @SuppressWarnings("unchecked")
+ private Pair<Any<?>, Provision> init(final AnyTypeKind anyTypeKind, final String anyKey, final String resourceKey) {
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
+
+ Any<?> any = anyUtils.dao().authFind(anyKey);
+ if (any == null) {
+ throw new NotFoundException(anyTypeKind + " '" + anyKey + "'");
+ }
+
+ ExternalResource resource = resourceDAO.find(resourceKey);
+ if (resource == null) {
+ throw new NotFoundException("Resource '" + resourceKey + "'");
+ }
+ Provision provision = resource.getProvision(any.getType()).orElseThrow(()
+ -> new NotFoundException("Provision for " + any.getType() + " on Resource '" + resourceKey + "'"));
+ if (provision.getMapping() == null) {
+ throw new NotFoundException("Mapping for " + any.getType() + " on Resource '" + resourceKey + "'");
+ }
+
+ return (Pair<Any<?>, Provision>) Pair.of(any, provision);
+ }
+
+ private ConnObjectTO getOnSyncope(final Any<?> any, final Provision provision, final String resourceKey) {
+ Pair<String, Set<Attribute>> attrs = mappingManager.prepareAttrs(any, null, false, true, provision);
+
+ MappingItem connObjectKey = provision.getMapping().getConnObjectKeyItem().orElseThrow(()
+ -> new NotFoundException("No RemoteKey set for " + resourceKey));
+
+ ConnObjectTO connObjectTO = ConnObjectUtils.getConnObjectTO(attrs.getRight());
+ if (attrs.getLeft() != null) {
+ connObjectTO.getAttrs().add(new AttrTO.Builder().
+ schema(connObjectKey.getExtAttrName()).value(attrs.getLeft()).build());
+ connObjectTO.getAttrs().add(new AttrTO.Builder().
+ schema(Uid.NAME).value(attrs.getLeft()).build());
+ }
+
+ return connObjectTO;
+ }
+
+ private ConnObjectTO getOnResource(final Any<?> any, final Provision provision) {
+ // 1. build connObjectKeyItem
+ MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision).orElseThrow(()
+ -> new NotFoundException("ConnObjectKey for " + any.getType()
+ + " on resource '" + provision.getResource().getKey() + "'"));
+ String connObjectKeyValue = mappingManager.getConnObjectKeyValue(any, provision).orElseThrow(()
+ -> new NotFoundException("Value for ConnObjectKey for " + any.getType()
+ + " on resource '" + provision.getResource().getKey() + "'"));
+
+ // 2. determine attributes to query
+ Set<MappingItem> linkinMappingItems = virSchemaDAO.findByProvision(provision).stream().
+ map(virSchema -> virSchema.asLinkingMappingItem()).collect(Collectors.toSet());
+ Iterator<MappingItem> mapItems = new IteratorChain<>(
+ provision.getMapping().getItems().iterator(),
+ linkinMappingItems.iterator());
+
+ // 3. read from the underlying connector
+ ConnObjectTO connObjectTO = null;
+
+ Connector connector = connFactory.getConnector(provision.getResource());
+ ConnectorObject connectorObject = connector.getObject(
+ provision.getObjectClass(),
+ AttributeBuilder.build(connObjectKeyItem.getExtAttrName(), connObjectKeyValue),
+ MappingUtils.buildOperationOptions(mapItems));
+ if (connectorObject != null) {
+ Set<Attribute> attributes = connectorObject.getAttributes();
+ if (AttributeUtil.find(Uid.NAME, attributes) == null) {
+ attributes.add(connectorObject.getUid());
+ }
+ if (AttributeUtil.find(Name.NAME, attributes) == null) {
+ attributes.add(connectorObject.getName());
+ }
+
+ connObjectTO = ConnObjectUtils.getConnObjectTO(attributes);
+ }
+
+ return connObjectTO;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.RESOURCE_GET_CONNOBJECT + "')")
+ public ReconciliationStatus status(final AnyTypeKind anyTypeKind, final String anyKey, final String resourceKey) {
+ Pair<Any<?>, Provision> init = init(anyTypeKind, anyKey, resourceKey);
+
+ ReconciliationStatus status = new ReconciliationStatus();
+ status.setOnSyncope(getOnSyncope(init.getLeft(), init.getRight(), resourceKey));
+ status.setOnResource(getOnResource(init.getLeft(), init.getRight()));
+
+ return status;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.TASK_EXECUTE + "')")
+ public void reconcile(final ReconciliationRequest request) {
+ Pair<Any<?>, Provision> init = init(request.getAnyTypeKind(), request.getAnyKey(), request.getResourceKey());
+
+ 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.getActions());
+ break;
+
+ case PULL:
+ results = singlePullExecutor.pull(
+ init.getRight(),
+ connFactory.getConnector(init.getRight().getResource()),
+ init.getRight().getMapping().getConnObjectKeyItem().get().getExtAttrName(),
+ mappingManager.getConnObjectKeyValue(init.getLeft(), init.getRight()).get(),
+ realmDAO.findByFullPath(init.getLeft().getRealm().getFullPath()),
+ request.isRemediation(),
+ request.getActions());
+ break;
+
+ default:
+ }
+
+ if (results != null && !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;
+ }
+ }
+
+ @Override
+ protected AbstractBaseBean resolveReference(final Method method, final Object... os)
+ throws UnresolvedReferenceException {
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
index 09079da..e59350e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
@@ -22,11 +22,12 @@ import java.util.Set;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
public interface AnyUtils {
- AnyTypeKind getAnyTypeKind();
+ AnyTypeKind anyTypeKind();
<T extends Any<?>> Class<T> anyClass();
@@ -45,9 +46,11 @@ public interface AnyUtils {
<T extends PlainAttrValue> T newPlainAttrUniqueValue();
<T extends PlainAttrValue> T clonePlainAttrValue(T src);
-
+
<T extends AnyTO> T newAnyTO();
+ <A extends Any<?>> AnyDAO<A> dao();
+
Set<ExternalResource> getAllResources(Any<?> any);
<S extends Schema> AllowedSchemas<S> getAllowedSchemas(Any<?> any, Class<S> reference);
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index abba39c..64550a7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -92,8 +92,8 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
@Transactional(readOnly = true)
@Override
- public String findKey(final String username) {
- return findKey(username, JPAAnyObject.TABLE);
+ public String findKey(final String name) {
+ return findKey(name, JPAAnyObject.TABLE);
}
@Transactional(readOnly = true)
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
index b687aa1..15fa17c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
@@ -32,6 +32,7 @@ import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -113,7 +114,7 @@ public class JPAAnyUtils implements AnyUtils {
}
@Override
- public AnyTypeKind getAnyTypeKind() {
+ public AnyTypeKind anyTypeKind() {
return anyTypeKind;
}
@@ -337,6 +338,29 @@ public class JPAAnyUtils implements AnyUtils {
return result;
}
+ @Override
+ public <A extends Any<?>> AnyDAO<A> dao() {
+ AnyDAO<A> result = null;
+
+ switch (anyTypeKind) {
+ case USER:
+ result = (AnyDAO<A>) userDAO;
+ break;
+
+ case GROUP:
+ result = (AnyDAO<A>) groupDAO;
+ break;
+
+ case ANY_OBJECT:
+ result = (AnyDAO<A>) anyObjectDAO;
+ break;
+
+ default:
+ }
+
+ return result;
+ }
+
@Transactional(readOnly = true)
@Override
public Set<ExternalResource> getAllResources(final Any<?> any) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..bbf8430
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.util.List;
+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;
+import org.quartz.JobExecutionException;
+
+public interface SyncopeSinglePullExecutor {
+
+ List<ProvisioningReport> pull(
+ Provision provision,
+ Connector connector,
+ String connObjectKey,
+ String connObjectValue,
+ Realm realm,
+ boolean remediation,
+ List<String> actions) throws JobExecutionException;
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..9068301
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import java.util.List;
+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;
+import org.quartz.JobExecutionException;
+
+public interface SyncopeSinglePushExecutor {
+
+ List<ProvisioningReport> push(
+ Provision provision,
+ Connector connector,
+ Any<?> any,
+ List<String> actions) throws JobExecutionException;
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index 70a8647..83d8e76 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -674,7 +674,7 @@ public class MappingManagerImpl implements MappingManager {
IntAttrName intAttrName;
try {
- intAttrName = intAttrNameParser.parse(mapItem.getIntAttrName(), anyUtils.getAnyTypeKind());
+ intAttrName = intAttrNameParser.parse(mapItem.getIntAttrName(), anyUtils.anyTypeKind());
} catch (ParseException e) {
LOG.error("Invalid intAttrName '{}' specified, ignoring", mapItem.getIntAttrName(), e);
return;
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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 3abbd84..35e0356 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
@@ -171,7 +171,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
ProvisioningReport ignoreResult = new ProvisioningReport();
ignoreResult.setOperation(ResourceOperation.NONE);
ignoreResult.setAnyType(provision == null
- ? getAnyUtils().getAnyTypeKind().name() : provision.getAnyType().getKey());
+ ? getAnyUtils().anyTypeKind().name() : provision.getAnyType().getKey());
ignoreResult.setStatus(ProvisioningReport.Status.IGNORE);
ignoreResult.setKey(null);
ignoreResult.setName(delta.getObject().getName().getNameValue());
@@ -914,7 +914,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
}
notificationManager.createTasks(AuditElements.EventCategoryType.PULL,
- getAnyUtils().getAnyTypeKind().name().toLowerCase(),
+ getAnyUtils().anyTypeKind().name().toLowerCase(),
profile.getTask().getResource().getKey(),
event,
result,
@@ -924,7 +924,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
furtherInput);
auditManager.audit(AuditElements.EventCategoryType.PULL,
- getAnyUtils().getAnyTypeKind().name().toLowerCase(),
+ getAnyUtils().anyTypeKind().name().toLowerCase(),
profile.getTask().getResource().getKey(),
event,
result,
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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 5f74388..63f397b 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
@@ -256,7 +256,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
: null;
LOG.debug("Propagating {} with key {} towards {}",
- anyUtils.getAnyTypeKind(), any.getKey(), profile.getTask().getResource());
+ anyUtils.anyTypeKind(), any.getKey(), profile.getTask().getResource());
Object output = null;
Result resultStatus = null;
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index 9edfd6b..f8b73a2 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -80,14 +80,6 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
protected ProvisioningProfile<PullTask, PullActions> profile;
- protected RealmPullResultHandler rhandler;
-
- protected AnyObjectPullResultHandler ahandler;
-
- protected UserPullResultHandler uhandler;
-
- protected GroupPullResultHandler ghandler;
-
@Override
public void setLatestSyncToken(final ObjectClass objectClass, final SyncToken latestSyncToken) {
latestSyncTokens.put(objectClass, latestSyncToken);
@@ -168,30 +160,18 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
}
protected RealmPullResultHandler buildRealmHandler() {
- RealmPullResultHandler handler = (RealmPullResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (RealmPullResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultRealmPullResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
- handler.setPullExecutor(this);
-
- return handler;
}
protected AnyObjectPullResultHandler buildAnyObjectHandler() {
- AnyObjectPullResultHandler handler = (AnyObjectPullResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (AnyObjectPullResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultAnyObjectPullResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
- handler.setPullExecutor(this);
-
- return handler;
}
protected UserPullResultHandler buildUserHandler() {
- UserPullResultHandler handler = (UserPullResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (UserPullResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultUserPullResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
- handler.setPullExecutor(this);
-
- return handler;
}
protected GroupPullResultHandler buildGroupHandler() {
@@ -245,7 +225,9 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
OperationOptions options = MappingUtils.buildOperationOptions(
MappingUtils.getPullItems(orgUnit.getItems()).iterator());
- rhandler = buildRealmHandler();
+ RealmPullResultHandler handler = buildRealmHandler();
+ handler.setProfile(profile);
+ handler.setPullExecutor(this);
try {
switch (pullTask.getPullMode()) {
@@ -257,7 +239,7 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
connector.sync(
orgUnit.getObjectClass(),
orgUnit.getSyncToken(),
- rhandler,
+ handler,
options);
if (!dryRun) {
@@ -271,14 +253,14 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
ImplementationManager.build(pullTask.getReconFilterBuilder());
connector.filteredReconciliation(orgUnit.getObjectClass(),
filterBuilder,
- rhandler,
+ handler,
options);
break;
case FULL_RECONCILIATION:
default:
connector.fullReconciliation(orgUnit.getObjectClass(),
- rhandler,
+ handler,
options);
break;
}
@@ -288,18 +270,15 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
}
// ...then provisions for any types
- ahandler = buildAnyObjectHandler();
- uhandler = buildUserHandler();
- ghandler = buildGroupHandler();
-
+ SyncopePullResultHandler handler;
+ GroupPullResultHandler ghandler = buildGroupHandler();
for (Provision provision : pullTask.getResource().getProvisions()) {
if (provision.getMapping() != null) {
status.set("Pulling " + provision.getObjectClass().getObjectClassValue());
- SyncopePullResultHandler handler;
switch (provision.getAnyType().getKind()) {
case USER:
- handler = uhandler;
+ handler = buildUserHandler();
break;
case GROUP:
@@ -308,8 +287,10 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
case ANY_OBJECT:
default:
- handler = ahandler;
+ handler = buildAnyObjectHandler();
}
+ handler.setProfile(profile);
+ handler.setPullExecutor(this);
try {
Set<MappingItem> linkingMappingItems = virSchemaDAO.findByProvision(provision).stream().
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
index 77ca4e1..941e5e4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
@@ -26,11 +26,10 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
-import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
@@ -148,10 +147,10 @@ public class PullUtils {
try {
List<String> anyKeys = match(connObj, provision.get(), anyUtils);
if (anyKeys.isEmpty()) {
- LOG.debug("No matching {} found for {}, aborting", anyUtils.getAnyTypeKind(), connObj);
+ LOG.debug("No matching {} found for {}, aborting", anyUtils.anyTypeKind(), connObj);
} else {
if (anyKeys.size() > 1) {
- LOG.warn("More than one {} found {} - taking first only", anyUtils.getAnyTypeKind(), anyKeys);
+ LOG.warn("More than one {} found {} - taking first only", anyUtils.anyTypeKind(), anyKeys);
}
result = Optional.ofNullable(anyKeys.iterator().next());
@@ -164,14 +163,6 @@ public class PullUtils {
return result;
}
- private AnyDAO<?> getAnyDAO(final AnyTypeKind anyTypeKind) {
- return AnyTypeKind.USER == anyTypeKind
- ? userDAO
- : AnyTypeKind.ANY_OBJECT == anyTypeKind
- ? anyObjectDAO
- : groupDAO;
- }
-
private List<String> findByConnObjectKey(
final ConnectorObject connObj, final Provision provision, final AnyUtils anyUtils) {
@@ -213,7 +204,7 @@ public class PullUtils {
if (intAttrName.getField() != null) {
switch (intAttrName.getField()) {
case "key":
- Any<?> any = getAnyDAO(provision.getAnyType().getKind()).find(connObjectKey);
+ Any<?> any = anyUtils.dao().find(connObjectKey);
if (any != null) {
result.add(any.getKey());
}
@@ -256,13 +247,13 @@ public class PullUtils {
}
}
- result.addAll(getAnyDAO(provision.getAnyType().getKind()).
+ result.addAll(anyUtils.dao().
findByPlainAttrValue(intAttrName.getSchemaName(), value).stream().
map(Entity::getKey).collect(Collectors.toList()));
break;
case DERIVED:
- result.addAll(getAnyDAO(provision.getAnyType().getKind()).
+ result.addAll(anyUtils.dao().
findByDerAttrValue(intAttrName.getSchemaName(), connObjectKey).stream().
map(Entity::getKey).collect(Collectors.toList()));
break;
@@ -312,7 +303,7 @@ public class PullUtils {
try {
return rule.isPresent()
- ? findByCorrelationRule(connObj, provision, rule.get(), anyUtils.getAnyTypeKind())
+ ? findByCorrelationRule(connObj, provision, rule.get(), anyUtils.anyTypeKind())
: findByConnObjectKey(connObj, provision, anyUtils);
} catch (RuntimeException e) {
LOG.error("Could not match {} with any existing {}", connObj, provision.getAnyType(), e);
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
index b813e71..2207f42 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PushJobDelegate.java
@@ -27,18 +27,15 @@ import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.spring.ApplicationContextProvider;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -63,41 +60,21 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
/**
- * User DAO.
- */
- @Autowired
- protected UserDAO userDAO;
-
- /**
* Search DAO.
*/
@Autowired
protected AnySearchDAO searchDAO;
- /**
- * Group DAO.
- */
@Autowired
- protected GroupDAO groupDAO;
-
- @Autowired
- protected AnyObjectDAO anyObjectDAO;
+ protected RealmDAO realmDAO;
@Autowired
- protected RealmDAO realmDAO;
+ protected AnyUtilsFactory anyUtilsFactory;
protected ProvisioningProfile<PushTask, PushActions> profile;
protected final Map<String, MutablePair<Integer, String>> handled = new HashMap<>();
- protected RealmPushResultHandler rhandler;
-
- protected AnyObjectPushResultHandler ahandler;
-
- protected UserPushResultHandler uhandler;
-
- protected GroupPushResultHandler ghandler;
-
protected void reportHandled(final String anyType, final String key) {
MutablePair<Integer, String> pair = handled.get(anyType);
if (pair == null) {
@@ -125,25 +102,6 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
return status.get();
}
- protected AnyDAO<?> getAnyDAO(final AnyTypeKind anyTypeKind) {
- AnyDAO<?> result;
- switch (anyTypeKind) {
- case USER:
- result = userDAO;
- break;
-
- case GROUP:
- result = groupDAO;
- break;
-
- case ANY_OBJECT:
- default:
- result = anyObjectDAO;
- }
-
- return result;
- }
-
protected void doHandle(
final List<? extends Any<?>> anys,
final SyncopePushResultHandler handler,
@@ -168,35 +126,23 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
}
protected RealmPushResultHandler buildRealmHandler() {
- RealmPushResultHandler handler = (RealmPushResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (RealmPushResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultRealmPushResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
-
- return handler;
}
protected AnyObjectPushResultHandler buildAnyObjectHandler() {
- AnyObjectPushResultHandler handler = (AnyObjectPushResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (AnyObjectPushResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultAnyObjectPushResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
-
- return handler;
}
protected UserPushResultHandler buildUserHandler() {
- UserPushResultHandler handler = (UserPushResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (UserPushResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultUserPushResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
-
- return handler;
}
protected GroupPushResultHandler buildGroupHandler() {
- GroupPushResultHandler handler = (GroupPushResultHandler) ApplicationContextProvider.getBeanFactory().
+ return (GroupPushResultHandler) ApplicationContextProvider.getBeanFactory().
createBean(DefaultGroupPushResultHandler.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
- handler.setProfile(profile);
-
- return handler;
}
@Override
@@ -233,13 +179,14 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
if (pushTask.getResource().getOrgUnit() != null) {
status.set("Pushing realms");
- rhandler = buildRealmHandler();
+ RealmPushResultHandler handler = buildRealmHandler();
+ handler.setProfile(profile);
for (Realm realm : realmDAO.findDescendants(profile.getTask().getSourceRealm())) {
// Never push the root realm
if (realm.getParent() != null) {
try {
- rhandler.handle(realm.getKey());
+ handler.handle(realm.getKey());
reportHandled(SyncopeConstants.REALM_ANYTYPE, realm.getName());
} catch (Exception e) {
LOG.warn("Failure pushing '{}' on '{}'", realm, pushTask.getResource(), e);
@@ -250,30 +197,27 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
}
// ...then provisions for any types
- ahandler = buildAnyObjectHandler();
- uhandler = buildUserHandler();
- ghandler = buildGroupHandler();
-
for (Provision provision : pushTask.getResource().getProvisions()) {
if (provision.getMapping() != null) {
status.set("Pushing " + provision.getAnyType().getKey());
- AnyDAO<?> anyDAO = getAnyDAO(provision.getAnyType().getKind());
+ AnyDAO<?> anyDAO = anyUtilsFactory.getInstance(provision.getAnyType().getKind()).dao();
SyncopePushResultHandler handler;
switch (provision.getAnyType().getKind()) {
case USER:
- handler = uhandler;
+ handler = buildUserHandler();
break;
case GROUP:
- handler = ghandler;
+ handler = buildGroupHandler();
break;
case ANY_OBJECT:
default:
- handler = ahandler;
+ handler = buildAnyObjectHandler();
}
+ handler.setProfile(profile);
Optional<? extends PushTaskAnyFilter> anyFilter = pushTask.getFilter(provision.getAnyType());
String filter = anyFilter.isPresent()
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..f4f57b4
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
@@ -0,0 +1,174 @@
+/*
+ * 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.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.syncope.common.lib.collections.IteratorChain;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
+import org.apache.syncope.common.lib.types.ImplementationType;
+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.dao.ImplementationDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.Realm;
+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.PullTask;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile;
+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.ReconFilterBuilder;
+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.spring.ImplementationManager;
+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.stereotype.Component;
+
+@Component
+public class SinglePullJobDelegate extends PullJobDelegate implements SyncopeSinglePullExecutor {
+
+ @Autowired
+ private ImplementationDAO implementationDAO;
+
+ @Override
+ public List<ProvisioningReport> pull(
+ final Provision provision,
+ final Connector connector,
+ final String connObjectKey,
+ final String connObjectValue,
+ final Realm realm,
+ final boolean remediation,
+ final List<String> actionKeys) throws JobExecutionException {
+
+ LOG.debug("Executing pull on {}", provision.getResource());
+
+ List<PullActions> actions = new ArrayList<>();
+ actionKeys.forEach(key -> {
+ Implementation impl = implementationDAO.find(key);
+ if (impl == null || impl.getType() != ImplementationType.PULL_ACTIONS) {
+ LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...", key);
+ } else {
+ try {
+ actions.add(ImplementationManager.build(impl));
+ } catch (Exception e) {
+ LOG.warn("While building {}", impl, e);
+ }
+ }
+ });
+
+ try {
+ Set<MappingItem> linkinMappingItems = virSchemaDAO.findByProvision(provision).stream().
+ map(virSchema -> virSchema.asLinkingMappingItem()).collect(Collectors.toSet());
+ Iterator<MappingItem> mapItems = new IteratorChain<>(
+ provision.getMapping().getItems().iterator(),
+ linkinMappingItems.iterator());
+ OperationOptions options = MappingUtils.buildOperationOptions(mapItems);
+
+ PullTask pullTask = entityFactory.newEntity(PullTask.class);
+ pullTask.setResource(provision.getResource());
+ pullTask.setMatchingRule(MatchingRule.UPDATE);
+ pullTask.setUnmatchingRule(UnmatchingRule.PROVISION);
+ pullTask.setPullMode(PullMode.FILTERED_RECONCILIATION);
+ pullTask.setPerformCreate(true);
+ pullTask.setPerformUpdate(true);
+ pullTask.setRemediation(remediation);
+ pullTask.setDestinationRealm(realm);
+
+ profile = new ProvisioningProfile<>(connector, pullTask);
+ profile.setDryRun(false);
+ profile.setResAct(ConflictResolutionAction.FIRSTMATCH);
+ profile.getActions().addAll(actions);
+
+ for (PullActions action : actions) {
+ action.beforeAll(profile);
+ }
+
+ SyncopePullResultHandler handler;
+ GroupPullResultHandler ghandler = buildGroupHandler();
+ switch (provision.getAnyType().getKind()) {
+ case USER:
+ handler = buildUserHandler();
+ break;
+
+ case GROUP:
+ handler = ghandler;
+ break;
+
+ case ANY_OBJECT:
+ default:
+ handler = buildAnyObjectHandler();
+ }
+ handler.setProfile(profile);
+ handler.setPullExecutor(this);
+
+ // execute filtered pull
+ connector.filteredReconciliation(
+ provision.getObjectClass(),
+ new AccountReconciliationFilterBuilder(connObjectKey, connObjectValue),
+ handler,
+ options);
+
+ try {
+ setGroupOwners(ghandler);
+ } catch (Exception e) {
+ LOG.error("While setting group owners", e);
+ }
+
+ for (PullActions action : actions) {
+ action.afterAll(profile);
+ }
+
+ return profile.getResults();
+ } catch (Exception e) {
+ throw e instanceof JobExecutionException
+ ? (JobExecutionException) e
+ : new JobExecutionException("While pulling from connector", e);
+ }
+ }
+
+ class AccountReconciliationFilterBuilder implements ReconFilterBuilder {
+
+ private final String key;
+
+ private final String value;
+
+ AccountReconciliationFilterBuilder(final String key, final String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public Filter build() {
+ return FilterBuilder.equalTo(AttributeBuilder.build(key, value));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..76bdc16
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
@@ -0,0 +1,117 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.task.PushTask;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile;
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
+import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
+import org.apache.syncope.core.provisioning.api.pushpull.SyncopePushResultHandler;
+import org.apache.syncope.core.provisioning.api.pushpull.SyncopeSinglePushExecutor;
+import org.apache.syncope.core.spring.ImplementationManager;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SinglePushJobDelegate extends PushJobDelegate implements SyncopeSinglePushExecutor {
+
+ @Autowired
+ private ImplementationDAO implementationDAO;
+
+ @Override
+ public List<ProvisioningReport> push(
+ final Provision provision,
+ final Connector connector,
+ final Any<?> any,
+ final List<String> actionKeys) throws JobExecutionException {
+
+ LOG.debug("Executing push on {}", provision.getResource());
+
+ List<PushActions> actions = new ArrayList<>();
+ actionKeys.forEach(key -> {
+ Implementation impl = implementationDAO.find(key);
+ if (impl == null || impl.getType() != ImplementationType.PUSH_ACTIONS) {
+ LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...", key);
+ } else {
+ try {
+ actions.add(ImplementationManager.build(impl));
+ } catch (Exception e) {
+ LOG.warn("While building {}", impl, e);
+ }
+ }
+ });
+
+ 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);
+
+ profile = new ProvisioningProfile<>(connector, pushTask);
+ profile.getActions().addAll(actions);
+ profile.setResAct(null);
+
+ for (PushActions action : actions) {
+ action.beforeAll(profile);
+ }
+
+ SyncopePushResultHandler handler;
+ switch (provision.getAnyType().getKind()) {
+ case USER:
+ handler = buildUserHandler();
+ break;
+
+ case GROUP:
+ handler = buildGroupHandler();
+ break;
+
+ case ANY_OBJECT:
+ default:
+ handler = buildAnyObjectHandler();
+ }
+ handler.setProfile(profile);
+
+ doHandle(Arrays.asList(any), handler, pushTask.getResource());
+
+ for (PushActions action : actions) {
+ action.afterAll(profile);
+ }
+
+ return profile.getResults();
+ } catch (Exception e) {
+ throw e instanceof JobExecutionException
+ ? (JobExecutionException) e
+ : new JobExecutionException("While pushing to connector", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
index ad9cbed..63e44cb 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
@@ -242,8 +242,8 @@ public class ConnObjectUtils {
updated.setKey(key);
T anyPatch = null;
- if (null != anyUtils.getAnyTypeKind()) {
- switch (anyUtils.getAnyTypeKind()) {
+ if (null != anyUtils.anyTypeKind()) {
+ switch (anyUtils.anyTypeKind()) {
case USER:
UserTO originalUser = (UserTO) original;
UserTO updatedUser = (UserTO) updated;
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index 92d2aad..9d028e4 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -64,18 +64,6 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
protected abstract P newPatch(String key);
- protected String getActualKey(final String key) {
- String actualKey = key;
- if (!SyncopeConstants.UUID_PATTERN.matcher(key).matches()) {
- actualKey = getAnyDAO().findKey(key);
- if (actualKey == null) {
- throw new NotFoundException("User, Group or Any Object for " + key);
- }
- }
-
- return actualKey;
- }
-
@Override
public Set<AttrTO> read(final String key, final SchemaType schemaType) {
TO any = read(key);
@@ -124,7 +112,7 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
@Override
public TO read(final String key) {
- return getAnyLogic().read(getActualKey(key));
+ return getAnyLogic().read(getActualKey(getAnyDAO(), key));
}
@Override
@@ -161,7 +149,7 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
}
protected Response doUpdate(final P anyPatch) {
- anyPatch.setKey(getActualKey(anyPatch.getKey()));
+ anyPatch.setKey(getActualKey(getAnyDAO(), anyPatch.getKey()));
Date etagDate = findLastChange(anyPatch.getKey());
checkETag(String.valueOf(etagDate.getTime()));
@@ -196,21 +184,23 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
@Override
public Response update(final String key, final SchemaType schemaType, final AttrTO attrTO) {
- String actualKey = getActualKey(key);
+ String actualKey = getActualKey(getAnyDAO(), key);
addUpdateOrReplaceAttr(actualKey, schemaType, attrTO, PatchOperation.ADD_REPLACE);
return modificationResponse(read(actualKey, schemaType, attrTO.getSchema()));
}
@Override
public void delete(final String key, final SchemaType schemaType, final String schema) {
- String actualKey = getActualKey(key);
addUpdateOrReplaceAttr(
- actualKey, schemaType, new AttrTO.Builder().schema(schema).build(), PatchOperation.DELETE);
+ getActualKey(getAnyDAO(), key),
+ schemaType,
+ new AttrTO.Builder().schema(schema).build(),
+ PatchOperation.DELETE);
}
@Override
public Response delete(final String key) {
- String actualKey = getActualKey(key);
+ String actualKey = getActualKey(getAnyDAO(), key);
Date etagDate = findLastChange(actualKey);
checkETag(String.valueOf(etagDate.getTime()));
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
index a040960..caef5d8 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
@@ -37,12 +37,15 @@ import org.apache.cxf.jaxrs.ext.search.SearchCondition;
import org.apache.cxf.jaxrs.ext.search.SearchContext;
import org.apache.syncope.common.lib.AbstractBaseBean;
import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.rest.api.service.JAXRSService;
import org.apache.syncope.common.rest.api.Preference;
import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
@@ -64,6 +67,18 @@ abstract class AbstractServiceImpl implements JAXRSService {
@Context
protected SearchContext searchContext;
+ protected String getActualKey(final AnyDAO<?> dao, final String pretendingKey) {
+ String actualKey = pretendingKey;
+ if (!SyncopeConstants.UUID_PATTERN.matcher(pretendingKey).matches()) {
+ actualKey = dao.findKey(pretendingKey);
+ if (actualKey == null) {
+ throw new NotFoundException("User, Group or Any Object for " + pretendingKey);
+ }
+ }
+
+ return actualKey;
+ }
+
protected boolean isNullPriorityAsync() {
return BooleanUtils.toBoolean(messageContext.getHttpHeaders().getHeaderString(RESTHeaders.NULL_PRIORITY_ASYNC));
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
index 961a328..3a7d40b 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
@@ -71,7 +71,7 @@ public class AnyObjectServiceImpl extends AbstractAnyService<AnyObjectTO, AnyObj
@Override
public Response update(final AnyObjectTO anyObjectTO) {
- anyObjectTO.setKey(getActualKey(anyObjectTO.getKey()));
+ anyObjectTO.setKey(getActualKey(getAnyDAO(), anyObjectTO.getKey()));
AnyObjectTO before = logic.read(anyObjectTO.getKey());
checkETag(before.getETagValue());
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
index 4e23d22..bc621e9 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
@@ -68,7 +68,7 @@ public class GroupServiceImpl extends AbstractAnyService<GroupTO, GroupPatch> im
@Override
public Response update(final GroupTO groupTO) {
- groupTO.setKey(getActualKey(groupTO.getKey()));
+ groupTO.setKey(getActualKey(getAnyDAO(), groupTO.getKey()));
GroupTO before = logic.read(groupTO.getKey());
checkETag(before.getETagValue());
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/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
new file mode 100644
index 0000000..80d89d5
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
@@ -0,0 +1,53 @@
+/*
+ * 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.rest.cxf.service;
+
+import org.apache.syncope.common.lib.to.ReconciliationRequest;
+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;
+import org.apache.syncope.core.logic.ReconciliationLogic;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReconciliationServiceImpl extends AbstractServiceImpl implements ReconciliationService {
+
+ @Autowired
+ private ReconciliationLogic logic;
+
+ @Autowired
+ private AnyUtilsFactory anyUtilsFactory;
+
+ @Override
+ public ReconciliationStatus status(final AnyTypeKind anyTypeKind, final String anyKey, final String resourceKey) {
+ return logic.status(
+ anyTypeKind,
+ getActualKey(anyUtilsFactory.getInstance(anyTypeKind).dao(), anyKey),
+ resourceKey);
+ }
+
+ @Override
+ public void reconcile(final ReconciliationRequest request) {
+ request.setAnyKey(
+ getActualKey(anyUtilsFactory.getInstance(request.getAnyTypeKind()).dao(), request.getAnyKey()));
+ logic.reconcile(request);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 4af144b..99dc24d 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -67,7 +67,7 @@ public class UserServiceImpl extends AbstractAnyService<UserTO, UserPatch> imple
@Override
public Response update(final UserTO userTO) {
- userTO.setKey(getActualKey(userTO.getKey()));
+ userTO.setKey(getActualKey(getAnyDAO(), userTO.getKey()));
UserTO before = logic.read(userTO.getKey());
checkETag(before.getETagValue());
http://git-wip-us.apache.org/repos/asf/syncope/blob/e5860a76/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 3151971..759f5e4 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -85,6 +85,7 @@ import org.apache.syncope.common.rest.api.service.GroupService;
import org.apache.syncope.common.rest.api.service.ImplementationService;
import org.apache.syncope.common.rest.api.service.MailTemplateService;
import org.apache.syncope.common.rest.api.service.RealmService;
+import org.apache.syncope.common.rest.api.service.ReconciliationService;
import org.apache.syncope.common.rest.api.service.RelationshipTypeService;
import org.apache.syncope.common.rest.api.service.RemediationService;
import org.apache.syncope.common.rest.api.service.ReportTemplateService;
@@ -228,6 +229,8 @@ public abstract class AbstractITCase {
protected static TaskService taskService;
+ protected static ReconciliationService reconciliationService;
+
protected static WorkflowService workflowService;
protected static MailTemplateService mailTemplateService;
@@ -307,6 +310,7 @@ public abstract class AbstractITCase {
reportTemplateService = adminClient.getService(ReportTemplateService.class);
reportService = adminClient.getService(ReportService.class);
taskService = adminClient.getService(TaskService.class);
+ reconciliationService = adminClient.getService(ReconciliationService.class);
policyService = adminClient.getService(PolicyService.class);
workflowService = adminClient.getService(WorkflowService.class);
mailTemplateService = adminClient.getService(MailTemplateService.class);