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 2016/06/14 16:22:32 UTC
[09/13] syncope git commit: [SYNCOPE-862] Features complete
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/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 a2c9271..4c44b7f 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
@@ -24,7 +24,6 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.policy.PullPolicySpec;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
@@ -47,8 +46,8 @@ import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -63,6 +62,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
@Transactional(readOnly = true)
@Component
@@ -103,6 +103,9 @@ public class PullUtils {
@Autowired
private AnyUtilsFactory anyUtilsFactory;
+ @Autowired
+ private IntAttrNameParser intAttrNameParser;
+
public String findMatchingAnyKey(
final AnyType anyType,
final String name,
@@ -127,7 +130,7 @@ public class PullUtils {
public boolean handle(final ConnectorObject obj) {
return found.add(obj);
}
- }, MappingManagerImpl.buildOperationOptions(MappingManagerImpl.getPullMappingItems(provision).iterator()));
+ }, MappingUtils.buildOperationOptions(MappingUtils.getPullMappingItems(provision).iterator()));
if (found.isEmpty()) {
LOG.debug("No {} found on {} with __NAME__ {}", provision.getObjectClass(), resource, name);
@@ -170,10 +173,10 @@ public class PullUtils {
List<String> result = new ArrayList<>();
- MappingItem connObjectKeyItem = MappingManagerImpl.getConnObjectKeyItem(provision);
+ MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
String transfUid = uid;
- for (MappingItemTransformer transformer : MappingManagerImpl.getMappingItemTransformers(connObjectKeyItem)) {
+ for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(connObjectKeyItem)) {
List<Object> output = transformer.beforePull(
connObjectKeyItem,
null,
@@ -183,9 +186,8 @@ public class PullUtils {
}
}
- IntAttrName intAttrName = IntAttrNameParser.parse(
+ IntAttrName intAttrName = intAttrNameParser.parse(
connObjectKeyItem.getIntAttrName(),
- anyUtilsFactory,
provision.getAnyType().getKind());
if (intAttrName.getField() != null) {
@@ -214,6 +216,8 @@ public class PullUtils {
result.add(anyObject.getKey());
}
break;
+
+ default:
}
} else if (intAttrName.getSchemaType() != null) {
switch (intAttrName.getSchemaType()) {
@@ -246,6 +250,8 @@ public class PullUtils {
result.add(any.getKey());
}
break;
+
+ default:
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/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 af2631c..c0ed5fc 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
@@ -18,7 +18,6 @@
*/
package org.apache.syncope.core.provisioning.java.utils;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
@@ -222,7 +221,7 @@ public class ConnObjectUtils {
// 1. fill with data from connector object
anyTO.setRealm(pullTask.getDestinatioRealm().getFullPath());
- for (MappingItem item : MappingManagerImpl.getPullMappingItems(provision)) {
+ for (MappingItem item : MappingUtils.getPullMappingItems(provision)) {
mappingManager.setIntValues(item, obj.getAttributeByName(item.getExtAttrName()), anyTO, anyUtils);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
new file mode 100644
index 0000000..63ceb98
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
@@ -0,0 +1,239 @@
+/*
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.MapContext;
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
+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.data.MappingItemTransformer;
+import org.apache.syncope.core.provisioning.java.data.JEXLMappingItemTransformer;
+import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.OperationOptions;
+import org.identityconnectors.framework.common.objects.OperationOptionsBuilder;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+
+public final class MappingUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MappingUtils.class);
+
+ public static MappingItem getConnObjectKeyItem(final Provision provision) {
+ Mapping mapping = null;
+ if (provision != null) {
+ mapping = provision.getMapping();
+ }
+
+ return mapping == null
+ ? null
+ : mapping.getConnObjectKeyItem();
+ }
+
+ private static List<MappingItem> getMappingItems(final Provision provision, final MappingPurpose purpose) {
+ List<? extends MappingItem> items = Collections.<MappingItem>emptyList();
+ if (provision != null) {
+ items = provision.getMapping().getItems();
+ }
+
+ List<MappingItem> result = new ArrayList<>();
+
+ switch (purpose) {
+ case PULL:
+ for (MappingItem item : items) {
+ if (MappingPurpose.PROPAGATION != item.getPurpose()
+ && MappingPurpose.NONE != item.getPurpose()) {
+
+ result.add(item);
+ }
+ }
+ break;
+
+ case PROPAGATION:
+ for (MappingItem item : items) {
+ if (MappingPurpose.PULL != item.getPurpose()
+ && MappingPurpose.NONE != item.getPurpose()) {
+
+ result.add(item);
+ }
+ }
+ break;
+
+ case BOTH:
+ for (MappingItem item : items) {
+ if (MappingPurpose.NONE != item.getPurpose()) {
+ result.add(item);
+ }
+ }
+ break;
+
+ case NONE:
+ for (MappingItem item : items) {
+ if (MappingPurpose.NONE == item.getPurpose()) {
+ result.add(item);
+ }
+ }
+ break;
+
+ default:
+ }
+
+ return result;
+ }
+
+ public static List<MappingItem> getPropagationMappingItems(final Provision provision) {
+ return getMappingItems(provision, MappingPurpose.PROPAGATION);
+ }
+
+ public static List<MappingItem> getPullMappingItems(final Provision provision) {
+ return getMappingItems(provision, MappingPurpose.PULL);
+ }
+
+ /**
+ * Build __NAME__ for propagation. First look if there ia a defined connObjectLink for the given resource (and in
+ * this case evaluate as JEXL); otherwise, take given connObjectKey.
+ *
+ * @param any given any object
+ * @param provision external resource
+ * @param connObjectKey connector object key
+ * @return the value to be propagated as __NAME__
+ */
+ public static Name evaluateNAME(final Any<?> any, final Provision provision, final String connObjectKey) {
+ if (StringUtils.isBlank(connObjectKey)) {
+ // LOG error but avoid to throw exception: leave it to the external resource
+ LOG.error("Missing ConnObjectKey for '{}': ", provision.getResource());
+ }
+
+ // Evaluate connObjectKey expression
+ String connObjectLink = provision == null || provision.getMapping() == null
+ ? null
+ : provision.getMapping().getConnObjectLink();
+ String evalConnObjectLink = null;
+ if (StringUtils.isNotBlank(connObjectLink)) {
+ JexlContext jexlContext = new MapContext();
+ JexlUtils.addFieldsToContext(any, jexlContext);
+ JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
+ JexlUtils.addDerAttrsToContext(any, jexlContext);
+ evalConnObjectLink = JexlUtils.evaluate(connObjectLink, jexlContext);
+ }
+
+ // If connObjectLink evaluates to an empty string, just use the provided connObjectKey as Name(),
+ // otherwise evaluated connObjectLink expression is taken as Name().
+ Name name;
+ if (StringUtils.isBlank(evalConnObjectLink)) {
+ // add connObjectKey as __NAME__ attribute ...
+ LOG.debug("Add connObjectKey [{}] as __NAME__", connObjectKey);
+ name = new Name(connObjectKey);
+ } else {
+ LOG.debug("Add connObjectLink [{}] as __NAME__", evalConnObjectLink);
+ name = new Name(evalConnObjectLink);
+
+ // connObjectKey not propagated: it will be used to set the value for __UID__ attribute
+ LOG.debug("connObjectKey will be used just as __UID__ attribute");
+ }
+
+ return name;
+ }
+
+ public static List<MappingItemTransformer> getMappingItemTransformers(final MappingItem mappingItem) {
+ List<MappingItemTransformer> result = new ArrayList<>();
+
+ // First consider the JEXL transformation expressions
+ JEXLMappingItemTransformer jexlTransformer = null;
+ if (StringUtils.isNotBlank(mappingItem.getPropagationJEXLTransformer())
+ || StringUtils.isNotBlank(mappingItem.getPullJEXLTransformer())) {
+
+ try {
+ jexlTransformer = (JEXLMappingItemTransformer) ApplicationContextProvider.getBeanFactory().
+ createBean(JEXLMappingItemTransformer.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+
+ jexlTransformer.setPropagationJEXL(mappingItem.getPropagationJEXLTransformer());
+ jexlTransformer.setPullJEXL(mappingItem.getPullJEXLTransformer());
+ } catch (Exception e) {
+ LOG.error("Could not instantiate {}, ignoring...", JEXLMappingItemTransformer.class.getName(), e);
+ }
+ }
+ if (jexlTransformer != null) {
+ result.add(jexlTransformer);
+ }
+
+ // Then other custom tranaformers
+ for (String className : mappingItem.getMappingItemTransformerClassNames()) {
+ try {
+ Class<?> transformerClass = ClassUtils.getClass(className);
+
+ result.add((MappingItemTransformer) ApplicationContextProvider.getBeanFactory().
+ createBean(transformerClass, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false));
+ } catch (Exception e) {
+ LOG.error("Could not instantiate {}, ignoring...", className, e);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Build options for requesting all mapped connector attributes.
+ *
+ * @param mapItems mapping items
+ * @return options for requesting all mapped connector attributes
+ * @see OperationOptions
+ */
+ public static OperationOptions buildOperationOptions(final Iterator<? extends MappingItem> mapItems) {
+ OperationOptionsBuilder builder = new OperationOptionsBuilder();
+
+ Set<String> attrsToGet = new HashSet<>();
+ attrsToGet.add(Name.NAME);
+ attrsToGet.add(Uid.NAME);
+ attrsToGet.add(OperationalAttributes.ENABLE_NAME);
+
+ while (mapItems.hasNext()) {
+ MappingItem mapItem = mapItems.next();
+ if (mapItem.getPurpose() != MappingPurpose.NONE) {
+ attrsToGet.add(mapItem.getExtAttrName());
+ }
+ }
+
+ builder.setAttributesToGet(attrsToGet);
+ // -------------------------------------
+
+ return builder.build();
+ }
+
+ /**
+ * Private default constructor, for static-only classes.
+ */
+ private MappingUtils() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/core/provisioning-java/src/main/resources/provisioningContext.xml
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/provisioningContext.xml b/core/provisioning-java/src/main/resources/provisioningContext.xml
index 068d1e7..37c8181 100644
--- a/core/provisioning-java/src/main/resources/provisioningContext.xml
+++ b/core/provisioning-java/src/main/resources/provisioningContext.xml
@@ -122,4 +122,5 @@ under the License.
<property name="stringLocations" value="${connid.locations}"/>
</bean>
+ <bean class="org.apache.syncope.core.provisioning.java.IntAttrNameParser"/>
</beans>
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
new file mode 100644
index 0000000..c603f8a
--- /dev/null
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional("Master")
+public class IntAttrNameParserTest extends AbstractTest {
+
+ @Autowired
+ private IntAttrNameParser intAttrNameParser;
+
+ @Test
+ public void ownFields() {
+ IntAttrName intAttrName = intAttrNameParser.parse("key", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNotNull(intAttrName.getField());
+ assertEquals("key", intAttrName.getField());
+ assertNull(intAttrName.getSchemaName());
+ assertNull(intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+
+ intAttrName = intAttrNameParser.parse("name", AnyTypeKind.GROUP);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+ assertNotNull(intAttrName.getField());
+ assertEquals("name", intAttrName.getField());
+ assertNull(intAttrName.getSchemaName());
+ assertNull(intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+
+ intAttrName = intAttrNameParser.parse("userOwner", AnyTypeKind.GROUP);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+ assertNotNull(intAttrName.getField());
+ assertEquals("userOwner", intAttrName.getField());
+ assertNull(intAttrName.getSchemaName());
+ assertNull(intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+
+ intAttrName = intAttrNameParser.parse("name", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ }
+
+ @Test
+ public void ownSchema() {
+ IntAttrName intAttrName = intAttrNameParser.parse("email", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("email", intAttrName.getSchemaName());
+ assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+
+ intAttrName = intAttrNameParser.parse("cn", AnyTypeKind.ANY_OBJECT);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("cn", intAttrName.getSchemaName());
+ assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+
+ intAttrName = intAttrNameParser.parse("rvirtualdata", AnyTypeKind.ANY_OBJECT);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("rvirtualdata", intAttrName.getSchemaName());
+ assertEquals(SchemaType.VIRTUAL, intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ }
+
+ @Test
+ public void enclosingGroup() {
+ IntAttrName intAttrName = intAttrNameParser.parse("groups[readers].cn", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("cn", intAttrName.getSchemaName());
+ assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+ assertEquals("readers", intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ }
+
+ @Test
+ public void relatedAnyObject() {
+ IntAttrName intAttrName = intAttrNameParser.parse("anyObjects[hp].name", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+ assertEquals("name", intAttrName.getField());
+ assertNull(intAttrName.getSchemaName());
+ assertNull(intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertEquals("hp", intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getMembershipOfGroup());
+ }
+
+ @Test
+ public void membership() {
+ IntAttrName intAttrName = intAttrNameParser.parse("memberships[top].cn", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("cn", intAttrName.getSchemaName());
+ assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertEquals("top", intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ }
+
+ @Test
+ public void invalid() {
+ try {
+ intAttrNameParser.parse("memberships.cn", AnyTypeKind.USER);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
index dd6792b..0e84b68 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
@@ -27,6 +27,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
import org.identityconnectors.framework.common.objects.Name;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,12 +58,12 @@ public class MappingTest extends AbstractTest {
User user = userDAO.findByUsername("rossini");
assertNotNull(user);
- Name name = MappingManagerImpl.evaluateNAME(user, provision, user.getUsername());
+ Name name = MappingUtils.evaluateNAME(user, provision, user.getUsername());
assertEquals("uid=rossini,ou=people,o=isp", name.getNameValue());
provision.getMapping().setConnObjectLink("'uid=' + username + ',o=' + realm + ',ou=people,o=isp'");
- name = MappingManagerImpl.evaluateNAME(user, provision, user.getUsername());
+ name = MappingUtils.evaluateNAME(user, provision, user.getUsername());
assertEquals("uid=rossini,o=even,ou=people,o=isp", name.getNameValue());
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
index 7fc60df..822860f 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
@@ -34,11 +34,11 @@ public class PrefixMappingItemTransformer extends DefaultMappingItemTransformer
@Override
public List<PlainAttrValue> beforePropagation(
final MappingItem mappingItem,
- final List<Any<?>> anys,
+ final Any<?> any,
final List<PlainAttrValue> values) {
if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
- return super.beforePropagation(mappingItem, anys, values);
+ return super.beforePropagation(mappingItem, any, values);
} else {
String value = values.get(0).getStringValue();
values.get(0).setStringValue(PREFIX + value);
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
index 1036fdc..849db31 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
@@ -43,17 +43,7 @@ public class NotificationsITCase extends AbstractConsoleITCase {
FormTester formTester = wicketTester.newFormTester(
"body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form");
- // -------------------------------
- // generate event to populate recipientAttrName
- // -------------------------------
- formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
- wicketTester.executeAjaxEvent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form:content:"
- + "form:view:recipientAttrType:dropDownChoiceField", Constants.ON_CHANGE);
- // -------------------------------
-
- formTester.select("content:form:view:recipientAttrType:dropDownChoiceField", 3);
- formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
- formTester.setValue("content:form:view:recipientAttrName:dropDownChoiceField", "0");
+ formTester.setValue("content:form:view:recipientAttrName:textField", "email");
formTester.select("content:form:view:template:dropDownChoiceField", 2);
formTester.select("content:form:view:traceLevel:dropDownChoiceField", 0);
formTester.setValue("content:form:view:sender:textField", sender);
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
index 6c3b10a..1ad33ea 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
@@ -168,23 +168,12 @@ public class TopologyITCase extends AbstractConsoleITCase {
formTester = wicketTester.newFormTester(
"body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form");
- formTester.setValue("view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", "0");
- wicketTester.executeAjaxEvent(
- "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
- + ":view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", Constants.ON_CHANGE);
-
- formTester.setValue("view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", "4");
- wicketTester.executeAjaxEvent(
- "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
- + ":view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", Constants.ON_CHANGE);
-
formTester.setValue("view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", "true");
wicketTester.executeAjaxEvent(
"body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
+ ":view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", Constants.ON_CHANGE);
- formTester.setValue("view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", "0");
- formTester.setValue("view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", "4");
+ formTester.setValue("view:mapping:mappingContainer:mappings:0:intAttrName:textField", "key");
formTester.setValue("view:mapping:mappingContainer:mappings:0:extAttrName:textField", "ID");
formTester.setValue("view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", "true");
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index a09b9bb..326cf96 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -867,8 +867,17 @@ public class GroupITCase extends AbstractITCase {
@Test
public void issueSYNCOPE632() {
- GroupTO groupTO = null;
+ GroupTO groupTO = getSampleTO("lastGroup");
try {
+ // 0. create group
+ groupTO.getPlainAttrs().add(attrTO("icon", "anIcon"));
+ groupTO.getPlainAttrs().add(attrTO("show", "true"));
+ groupTO.getDerAttrs().add(attrTO("displayProperty", null));
+ groupTO.getResources().clear();
+
+ groupTO = createGroup(groupTO).getAny();
+ assertNotNull(groupTO);
+
// 1. create new LDAP resource having ConnObjectKey mapped to a derived attribute
ResourceTO newLDAP = resourceService.read(RESOURCE_NAME_LDAP);
newLDAP.setKey("new-ldap");
@@ -887,22 +896,22 @@ public class GroupITCase extends AbstractITCase {
mapping.setConnObjectLink("'cn=' + displayProperty + ',ou=groups,o=isp'");
MappingItemTO description = new MappingItemTO();
+ description.setIntAttrName("key");
description.setExtAttrName("description");
- description.setPurpose(MappingPurpose.BOTH);
+ description.setPurpose(MappingPurpose.PROPAGATION);
mapping.add(description);
newLDAP = createResource(newLDAP);
assertNotNull(newLDAP);
- // 2. create a group and give the resource created above
- groupTO = getSampleTO("lastGroup" + getUUIDString());
- groupTO.getPlainAttrs().add(attrTO("icon", "anIcon"));
- groupTO.getPlainAttrs().add(attrTO("show", "true"));
- groupTO.getDerAttrs().add(attrTO("displayProperty", null));
- groupTO.getResources().clear();
- groupTO.getResources().add("new-ldap");
+ // 2. update group and give the resource created above
+ GroupPatch patch = new GroupPatch();
+ patch.setKey(groupTO.getKey());
+ patch.getResources().add(new StringPatchItem.Builder().
+ operation(PatchOperation.ADD_REPLACE).
+ value("new-ldap").build());
- groupTO = createGroup(groupTO).getAny();
+ groupTO = updateGroup(patch).getAny();
assertNotNull(groupTO);
// 3. update the group
@@ -943,7 +952,7 @@ public class GroupITCase extends AbstractITCase {
assertEquals(1, entries);
} finally {
- if (groupTO != null) {
+ if (groupTO.getKey() != null) {
groupService.delete(groupTO.getKey());
}
resourceService.delete("new-ldap");
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
index 38b3631..3d98f28 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -18,30 +18,47 @@
*/
package org.apache.syncope.fit.core;
+import static org.apache.syncope.fit.core.AbstractTaskITCase.execProvisioningTask;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import javax.ws.rs.core.Response;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.patch.AttrPatch;
+import org.apache.syncope.common.lib.patch.DeassociationPatch;
import org.apache.syncope.common.lib.patch.MembershipPatch;
import org.apache.syncope.common.lib.patch.UserPatch;
import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.to.TypeExtensionTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
+import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
+import org.apache.syncope.common.rest.api.service.TaskService;
import org.apache.syncope.fit.AbstractITCase;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import org.springframework.jdbc.core.JdbcTemplate;
@FixMethodOrder(MethodSorters.JVM)
public class MembershipITCase extends AbstractITCase {
@@ -203,4 +220,99 @@ public class MembershipITCase extends AbstractITCase {
user = userService.read(user.getKey());
assertTrue(user.getMemberships().isEmpty());
}
+
+ @Test
+ public void syncWithMembershipAttr() {
+ // 0. create ad-hoc resource, with adequate mapping
+ ResourceTO newResource = resourceService.read(RESOURCE_NAME_DBPULL);
+ newResource.setKey(getUUIDString());
+
+ MappingItemTO item = IterableUtils.find(newResource.getProvision("USER").getMapping().getItems(),
+ new Predicate<MappingItemTO>() {
+
+ @Override
+ public boolean evaluate(final MappingItemTO object) {
+ return "firstname".equals(object.getIntAttrName());
+ }
+ });
+ assertNotNull(item);
+ assertEquals("ID", item.getExtAttrName());
+ item.setIntAttrName("memberships[additional].aLong");
+ item.setPurpose(MappingPurpose.BOTH);
+
+ item = IterableUtils.find(newResource.getProvision("USER").getMapping().getItems(),
+ new Predicate<MappingItemTO>() {
+
+ @Override
+ public boolean evaluate(final MappingItemTO object) {
+ return "fullname".equals(object.getIntAttrName());
+ }
+ });
+ item.setPurpose(MappingPurpose.PULL);
+
+ PullTaskTO newTask = null;
+ try {
+ newResource = createResource(newResource);
+ assertNotNull(newResource);
+
+ // 1. create user with new resource assigned
+ UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
+ user.setRealm("/even/two");
+ user.getPlainAttrs().remove(user.getPlainAttrMap().get("ctype"));
+ user.getResources().clear();
+ user.getResources().add(newResource.getKey());
+
+ MembershipTO membership = new MembershipTO.Builder().group("034740a9-fa10-453b-af37-dc7897e98fb1").build();
+ membership.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("5432").build());
+ user.getMemberships().add(membership);
+
+ user = createUser(user).getAny();
+ assertNotNull(user);
+
+ // 2. verify that user was found on resource
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+ String idOnResource = jdbcTemplate.queryForObject(
+ "SELECT id FROM testpull WHERE id=?", String.class, "5432");
+ assertEquals("5432", idOnResource);
+
+ // 3. unlink user from resource, then remove it
+ DeassociationPatch patch = new DeassociationPatch();
+ patch.setKey(user.getKey());
+ patch.setAction(ResourceDeassociationAction.UNLINK);
+ patch.getResources().add(newResource.getKey());
+ assertNotNull(userService.deassociate(patch).readEntity(BulkActionResult.class));
+
+ userService.delete(user.getKey());
+
+ // 4. create pull task and execute
+ newTask = taskService.read("7c2242f4-14af-4ab5-af31-cdae23783655", true);
+ newTask.setResource(newResource.getKey());
+ newTask.setDestinationRealm("/even/two");
+
+ Response response = taskService.create(newTask);
+ newTask = getObject(response.getLocation(), TaskService.class, PullTaskTO.class);
+ assertNotNull(newTask);
+
+ ExecTO execution = execProvisioningTask(taskService, newTask.getKey(), 50, false);
+ assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
+
+ // 5. verify that pulled user has
+ PagedResult<UserTO> users = userService.search(new AnySearchQuery.Builder().
+ realm("/").
+ fiql(SyncopeClient.getUserSearchConditionBuilder().
+ is("username").equalTo(user.getUsername()).query()).build());
+ assertEquals(1, users.getTotalCount());
+ assertEquals(1, users.getResult().get(0).getMemberships().size());
+ assertEquals("5432", users.getResult().get(0).getMemberships().get(0).
+ getPlainAttrMap().get("aLong").getValues().get(0));
+ } catch (Exception e) {
+ LOG.error("Unexpected error", e);
+ fail(e.getMessage());
+ } finally {
+ if (newTask != null && !"83f7e85d-9774-43fe-adba-ccd856312994".equals(newTask.getKey())) {
+ taskService.delete(newTask.getKey());
+ }
+ resourceService.delete(newResource.getKey());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
index a89fae3..59de26b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
@@ -339,7 +339,7 @@ public class MigrationITCase extends AbstractTaskITCase {
provisionTO.setMapping(mapping);
item = new MappingItemTO();
- item.setIntAttrName("groupName");
+ item.setIntAttrName("name");
item.setExtAttrName("name");
item.setMandatoryCondition("true");
item.setPurpose(MappingPurpose.PULL);
@@ -417,7 +417,7 @@ public class MigrationITCase extends AbstractTaskITCase {
public void migrateFromSyncope12() throws InterruptedException {
// 1. cleanup
try {
- realmService.delete(MIGRATION_REALM);
+ realmService.delete("/" + MIGRATION_REALM);
} catch (Exception e) {
// ignore
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d7517772/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
index f509611..6d7dd0d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -255,10 +255,8 @@ public class ResourceITCase extends AbstractITCase {
createResource(resourceTO);
fail("Create should not have worked");
} catch (SyncopeClientException e) {
- assertEquals(ClientExceptionType.Composite, e.getType());
- SyncopeClientException rvm = e.asComposite().getException(ClientExceptionType.RequiredValuesMissing);
- assertNotNull(rvm);
- assertEquals("intAttrName", rvm.getElements().iterator().next());
+ assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+ assertEquals("intAttrName", e.getElements().iterator().next());
}
}
@@ -701,4 +699,34 @@ public class ResourceITCase extends AbstractITCase {
}
}
}
+
+ public void issueSYNCOPE645() {
+ ResourceTO resource = new ResourceTO();
+ resource.setKey("ws-target-resource-basic-save-invalid");
+
+ String connector = resourceService.read("ws-target-resource-1").getConnector();
+ resource.setConnector(connector);
+
+ ProvisionTO provision = new ProvisionTO();
+ provision.setAnyType(AnyTypeKind.USER.name());
+ provision.setObjectClass("__ACCOUNT__");
+ resource.getProvisions().add(provision);
+
+ MappingTO mapping = new MappingTO();
+ provision.setMapping(mapping);
+
+ MappingItemTO item = new MappingItemTO();
+ item.setIntAttrName("icon");
+ item.setExtAttrName("icon");
+ item.setPurpose(MappingPurpose.BOTH);
+ mapping.setConnObjectKeyItem(item);
+
+ // save the resource
+ try {
+ resourceService.create(resource);
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.InvalidMapping, e.getType());
+ }
+ }
}