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 2015/06/11 16:17:46 UTC
[56/70] syncope git commit: [SYNCOPE-666] Any* tests added
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/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 98a23a6..2d6c6e4 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
@@ -19,98 +19,23 @@
package org.apache.syncope.core.rest.cxf.service;
import java.util.List;
-import javax.ws.rs.core.Response;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.mod.GroupMod;
-import org.apache.syncope.common.lib.to.BulkAction;
-import org.apache.syncope.common.lib.to.BulkActionResult;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
-import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
-import org.apache.syncope.common.lib.wrap.ResourceKey;
-import org.apache.syncope.common.rest.api.CollectionWrapper;
-import org.apache.syncope.common.rest.api.beans.AnyListQuery;
-import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.core.logic.AbstractAnyLogic;
import org.apache.syncope.core.logic.GroupLogic;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
-public class GroupServiceImpl extends AbstractServiceImpl implements GroupService {
+public class GroupServiceImpl extends AbstractAnyService<GroupTO, GroupMod> implements GroupService {
@Autowired
private GroupLogic logic;
@Override
- public Response create(final GroupTO groupTO) {
- GroupTO created = logic.create(groupTO);
- return createResponse(created.getKey(), created);
- }
-
- @Override
- public Response delete(final Long groupKey) {
- GroupTO group = logic.read(groupKey);
-
- checkETag(group.getETagValue());
-
- GroupTO deleted = logic.delete(groupKey);
- return modificationResponse(deleted);
- }
-
- @Override
- public PagedResult<GroupTO> list(final AnyListQuery listQuery) {
- CollectionUtils.transform(listQuery.getRealms(), new Transformer<String, String>() {
-
- @Override
- public String transform(final String input) {
- return StringUtils.prependIfMissing(input, SyncopeConstants.ROOT_REALM);
- }
- });
-
- return buildPagedResult(
- logic.list(
- listQuery.getPage(),
- listQuery.getSize(),
- getOrderByClauses(listQuery.getOrderBy()),
- listQuery.getRealms()),
- listQuery.getPage(),
- listQuery.getSize(),
- logic.count(listQuery.getRealms()));
- }
-
- @Override
- public GroupTO read(final Long groupKey) {
- return logic.read(groupKey);
- }
-
- @Override
- public PagedResult<GroupTO> search(final AnySearchQuery searchQuery) {
- CollectionUtils.transform(searchQuery.getRealms(), new Transformer<String, String>() {
-
- @Override
- public String transform(final String input) {
- return StringUtils.prependIfMissing(input, SyncopeConstants.ROOT_REALM);
- }
- });
-
- SearchCond cond = getSearchCond(searchQuery.getFiql());
- return buildPagedResult(
- logic.search(
- cond,
- searchQuery.getPage(),
- searchQuery.getSize(),
- getOrderByClauses(searchQuery.getOrderBy()),
- searchQuery.getRealms()),
- searchQuery.getPage(),
- searchQuery.getSize(),
- logic.searchCount(cond, searchQuery.getRealms()));
+ protected AbstractAnyLogic<GroupTO, GroupMod> getAnyLogic() {
+ return logic;
}
@Override
@@ -118,126 +43,4 @@ public class GroupServiceImpl extends AbstractServiceImpl implements GroupServic
return logic.own();
}
- @Override
- public Response update(final Long groupKey, final GroupMod groupMod) {
- GroupTO group = logic.read(groupKey);
-
- checkETag(group.getETagValue());
-
- groupMod.setKey(groupKey);
- GroupTO updated = logic.update(groupMod);
- return modificationResponse(updated);
- }
-
- @Override
- public Response bulkDeassociation(
- final Long groupKey, final ResourceDeassociationActionType type, final List<ResourceKey> resourceNames) {
-
- GroupTO group = logic.read(groupKey);
-
- checkETag(group.getETagValue());
-
- GroupTO updated;
- switch (type) {
- case UNLINK:
- updated = logic.unlink(groupKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- case UNASSIGN:
- updated = logic.unassign(groupKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- case DEPROVISION:
- updated = logic.deprovision(groupKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- default:
- updated = logic.read(groupKey);
- }
-
- BulkActionResult result = new BulkActionResult();
-
- if (type == ResourceDeassociationActionType.UNLINK) {
- for (ResourceKey resourceName : resourceNames) {
- result.getResults().put(resourceName.getElement(),
- updated.getResources().contains(resourceName.getElement())
- ? BulkActionResult.Status.FAILURE
- : BulkActionResult.Status.SUCCESS);
- }
- } else {
- for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
- result.getResults().put(propagationStatusTO.getResource(),
- BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
- }
- }
-
- return modificationResponse(result);
- }
-
- @Override
- public Response bulkAssociation(
- final Long groupKey, final ResourceAssociationActionType type, final List<ResourceKey> resourceNames) {
-
- GroupTO group = logic.read(groupKey);
-
- checkETag(group.getETagValue());
-
- GroupTO updated;
- switch (type) {
- case LINK:
- updated = logic.link(groupKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- case ASSIGN:
- updated = logic.assign(groupKey, CollectionWrapper.unwrap(resourceNames), false, null);
- break;
-
- case PROVISION:
- updated = logic.provision(groupKey, CollectionWrapper.unwrap(resourceNames), false, null);
- break;
-
- default:
- updated = logic.read(groupKey);
- }
-
- BulkActionResult result = new BulkActionResult();
-
- if (type == ResourceAssociationActionType.LINK) {
- for (ResourceKey resourceName : resourceNames) {
- result.getResults().put(resourceName.getElement(),
- updated.getResources().contains(resourceName.getElement())
- ? BulkActionResult.Status.FAILURE
- : BulkActionResult.Status.SUCCESS);
- }
- } else {
- for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
- result.getResults().put(propagationStatusTO.getResource(),
- BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
- }
- }
-
- return modificationResponse(result);
- }
-
- @Override
- public BulkActionResult bulk(final BulkAction bulkAction) {
- BulkActionResult result = new BulkActionResult();
-
- if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
- for (String groupKey : bulkAction.getTargets()) {
- try {
- result.getResults().put(
- String.valueOf(logic.delete(Long.valueOf(groupKey)).getKey()),
- BulkActionResult.Status.SUCCESS);
- } catch (Exception e) {
- LOG.error("Error performing delete for group {}", groupKey, e);
- result.getResults().put(groupKey, BulkActionResult.Status.FAILURE);
- }
- }
- } else {
- LOG.warn("Unsupported bulk action: {}", bulkAction.getOperation());
- }
-
- return result;
- }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/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 192b4e0..391aea8 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
@@ -18,44 +18,33 @@
*/
package org.apache.syncope.core.rest.cxf.service;
-import java.util.List;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
import org.apache.syncope.common.lib.mod.StatusMod;
import org.apache.syncope.common.lib.mod.UserMod;
-import org.apache.syncope.common.lib.to.BulkAction;
-import org.apache.syncope.common.lib.to.BulkActionResult;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
-import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
-import org.apache.syncope.common.lib.wrap.ResourceKey;
-import org.apache.syncope.common.rest.api.CollectionWrapper;
import org.apache.syncope.common.rest.api.RESTHeaders;
-import org.apache.syncope.common.rest.api.beans.AnyListQuery;
-import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
import org.apache.syncope.common.rest.api.service.UserService;
+import org.apache.syncope.core.logic.AbstractAnyLogic;
import org.apache.syncope.core.logic.UserLogic;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
-public class UserServiceImpl extends AbstractServiceImpl implements UserService {
+public class UserServiceImpl extends AbstractAnyService<UserTO, UserMod> implements UserService {
@Autowired
private UserLogic logic;
@Override
- public Response getUsername(final Long userKey) {
+ protected AbstractAnyLogic<UserTO, UserMod> getAnyLogic() {
+ return logic;
+ }
+
+ @Override
+ public Response getUsername(final Long key) {
return Response.ok().header(HttpHeaders.ALLOW, OPTIONS_ALLOW).
- header(RESTHeaders.USERNAME, logic.getUsername(userKey)).
+ header(RESTHeaders.USERNAME, logic.getUsername(key)).
build();
}
@@ -73,237 +62,13 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
}
@Override
- public Response delete(final Long userKey) {
- UserTO user = logic.read(userKey);
-
- checkETag(user.getETagValue());
-
- UserTO deleted = logic.delete(userKey);
- return modificationResponse(deleted);
- }
-
- @Override
- public PagedResult<UserTO> list(final AnyListQuery listQuery) {
- CollectionUtils.transform(listQuery.getRealms(), new Transformer<String, String>() {
-
- @Override
- public String transform(final String input) {
- return StringUtils.prependIfMissing(input, SyncopeConstants.ROOT_REALM);
- }
- });
-
- return buildPagedResult(
- logic.list(
- listQuery.getPage(),
- listQuery.getSize(),
- getOrderByClauses(listQuery.getOrderBy()),
- listQuery.getRealms()),
- listQuery.getPage(),
- listQuery.getSize(),
- logic.count(listQuery.getRealms()));
- }
-
- @Override
- public UserTO read(final Long userKey) {
- return logic.read(userKey);
- }
-
- @Override
- public PagedResult<UserTO> search(final AnySearchQuery searchQuery) {
- CollectionUtils.transform(searchQuery.getRealms(), new Transformer<String, String>() {
-
- @Override
- public String transform(final String input) {
- return StringUtils.prependIfMissing(input, SyncopeConstants.ROOT_REALM);
- }
- });
-
- SearchCond cond = getSearchCond(searchQuery.getFiql());
- return buildPagedResult(
- logic.search(
- cond,
- searchQuery.getPage(),
- searchQuery.getSize(),
- getOrderByClauses(searchQuery.getOrderBy()),
- searchQuery.getRealms()),
- searchQuery.getPage(),
- searchQuery.getSize(),
- logic.searchCount(cond, searchQuery.getRealms()));
- }
-
- @Override
- public Response update(final Long userKey, final UserMod userMod) {
- UserTO user = logic.read(userKey);
-
- checkETag(user.getETagValue());
-
- userMod.setKey(userKey);
- UserTO updated = logic.update(userMod);
- return modificationResponse(updated);
- }
-
- @Override
- public Response status(final Long userKey, final StatusMod statusMod) {
- UserTO user = logic.read(userKey);
+ public Response status(final Long key, final StatusMod statusMod) {
+ UserTO user = logic.read(key);
checkETag(user.getETagValue());
- statusMod.setKey(userKey);
+ statusMod.setKey(key);
UserTO updated = logic.status(statusMod);
return modificationResponse(updated);
}
-
- @Override
- public Response bulkDeassociation(
- final Long userKey, final ResourceDeassociationActionType type, final List<ResourceKey> resourceNames) {
-
- final UserTO user = logic.read(userKey);
-
- checkETag(user.getETagValue());
-
- UserTO updated;
- switch (type) {
- case UNLINK:
- updated = logic.unlink(userKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- case UNASSIGN:
- updated = logic.unassign(userKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- case DEPROVISION:
- updated = logic.deprovision(userKey, CollectionWrapper.unwrap(resourceNames));
- break;
-
- default:
- updated = logic.read(userKey);
- }
-
- BulkActionResult result = new BulkActionResult();
-
- if (type == ResourceDeassociationActionType.UNLINK) {
- for (ResourceKey resourceName : resourceNames) {
- result.getResults().put(
- resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
- ? BulkActionResult.Status.FAILURE
- : BulkActionResult.Status.SUCCESS);
- }
- } else {
- for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
- result.getResults().put(propagationStatusTO.getResource(),
- BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
- }
- }
-
- return modificationResponse(result);
- }
-
- @Override
- public Response bulkAssociation(
- final Long userKey, final ResourceAssociationActionType type, final ResourceAssociationMod associationMod) {
-
- final UserTO user = logic.read(userKey);
-
- checkETag(user.getETagValue());
-
- UserTO updated;
- switch (type) {
- case LINK:
- updated = logic.link(
- userKey,
- CollectionWrapper.unwrap(associationMod.getTargetResources()));
- break;
-
- case ASSIGN:
- updated = logic.assign(
- userKey,
- CollectionWrapper.unwrap(associationMod.getTargetResources()),
- associationMod.isChangePwd(),
- associationMod.getPassword());
- break;
-
- case PROVISION:
- updated = logic.provision(
- userKey,
- CollectionWrapper.unwrap(associationMod.getTargetResources()),
- associationMod.isChangePwd(),
- associationMod.getPassword());
- break;
-
- default:
- updated = logic.read(userKey);
- }
-
- BulkActionResult result = new BulkActionResult();
-
- if (type == ResourceAssociationActionType.LINK) {
- for (ResourceKey resourceName : associationMod.getTargetResources()) {
- result.getResults().put(resourceName.getElement(),
- updated.getResources().contains(resourceName.getElement())
- ? BulkActionResult.Status.FAILURE
- : BulkActionResult.Status.SUCCESS);
- }
- } else {
- for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
- result.getResults().put(propagationStatusTO.getResource(),
- BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
- }
- }
-
- return modificationResponse(result);
- }
-
- @Override
- public BulkActionResult bulk(final BulkAction bulkAction) {
- BulkActionResult result = new BulkActionResult();
-
- switch (bulkAction.getOperation()) {
- case DELETE:
- for (String key : bulkAction.getTargets()) {
- try {
- result.getResults().put(
- String.valueOf(logic.delete(Long.valueOf(key)).getKey()),
- BulkActionResult.Status.SUCCESS);
- } catch (Exception e) {
- LOG.error("Error performing delete for user {}", key, e);
- result.getResults().put(key, BulkActionResult.Status.FAILURE);
- }
- }
- break;
-
- case SUSPEND:
- for (String key : bulkAction.getTargets()) {
- StatusMod statusMod = new StatusMod();
- statusMod.setKey(Long.valueOf(key));
- statusMod.setType(StatusMod.ModType.SUSPEND);
- try {
- result.getResults().put(
- String.valueOf(logic.status(statusMod).getKey()), BulkActionResult.Status.SUCCESS);
- } catch (Exception e) {
- LOG.error("Error performing suspend for user {}", key, e);
- result.getResults().put(key, BulkActionResult.Status.FAILURE);
- }
- }
- break;
-
- case REACTIVATE:
- for (String key : bulkAction.getTargets()) {
- StatusMod statusMod = new StatusMod();
- statusMod.setKey(Long.valueOf(key));
- statusMod.setType(StatusMod.ModType.REACTIVATE);
- try {
- result.getResults().put(
- String.valueOf(logic.status(statusMod).getKey()), BulkActionResult.Status.SUCCESS);
- } catch (Exception e) {
- LOG.error("Error performing reactivate for user {}", key, e);
- result.getResults().put(key, BulkActionResult.Status.FAILURE);
- }
- }
- break;
-
- default:
- }
-
- return result;
- }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
----------------------------------------------------------------------
diff --git a/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java b/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
index 3520a4a..4359e7b 100644
--- a/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
+++ b/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
@@ -56,6 +56,9 @@ public class CamelRouteLoader implements SyncopeLoader {
@javax.annotation.Resource(name = "groupRoutes")
private ResourceWithFallbackLoader groupRoutesLoader;
+ @javax.annotation.Resource(name = "anyObjectRoutes")
+ private ResourceWithFallbackLoader anyObjectRoutesLoader;
+
@Autowired
private DataSource dataSource;
@@ -76,6 +79,7 @@ public class CamelRouteLoader implements SyncopeLoader {
if (!loaded) {
loadRoutes(userRoutesLoader.getResource(), AnyTypeKind.USER);
loadRoutes(groupRoutesLoader.getResource(), AnyTypeKind.GROUP);
+ loadRoutes(anyObjectRoutesLoader.getResource(), AnyTypeKind.ANY_OBJECT);
loaded = true;
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
new file mode 100644
index 0000000..ae29501
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
@@ -0,0 +1,163 @@
+/*
+ * 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.camel;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.camel.Exchange;
+import org.apache.camel.PollingConsumer;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
+
+public class CamelAnyObjectProvisioningManager
+ extends AbstractCamelProvisioningManager implements AnyObjectProvisioningManager {
+
+ @Override
+ public Pair<Long, List<PropagationStatus>> create(final AnyObjectTO any) {
+ return create(any, Collections.<String>emptySet());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Pair<Long, List<PropagationStatus>> create(
+ final AnyObjectTO anyObjectTO, final Set<String> excludedResources) {
+
+ PollingConsumer pollingConsumer = getConsumer("direct:createAnyObjectPort");
+
+ Map<String, Object> props = new HashMap<>();
+ props.put("excludedResources", excludedResources);
+
+ sendMessage("direct:createAnyObject", anyObjectTO, props);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(Pair.class);
+ }
+
+ @Override
+ public Pair<Long, List<PropagationStatus>> update(final AnyObjectMod anyMod) {
+ return update(anyMod, Collections.<String>emptySet());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Pair<Long, List<PropagationStatus>> update(
+ final AnyObjectMod anyMod, final Set<String> excludedResources) {
+
+ PollingConsumer pollingConsumer = getConsumer("direct:updateAnyObjectPort");
+
+ Map<String, Object> props = new HashMap<>();
+ props.put("excludedResources", excludedResources);
+
+ sendMessage("direct:updateAnyObject", anyMod, props);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(Pair.class);
+ }
+
+ @Override
+ public List<PropagationStatus> delete(final Long anyObjectObjectKey) {
+ return delete(anyObjectObjectKey, Collections.<String>emptySet());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<PropagationStatus> delete(final Long anyObjectKey, final Set<String> excludedResources) {
+ PollingConsumer pollingConsumer = getConsumer("direct:deleteAnyObjectPort");
+
+ Map<String, Object> props = new HashMap<>();
+ props.put("excludedResources", excludedResources);
+
+ sendMessage("direct:deleteAnyObject", anyObjectKey, props);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(List.class);
+ }
+
+ @Override
+ public Long unlink(final AnyObjectMod anyObjectMod) {
+ PollingConsumer pollingConsumer = getConsumer("direct:unlinkAnyObjectPort");
+
+ sendMessage("direct:unlinkAnyObject", anyObjectMod);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(Long.class);
+ }
+
+ @Override
+ public Long link(final AnyObjectMod anyObjectMod) {
+ PollingConsumer pollingConsumer = getConsumer("direct:linkAnyObjectPort");
+
+ sendMessage("direct:linkAnyObject", anyObjectMod);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(Long.class);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<PropagationStatus> deprovision(final Long anyObjectKey, final Collection<String> resources) {
+ PollingConsumer pollingConsumer = getConsumer("direct:deprovisionAnyObjectPort");
+
+ Map<String, Object> props = new HashMap<>();
+ props.put("resources", resources);
+
+ sendMessage("direct:deprovisionAnyObject", anyObjectKey, props);
+
+ Exchange exchange = pollingConsumer.receive();
+
+ if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) != null) {
+ throw (RuntimeException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
+ }
+
+ return exchange.getIn().getBody(List.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectCreateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectCreateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectCreateProcessor.java
new file mode 100644
index 0000000..2f2e41e
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectCreateProcessor.java
@@ -0,0 +1,71 @@
+/*
+ * 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.camel.processor;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyObjectCreateProcessor implements Processor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnyObjectCreateProcessor.class);
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void process(final Exchange exchange) {
+ WorkflowResult<Long> created = (WorkflowResult) exchange.getIn().getBody();
+ AnyObjectTO any = exchange.getProperty("any", AnyObjectTO.class);
+ Set<String> excludedResource = exchange.getProperty("excludedResources", Set.class);
+
+ List<PropagationTask> tasks =
+ propagationManager.getAnyObjectCreateTasks(created, any.getVirAttrs(), excludedResource);
+ PropagationReporter propagationReporter =
+ ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
+ try {
+ taskExecutor.execute(tasks, propagationReporter);
+ } catch (PropagationException e) {
+ LOG.error("Error propagation primary resource", e);
+ propagationReporter.onPrimaryResourceFailure(tasks);
+ }
+
+ exchange.getOut().setBody(new ImmutablePair<>(created.getResult(), propagationReporter.getStatuses()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeleteProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeleteProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeleteProcessor.java
new file mode 100644
index 0000000..d1c9243
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeleteProcessor.java
@@ -0,0 +1,83 @@
+/*
+ * 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.camel.processor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
+import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyObjectDeleteProcessor implements Processor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnyObjectDeleteProcessor.class);
+
+ @Autowired
+ protected AnyObjectWorkflowAdapter gwfAdapter;
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @Autowired
+ protected AnyObjectDAO anyObjectDAO;
+
+ @Override
+ public void process(final Exchange exchange) throws Exception {
+ Long anyKey = exchange.getIn().getBody(Long.class);
+ AnyObject anyObject = anyObjectDAO.find(anyKey);
+ @SuppressWarnings("unchecked")
+ Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
+
+ List<PropagationTask> tasks = new ArrayList<>();
+
+ if (anyObject != null) {
+ // Generate propagation tasks for deleting this anyObject from resources
+ tasks.addAll(propagationManager.getAnyObjectDeleteTasks(anyObject.getKey(), excludedResources));
+ }
+
+ PropagationReporter propagationReporter =
+ ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
+ try {
+ taskExecutor.execute(tasks, propagationReporter);
+ } catch (PropagationException e) {
+ LOG.error("Error propagation primary resource", e);
+ propagationReporter.onPrimaryResourceFailure(tasks);
+ }
+
+ exchange.setProperty("statuses", propagationReporter.getStatuses());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeprovisionProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeprovisionProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeprovisionProcessor.java
new file mode 100644
index 0000000..c56ab90
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectDeprovisionProcessor.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.core.provisioning.camel.processor;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyObjectDeprovisionProcessor implements Processor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserDeprovisionProcessor.class);
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @Autowired
+ protected AnyObjectDAO anyObjectDAO;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void process(final Exchange exchange) {
+ Long anyObjectKey = exchange.getIn().getBody(Long.class);
+ List<String> resources = exchange.getProperty("resources", List.class);
+
+ AnyObject anyObject = anyObjectDAO.authFind(anyObjectKey);
+
+ Collection<String> noPropResourceNames = CollectionUtils.removeAll(anyObject.getResourceNames(), resources);
+
+ List<PropagationTask> tasks =
+ propagationManager.getAnyObjectDeleteTasks(anyObjectKey, new HashSet<>(resources), noPropResourceNames);
+ PropagationReporter propagationReporter =
+ ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
+ try {
+ taskExecutor.execute(tasks, propagationReporter);
+ } catch (PropagationException e) {
+ LOG.error("Error propagation primary resource", e);
+ propagationReporter.onPrimaryResourceFailure(tasks);
+ }
+
+ exchange.getOut().setBody(propagationReporter.getStatuses());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
new file mode 100644
index 0000000..2979e97
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.camel.processor;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyObjectUpdateProcessor implements Processor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserUpdateProcessor.class);
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @Autowired
+ protected VirAttrHandler virtAttrHandler;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void process(final Exchange exchange) {
+ WorkflowResult<Long> updated = (WorkflowResult) exchange.getIn().getBody();
+ AnyObjectMod anyObjectMod = exchange.getProperty("anyMod", AnyObjectMod.class);
+ Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
+
+ List<PropagationTask> tasks = propagationManager.getAnyObjectUpdateTasks(updated,
+ anyObjectMod.getVirAttrsToRemove(), anyObjectMod.getVirAttrsToUpdate(), excludedResources);
+ if (tasks.isEmpty()) {
+ // SYNCOPE-459: take care of user virtual attributes ...
+ PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+ updated.getResult(),
+ AnyTypeKind.GROUP,
+ anyObjectMod.getVirAttrsToRemove(),
+ anyObjectMod.getVirAttrsToUpdate());
+ tasks.addAll(!propByResVirAttr.isEmpty()
+ ? propagationManager.getAnyObjectUpdateTasks(updated, null, null, null)
+ : Collections.<PropagationTask>emptyList());
+ }
+
+ PropagationReporter propagationReporter =
+ ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
+ try {
+ taskExecutor.execute(tasks, propagationReporter);
+ } catch (PropagationException e) {
+ LOG.error("Error propagation primary resource", e);
+ propagationReporter.onPrimaryResourceFailure(tasks);
+ }
+
+ exchange.getOut().setBody(new ImmutablePair<>(updated.getResult(), propagationReporter.getStatuses()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/resources/anyObjectRoutes.xml
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/resources/anyObjectRoutes.xml b/ext/camel/provisioning-camel/src/main/resources/anyObjectRoutes.xml
new file mode 100644
index 0000000..de4df0b
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/resources/anyObjectRoutes.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<routes>
+
+ <route id="createAnyObject">
+ <from uri="direct:createAnyObject"/>
+ <setProperty propertyName="any">
+ <simple>${body}</simple>
+ </setProperty>
+ <doTry>
+ <bean ref="awfAdapter" method="create(${body})"/>
+ <process ref="anyObjectCreateProcessor"/>
+ <to uri="direct:createAnyObjectPort"/>
+ <doCatch>
+ <exception>java.lang.RuntimeException</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <to uri="direct:createAnyObjectPort"/>
+ </doCatch>
+ </doTry>
+ </route>
+
+ <route id="updateAnyObject">
+ <from uri="direct:updateAnyObject"/>
+ <setProperty propertyName="anyMod">
+ <simple>${body}</simple>
+ </setProperty>
+ <doTry>
+ <bean ref="awfAdapter" method="update(${body})"/>
+ <process ref="anyObjectUpdateProcessor"/>
+ <to uri="direct:updateAnyObjectPort"/>
+ <doCatch>
+ <exception>java.lang.RuntimeException</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <to uri="direct:updateAnyObjectPort"/>
+ </doCatch>
+ </doTry>
+ </route>
+
+ <route id="deleteAnyObject">
+ <from uri="direct:deleteAnyObject"/>
+ <doTry>
+ <process ref="anyObjectDeleteProcessor"/>
+ <bean ref="awfAdapter" method="delete(${body})"/>
+ <setBody>
+ <simple>${property.statuses}</simple>
+ </setBody>
+ <to uri="direct:deleteAnyObjectPort"/>
+ <doCatch>
+ <exception>java.lang.RuntimeException</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <to uri="direct:deleteAnyObjectPort"/>
+ </doCatch>
+ </doTry>
+ </route>
+
+ <route id="unlinkAnyObject">
+ <from uri="direct:unlinkAnyObject"/>
+ <doTry>
+ <bean ref="awfAdapter" method="update(${body})"/>
+ <setBody>
+ <simple>${body.getResult}</simple>
+ </setBody>
+ <to uri="direct:unlinkAnyObjectPort"/>
+ <doCatch>
+ <exception>java.lang.RuntimeException</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <to uri="direct:unlinkAnyObjectPort"/>
+ </doCatch>
+ </doTry>
+ </route>
+
+ <route id="linkAnyObject">
+ <from uri="direct:linkAnyObject"/>
+ <doTry>
+ <bean ref="awfAdapter" method="update(${body})"/>
+ <setBody>
+ <simple>${body.getResult}</simple>
+ </setBody>
+ <to uri="direct:linkAnyObjectPort"/>
+ <doCatch>
+ <exception>java.lang.RuntimeException</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <to uri="direct:linkAnyObjectPort"/>
+ </doCatch>
+ </doTry>
+ </route>
+
+ <route id="deprovisionAnyObject">
+ <from uri="direct:deprovisionAnyObject"/>
+ <process ref="anyObjectDeprovisionProcessor"/>
+ <to uri="direct:deprovisionAnyObjectPort"/>
+ </route>
+
+</routes>
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/resources/provisioning.properties
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/resources/provisioning.properties b/ext/camel/provisioning-camel/src/main/resources/provisioning.properties
index 5061502..aa843ca 100644
--- a/ext/camel/provisioning-camel/src/main/resources/provisioning.properties
+++ b/ext/camel/provisioning-camel/src/main/resources/provisioning.properties
@@ -17,5 +17,5 @@
camel.directory=${conf.directory}
userProvisioningManager=org.apache.syncope.core.provisioning.camel.CamelUserProvisioningManager
groupProvisioningManager=org.apache.syncope.core.provisioning.camel.CamelGroupProvisioningManager
-anyObjectProvisioningManager=org.apache.syncope.core.provisioning.java.DefaultAnyObjectProvisioningManager
+anyObjectProvisioningManager=org.apache.syncope.core.provisioning.camel.CamelAnObjectProvisioningManager
virAttrCache=org.apache.syncope.core.provisioning.java.cache.MemoryVirAttrCache
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/ext/camel/provisioning-camel/src/main/resources/provisioningCamelContext.xml
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/resources/provisioningCamelContext.xml b/ext/camel/provisioning-camel/src/main/resources/provisioningCamelContext.xml
index 8eec14d..d334d75 100644
--- a/ext/camel/provisioning-camel/src/main/resources/provisioningCamelContext.xml
+++ b/ext/camel/provisioning-camel/src/main/resources/provisioningCamelContext.xml
@@ -33,7 +33,11 @@ under the License.
<property name="primary" value="file:${camel.directory}/groupRoutes.xml"/>
<property name="fallback" value="classpath:groupRoutes.xml"/>
</bean>
-
+ <bean id="anyObjectRoutes" class="org.apache.syncope.core.misc.spring.ResourceWithFallbackLoader">
+ <property name="primary" value="file:${camel.directory}/anyObjectRoutes.xml"/>
+ <property name="fallback" value="classpath:anyObjectRoutes.xml"/>
+ </bean>
+
<context:component-scan base-package="org.apache.syncope.core.provisioning.camel"/>
</beans>
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/build-tools/pom.xml
----------------------------------------------------------------------
diff --git a/fit/build-tools/pom.xml b/fit/build-tools/pom.xml
index bfae2f4..679eee6 100644
--- a/fit/build-tools/pom.xml
+++ b/fit/build-tools/pom.xml
@@ -85,10 +85,16 @@ under the License.
<dependency>
<groupId>net.tirasa.connid.bundles.db</groupId>
<artifactId>net.tirasa.connid.bundles.db.table</artifactId>
- <version>${connid.db.table.version}</version>
+ <version>${connid.database.version}</version>
<scope>runtime</scope>
</dependency>
-
+ <dependency>
+ <groupId>net.tirasa.connid.bundles.db</groupId>
+ <artifactId>net.tirasa.connid.bundles.db.scriptedsql</artifactId>
+ <version>${connid.database.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/build-tools/src/main/java/org/apache/syncope/fit/buildtools/ConnIdStartStopListener.java
----------------------------------------------------------------------
diff --git a/fit/build-tools/src/main/java/org/apache/syncope/fit/buildtools/ConnIdStartStopListener.java b/fit/build-tools/src/main/java/org/apache/syncope/fit/buildtools/ConnIdStartStopListener.java
index 37adbd3..67567ec 100644
--- a/fit/build-tools/src/main/java/org/apache/syncope/fit/buildtools/ConnIdStartStopListener.java
+++ b/fit/build-tools/src/main/java/org/apache/syncope/fit/buildtools/ConnIdStartStopListener.java
@@ -49,7 +49,8 @@ public class ConnIdStartStopListener implements ServletContextListener {
for (String bundleFile : new String[] {
"testconnectorserver.soap.bundle",
- "testconnectorserver.db.bundle",
+ "testconnectorserver.dbtable.bundle",
+ "testconnectorserver.scriptedsql.bundle",
"testconnectorserver.csvdir.bundle",
"testconnectorserver.ldap.bundle" }) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/build-tools/src/main/resources/buildToolsContext.xml
----------------------------------------------------------------------
diff --git a/fit/build-tools/src/main/resources/buildToolsContext.xml b/fit/build-tools/src/main/resources/buildToolsContext.xml
index 2b63ed6..e0f5678 100644
--- a/fit/build-tools/src/main/resources/buildToolsContext.xml
+++ b/fit/build-tools/src/main/resources/buildToolsContext.xml
@@ -45,8 +45,11 @@ under the License.
<bean id="testconnectorserver.soap.bundle" class="java.lang.String">
<constructor-arg value="net.tirasa.connid.bundles.soap-${connid.soap.version}.jar"/>
</bean>
- <bean id="testconnectorserver.db.bundle" class="java.lang.String">
- <constructor-arg value="net.tirasa.connid.bundles.db.table-${connid.db.table.version}.jar"/>
+ <bean id="testconnectorserver.dbtable.bundle" class="java.lang.String">
+ <constructor-arg value="net.tirasa.connid.bundles.db.table-${connid.database.version}.jar"/>
+ </bean>
+ <bean id="testconnectorserver.scriptedsql.bundle" class="java.lang.String">
+ <constructor-arg value="net.tirasa.connid.bundles.db.scriptedsql-${connid.database.version}.jar"/>
</bean>
<bean id="testconnectorserver.csvdir.bundle" class="java.lang.String">
<constructor-arg value="net.tirasa.connid.bundles.csvdir-${connid.csvdir.version}.jar"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/build-tools/src/main/resources/testdb.sql
----------------------------------------------------------------------
diff --git a/fit/build-tools/src/main/resources/testdb.sql b/fit/build-tools/src/main/resources/testdb.sql
index ff4dd47..9202a87 100644
--- a/fit/build-tools/src/main/resources/testdb.sql
+++ b/fit/build-tools/src/main/resources/testdb.sql
@@ -37,10 +37,16 @@ INSERT INTO test2 VALUES ('verdi', 'password321', 'true');
-- this table is for issueSYNCOPE230
DROP TABLE testsync IF EXISTS;
-CREATE TABLE TESTSYNC (
+CREATE TABLE testsync (
id NUMBER(10) PRIMARY KEY,
username VARCHAR(80),
surname VARCHAR(80),
email VARCHAR(80));
INSERT INTO testsync VALUES (965, 'issuesyncope230', 'Surname', 'syncope230@syncope.apache.org');
+
+DROP TABLE testPRINTER IF EXISTS;
+CREATE TABLE testPRINTER (
+id NUMBER(10) PRIMARY KEY,
+location VARCHAR(80),
+lastModification TIMESTAMP);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/connid.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/connid.properties b/fit/core-reference/src/main/resources/connid.properties
index a18252f..22ed0a8 100644
--- a/fit/core-reference/src/main/resources/connid.properties
+++ b/fit/core-reference/src/main/resources/connid.properties
@@ -20,5 +20,5 @@ connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}
## for test only
testdb.url=${testdb.url}
connid.soap.version=${connid.soap.version}
-connid.db.table.version=${connid.db.table.version}
+connid.database.version=${connid.database.version}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/CreateScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/CreateScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/CreateScript.groovy
new file mode 100644
index 0000000..52c10f9
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/CreateScript.groovy
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends us the following:
+// connection : SQL connection
+// action: String correponding to the action ("CREATE" here)
+// log: a handler to the Log facility
+// objectClass: a String describing the Object class (__ACCOUNT__ / __GROUP__ / other)
+// id: The entry identifier (OpenICF "Name" atribute. (most often matches the uid)
+// attributes: an Attribute Map, containg the <String> attribute name as a key
+// and the <List> attribute value(s) as value.
+// password: password string, clear text
+// options: a handler to the OperationOptions Map
+
+log.info("Entering " + action + " Script");
+
+def sql = new Sql(connection);
+
+switch ( objectClass ) {
+case "__PRINTER__":
+ sql.execute("INSERT INTO TESTPRINTER (id, location, lastmodification) values (?,?,?)",
+ [
+ id,
+ attributes.get("location").get(0),
+ new Date()
+ ])
+ break
+
+default:
+ id;
+}
+
+return id;
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/DeleteScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/DeleteScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/DeleteScript.groovy
new file mode 100644
index 0000000..cdd7f5b
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/DeleteScript.groovy
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends the following:
+// connection: handler to the SQL connection
+// action: a string describing the action ("DELETE" here)
+// log: a handler to the Log facility
+// objectClass: a String describing the Object class (__ACCOUNT__ / __GROUP__ / other)
+// options: a handler to the OperationOptions Map
+// uid: String for the unique id that specifies the object to delete
+
+log.info("Entering " + action + " Script");
+def sql = new Sql(connection);
+
+assert uid != null
+
+switch ( objectClass ) {
+case "__PRINTER__":
+ sql.execute("DELETE FROM TESTPRINTER where id= ?",[uid])
+ break
+
+default:
+ uid;
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/SchemaScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/SchemaScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/SchemaScript.groovy
new file mode 100644
index 0000000..50f8a8a
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/SchemaScript.groovy
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+import org.identityconnectors.framework.common.objects.AttributeInfo;
+import org.identityconnectors.framework.common.objects.AttributeInfo.Flags;
+import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
+import org.identityconnectors.framework.common.objects.ObjectClassInfo;
+import org.identityconnectors.framework.common.objects.ObjectClassInfoBuilder;
+
+// Parameters:
+// The connector sends the following:
+// action: a string describing the action ("SCHEMA" here)
+// log: a handler to the Log facility
+// builder: SchemaBuilder instance for the connector
+//
+// The connector will make the final call to builder.build()
+// so the scipt just need to declare the different object types.
+
+// This sample shows how to create 3 basic ObjectTypes: __ACCOUNT__, __GROUP__ and organization.
+// Each of them contains one required attribute and normal String attributes
+
+
+log.info("Entering " + action + " Script");
+
+idAIB = new AttributeInfoBuilder("id", String.class);
+idAIB.setRequired(true);
+
+orgAttrsInfo = new HashSet<AttributeInfo>();
+orgAttrsInfo.add(idAIB.build());
+orgAttrsInfo.add(AttributeInfoBuilder.build("location", String.class));
+// Create the organization Object class
+ObjectClassInfo ociOrg = new ObjectClassInfoBuilder().setType("__PRINTER__").addAllAttributeInfo(orgAttrsInfo).build();
+builder.defineObjectClass(ociOrg);
+
+log.info("Schema script done");
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/SearchScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/SearchScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/SearchScript.groovy
new file mode 100644
index 0000000..cc0dd65
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/SearchScript.groovy
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends the following:
+// connection: handler to the SQL connection
+// objectClass: a String describing the Object class (__ACCOUNT__ / __GROUP__ / other)
+// action: a string describing the action ("SEARCH" here)
+// log: a handler to the Log facility
+// options: a handler to the OperationOptions Map
+// query: a handler to the Query Map
+//
+// The Query map describes the filter used.
+//
+// query = [ operation: "CONTAINS", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "ENDSWITH", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "STARTSWITH", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "EQUALS", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "GREATERTHAN", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "GREATERTHANOREQUAL", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "LESSTHAN", left: attribute, right: "value", not: true/false ]
+// query = [ operation: "LESSTHANOREQUAL", left: attribute, right: "value", not: true/false ]
+// query = null : then we assume we fetch everything
+//
+// AND and OR filter just embed a left/right couple of queries.
+// query = [ operation: "AND", left: query1, right: query2 ]
+// query = [ operation: "OR", left: query1, right: query2 ]
+//
+// Returns: A list of Maps. Each map describing one row.
+// !!!! Each Map must contain a '__UID__' and '__NAME__' attribute.
+// This is required to build a ConnectorObject.
+
+log.info("Entering " + action + " Script");
+
+def sql = new Sql(connection);
+def result = []
+def where = "";
+
+if (query != null) {
+ // Need to handle the __UID__ in queries
+ if (query.get("left").equalsIgnoreCase("__UID__") && objectClass.equalsIgnoreCase("__PRINTER__")) {
+ query.put("left","id")
+ }
+
+ // We can use Groovy template engine to generate our custom SQL queries
+ def engine = new groovy.text.SimpleTemplateEngine();
+
+ def whereTemplates = [
+ CONTAINS:' WHERE $left ${not ? "NOT " : ""}LIKE "%$right%"',
+ ENDSWITH:' WHERE $left ${not ? "NOT " : ""}LIKE "%$right"',
+ STARTSWITH:' WHERE $left ${not ? "NOT " : ""}LIKE "$right%"',
+ EQUALS:' WHERE $left ${not ? "<>" : "="} \'$right\'',
+ GREATERTHAN:' WHERE $left ${not ? "<=" : ">"} "$right"',
+ GREATERTHANOREQUAL:' WHERE $left ${not ? "<" : ">="} "$right"',
+ LESSTHAN:' WHERE $left ${not ? ">=" : "<"} "$right"',
+ LESSTHANOREQUAL:' WHERE $left ${not ? ">" : "<="} "$right"'
+ ]
+
+ def wt = whereTemplates.get(query.get("operation"));
+ def binding = [left:query.get("left"),right:query.get("right"),not:query.get("not")];
+ def template = engine.createTemplate(wt).make(binding);
+ where = template.toString();
+ log.ok("Search WHERE clause is: "+ where)
+}
+
+switch ( objectClass ) {
+case "__PRINTER__":
+ sql.eachRow("SELECT * FROM TESTPRINTER " + where,
+ {result.add([__UID__:it.id, __NAME__:it.id, location:it.location])} );
+ break
+
+default:
+ result;
+}
+
+return result;
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/SyncScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/SyncScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/SyncScript.groovy
new file mode 100644
index 0000000..6060870
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/SyncScript.groovy
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends the following:
+// connection: handler to the SQL connection
+// objectClass: a String describing the Object class (__ACCOUNT__ / __GROUP__ / other)
+// action: a string describing the action ("SYNC" or "GET_LATEST_SYNC_TOKEN" here)
+// log: a handler to the Log facility
+// options: a handler to the OperationOptions Map (null if action = "GET_LATEST_SYNC_TOKEN")
+// token: a handler to an Object representing the sync token (null if action = "GET_LATEST_SYNC_TOKEN")
+//
+//
+// Returns:
+// if action = "GET_LATEST_SYNC_TOKEN", it must return an object representing the last known
+// sync token for the corresponding ObjectClass
+//
+// if action = "SYNC":
+// A list of Maps . Each map describing one update:
+// Map should look like the following:
+//
+// [
+// "token": <Object> token object (could be Integer, Date, String) , [!! could be null]
+// "operation":<String> ("CREATE_OR_UPDATE"|"DELETE") will always default to CREATE_OR_DELETE ,
+// "uid":<String> uid (uid of the entry) ,
+// "previousUid":<String> prevuid (This is for rename ops) ,
+// "password":<String> password (optional... allows to pass clear text password if needed),
+// "attributes":Map<String,List> of attributes name/values
+// ]
+
+log.info("Entering " + action + " Script");
+def sql = new Sql(connection);
+
+if (action.equalsIgnoreCase("GET_LATEST_SYNC_TOKEN")) {
+ switch (objectClass) {
+ case "__PRINTER__":
+ row = sql.firstRow("SELECT lastmodification FROM TESTPRINTER ORDER BY lastmodification DESC");
+ log.ok("Get Latest Sync Token script: last token is: " + row["lastmodification"])
+ break;
+
+ default:
+ row = null;
+ }
+
+ return row == null ? null : row["lastmodification"].getTime();
+} else if (action.equalsIgnoreCase("SYNC")) {
+ def result = [];
+ def lastmodification = null;
+ if (token != null) {
+ lastmodification = new Date(token);
+ } else {
+ lastmodification = new Date(0);
+ }
+
+ switch (objectClass) {
+ case "__PRINTER__":
+ sql.eachRow("SELECT * FROM TESTPRINTER WHERE lastmodification > ${lastmodification}",
+ {
+ result.add([
+ operation:"CREATE_OR_UPDATE",
+ uid:it.id.toString(),
+ token:it.lastmodification.getTime(),
+ attributes:[
+ __UID__:it.id.toString(),
+ __NAME__:it.id.toString(),
+ id:it.id.toString(),
+ location:it.location
+ ]
+ ]);
+ }
+ )
+ break;
+ }
+
+ log.ok("Sync script: found " + result.size() + " events to sync");
+ return result;
+} else {
+ log.error("Sync script: action '" + action + "' is not implemented in this script");
+ return null;
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/TestScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/TestScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/TestScript.groovy
new file mode 100644
index 0000000..5b8f4b5
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/TestScript.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends the following:
+// connection: handler to the SQL connection
+// action: a string describing the action ("TEST" here)
+// log: a handler to the Log facility
+
+log.info("Entering " + action + " Script");
+def sql = new Sql(connection);
+
+sql.eachRow("select * from TESTPRINTER", { println it.uid} );
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/main/resources/scriptedsql/UpdateScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/scriptedsql/UpdateScript.groovy b/fit/core-reference/src/main/resources/scriptedsql/UpdateScript.groovy
new file mode 100644
index 0000000..f3155cb
--- /dev/null
+++ b/fit/core-reference/src/main/resources/scriptedsql/UpdateScript.groovy
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+import groovy.sql.Sql;
+import groovy.sql.DataSet;
+
+// Parameters:
+// The connector sends us the following:
+// connection : SQL connection
+//
+// action: String correponding to the action (UPDATE/ADD_ATTRIBUTE_VALUES/REMOVE_ATTRIBUTE_VALUES)
+// - UPDATE : For each input attribute, replace all of the current values of that attribute
+// in the target object with the values of that attribute.
+// - ADD_ATTRIBUTE_VALUES: For each attribute that the input set contains, add to the current values
+// of that attribute in the target object all of the values of that attribute in the input set.
+// - REMOVE_ATTRIBUTE_VALUES: For each attribute that the input set contains, remove from the current values
+// of that attribute in the target object any value that matches one of the values of the attribute from the input set.
+
+// log: a handler to the Log facility
+//
+// objectClass: a String describing the Object class (__ACCOUNT__ / __GROUP__ / other)
+//
+// uid: a String representing the entry uid
+//
+// attributes: an Attribute Map, containg the <String> attribute name as a key
+// and the <List> attribute value(s) as value.
+//
+// password: password string, clear text (only for UPDATE)
+//
+// options: a handler to the OperationOptions Map
+
+log.info("Entering " + action + " Script");
+def sql = new Sql(connection);
+
+
+switch (action) {
+case "UPDATE":
+ if (attributes.get("location").get(0) != null) {
+ sql.executeUpdate("UPDATE TESTPRINTER SET location = ?, lastmodification = ? where id = ?",
+ [attributes.get("location").get(0), new Date(), attributes.get("__NAME__").get(0)])
+
+ return attributes.get("__NAME__").get(0);
+ }
+ break
+
+case "ADD_ATTRIBUTE_VALUES":
+ break
+
+
+default:
+ sql
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/a45a46bb/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
index 8cfec8b..efe1b16 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
@@ -35,11 +35,13 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.mod.AnyObjectMod;
import org.apache.syncope.common.lib.mod.AttrMod;
import org.apache.syncope.common.lib.mod.GroupMod;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.AbstractPolicyTO;
import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AttrTO;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.to.GroupTO;
@@ -48,6 +50,7 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.ConnConfProperty;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyObjectService;
import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
import org.apache.syncope.common.rest.api.service.AnyTypeService;
import org.apache.syncope.common.rest.api.service.CamelRouteService;
@@ -141,6 +144,8 @@ public abstract class AbstractITCase {
protected static final String RESOURCE_NAME_CREATE_NONE = "ws-target-resource-create-none";
+ protected static final String RESOURCE_NAME_DBSCRIPTED = "resource-db-scripted";
+
protected static String ANONYMOUS_UNAME;
protected static String ANONYMOUS_KEY;
@@ -155,6 +160,8 @@ public abstract class AbstractITCase {
protected static RealmService realmService;
+ protected static AnyObjectService anyObjectService;
+
protected static RoleService roleService;
protected static UserService userService;
@@ -226,6 +233,7 @@ public abstract class AbstractITCase {
anyTypeClassService = adminClient.getService(AnyTypeClassService.class);
anyTypeService = adminClient.getService(AnyTypeService.class);
realmService = adminClient.getService(RealmService.class);
+ anyObjectService = adminClient.getService(AnyObjectService.class);
roleService = adminClient.getService(RoleService.class);
userService = adminClient.getService(UserService.class);
userSelfService = adminClient.getService(UserSelfService.class);
@@ -287,8 +295,8 @@ public abstract class AbstractITCase {
return userService.update(userMod.getKey(), userMod).readEntity(UserTO.class);
}
- protected UserTO deleteUser(final Long id) {
- return userService.delete(id).readEntity(UserTO.class);
+ protected UserTO deleteUser(final Long key) {
+ return userService.delete(key).readEntity(UserTO.class);
}
public <T> T getObject(final URI location, final Class<?> serviceClass, final Class<T> resultClass) {
@@ -322,6 +330,25 @@ public abstract class AbstractITCase {
return getObject(response.getLocation(), RoleService.class, RoleTO.class);
}
+ protected AnyObjectTO createAnyObject(final AnyObjectTO anyObjectTO) {
+ Response response = anyObjectService.create(anyObjectTO);
+ if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+ Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+ if (ex != null) {
+ throw (RuntimeException) ex;
+ }
+ }
+ return getObject(response.getLocation(), AnyObjectService.class, AnyObjectTO.class);
+ }
+
+ protected AnyObjectTO updateAnyObject(final AnyObjectMod anyObjectMod) {
+ return anyObjectService.update(anyObjectMod.getKey(), anyObjectMod).readEntity(AnyObjectTO.class);
+ }
+
+ protected AnyObjectTO deleteAnyObject(final Long key) {
+ return anyObjectService.delete(key).readEntity(AnyObjectTO.class);
+ }
+
protected GroupTO createGroup(final GroupTO groupTO) {
Response response = groupService.create(groupTO);
if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
@@ -337,8 +364,8 @@ public abstract class AbstractITCase {
return groupService.update(groupMod.getKey(), groupMod).readEntity(GroupTO.class);
}
- protected GroupTO deleteGroup(final Long id) {
- return groupService.delete(id).readEntity(GroupTO.class);
+ protected GroupTO deleteGroup(final Long key) {
+ return groupService.delete(key).readEntity(GroupTO.class);
}
@SuppressWarnings("unchecked")