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/05 17:11:53 UTC
[18/21] syncope git commit: [SYNCOPE-666] All tests are green,
time to add more
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index fb01aa4..4a8a35b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -18,14 +18,17 @@
*/
package org.apache.syncope.core.provisioning.java.data;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.SyncopeClientCompositeException;
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -33,6 +36,8 @@ import org.apache.syncope.common.lib.mod.AnyMod;
import org.apache.syncope.common.lib.mod.AttrMod;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.IntMappingType;
import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -60,21 +65,25 @@ import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.common.lib.types.PropagationByResource;
import org.apache.syncope.core.misc.ConnObjectUtils;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
import org.apache.syncope.core.misc.MappingUtils;
import org.apache.syncope.core.misc.jexl.JexlUtils;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Membership;
import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.Relationship;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -83,10 +92,18 @@ abstract class AbstractAnyDataBinder {
protected static final Logger LOG = LoggerFactory.getLogger(AbstractAnyDataBinder.class);
+ private static final IntMappingType[] FOR_MANDATORY = new IntMappingType[] {
+ IntMappingType.AnyPlainSchema, IntMappingType.AnyDerivedSchema,
+ IntMappingType.UserPlainSchema, IntMappingType.UserDerivedSchema,
+ IntMappingType.GroupPlainSchema, IntMappingType.GroupDerivedSchema };
+
@Autowired
protected RealmDAO realmDAO;
@Autowired
+ protected AnyTypeClassDAO anyTypeClassDAO;
+
+ @Autowired
protected AnyObjectDAO anyObjectDAO;
@Autowired
@@ -129,7 +146,7 @@ abstract class AbstractAnyDataBinder {
protected AnyUtilsFactory anyUtilsFactory;
@Autowired
- protected VirAttrHandler virtAttrHander;
+ protected VirAttrHandler virAttrHander;
@Autowired
protected ConnObjectUtils connObjectUtils;
@@ -138,7 +155,7 @@ abstract class AbstractAnyDataBinder {
if (StringUtils.isNotBlank(anyMod.getRealm())) {
Realm newRealm = realmDAO.find(anyMod.getRealm());
if (newRealm == null) {
- LOG.warn("Invalid realm specified: {}, ignoring", anyMod.getRealm());
+ LOG.debug("Invalid realm specified: {}, ignoring", anyMod.getRealm());
} else {
any.setRealm(newRealm);
}
@@ -155,7 +172,6 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Ignoring invalid schema {}", schemaName);
} else if (schema.isReadonly()) {
schema = null;
-
LOG.debug("Ignoring readonly schema {}", schemaName);
}
}
@@ -175,7 +191,7 @@ abstract class AbstractAnyDataBinder {
return schema;
}
- protected void fillAttribute(final List<String> values, final AnyUtils anyUtils,
+ private void fillAttribute(final List<String> values, final AnyUtils anyUtils,
final PlainSchema schema, final PlainAttr<?> attr, final SyncopeClientException invalidValues) {
// if schema is multivalue, all values are considered for addition;
@@ -201,54 +217,57 @@ abstract class AbstractAnyDataBinder {
}
}
- private boolean evaluateMandatoryCondition(final AnyUtils anyUtils, final ExternalResource resource,
- final Any<?, ?, ?> any, final String intAttrName, final IntMappingType intMappingType) {
+ private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?, ?, ?> any) {
+ List<String> missingAttrNames = new ArrayList<>();
+
+ if (provision != null) {
+ for (MappingItem item : provision.getMapping().getItems()) {
+ if (ArrayUtils.contains(FOR_MANDATORY, item.getIntMappingType())
+ && (item.getPurpose() == MappingPurpose.PROPAGATION
+ || item.getPurpose() == MappingPurpose.BOTH)) {
- boolean result = false;
+ List<PlainAttrValue> values = MappingUtils.getIntValues(
+ provision, item, Collections.<Any<?, ?, ?>>singletonList(any), null, null);
+ if ((values == null || values.isEmpty())
+ && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
- Collection<MappingItem> mappings = MappingUtils.getMatchingMappingItems(
- anyUtils.getMappingItems(resource.getProvision(any.getType()), MappingPurpose.PROPAGATION),
- intAttrName, intMappingType);
- for (Iterator<MappingItem> itor = mappings.iterator(); itor.hasNext() && !result;) {
- MappingItem mapping = itor.next();
- result |= JexlUtils.evaluateMandatoryCondition(mapping.getMandatoryCondition(), any);
+ missingAttrNames.add(item.getIntAttrName());
+ }
+ }
+ }
}
- return result;
+ return missingAttrNames;
}
- private boolean evaluateMandatoryCondition(final AnyUtils anyUtils,
- final Any<?, ?, ?> any, final String intAttrName, final IntMappingType intMappingType) {
+ private SyncopeClientException checkMandatoryOnResources(
+ final Any<?, ?, ?> any, final Set<ExternalResource> resources) {
- boolean result = false;
+ SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
- Iterable<? extends ExternalResource> iterable = any instanceof User
- ? userDAO.findAllResources((User) any)
- : any instanceof Group
- ? ((Group) any).getResources()
- : Collections.<ExternalResource>emptySet();
-
- for (Iterator<? extends ExternalResource> itor = iterable.iterator(); itor.hasNext() && !result;) {
- ExternalResource resource = itor.next();
- if (resource.isEnforceMandatoryCondition()) {
- result |= evaluateMandatoryCondition(
- anyUtils, resource, any, intAttrName, intMappingType);
+ for (ExternalResource resource : resources) {
+ Provision provision = resource.getProvision(any.getType());
+ if (resource.isEnforceMandatoryCondition() && provision != null) {
+ List<String> missingAttrNames = evaluateMandatoryCondition(provision, any);
+ if (!missingAttrNames.isEmpty()) {
+ LOG.error("Mandatory schemas {} not provided with values", missingAttrNames);
+
+ reqValMissing.getElements().addAll(missingAttrNames);
+ }
}
}
- return result;
+ return reqValMissing;
}
- private SyncopeClientException checkMandatory(final AnyUtils anyUtils, final Any<?, ?, ?> any) {
+ private SyncopeClientException checkMandatory(final Any<?, ?, ?> any) {
SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
// Check if there is some mandatory schema defined for which no value has been provided
for (PlainSchema schema : any.getAllowedPlainSchemas()) {
if (any.getPlainAttr(schema.getKey()) == null
&& !schema.isReadonly()
- && (JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any)
- || evaluateMandatoryCondition(anyUtils, any, schema.getKey(),
- anyUtils.plainIntMappingType()))) {
+ && (JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any))) {
LOG.error("Mandatory schema " + schema.getKey() + " not provided with values");
@@ -256,30 +275,21 @@ abstract class AbstractAnyDataBinder {
}
}
- for (DerSchema derSchema : any.getAllowedDerSchemas()) {
- if (any.getDerAttr(derSchema.getKey()) == null
- && evaluateMandatoryCondition(anyUtils, any, derSchema.getKey(),
- anyUtils.derIntMappingType())) {
-
- LOG.error("Mandatory derived schema " + derSchema.getKey() + " does not evaluate to any value");
-
- reqValMissing.getElements().add(derSchema.getKey());
- }
- }
-
- for (VirSchema virSchema : any.getAllowedVirSchemas()) {
- if (any.getVirAttr(virSchema.getKey()) == null
- && !virSchema.isReadonly()
- && evaluateMandatoryCondition(anyUtils, any, virSchema.getKey(),
- anyUtils.virIntMappingType())) {
+ return reqValMissing;
+ }
- LOG.error("Mandatory virtual schema " + virSchema.getKey() + " not provided with values");
+ private Set<ExternalResource> getAllResources(final Any<?, ?, ?> any) {
+ Set<ExternalResource> resources = new HashSet<>();
- reqValMissing.getElements().add(virSchema.getKey());
- }
+ if (any instanceof User) {
+ resources.addAll(userDAO.findAllResources((User) any));
+ } else if (any instanceof Group) {
+ resources.addAll(((Group) any).getResources());
+ } else if (any instanceof AnyObject) {
+ resources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
}
- return reqValMissing;
+ return resources;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -288,9 +298,29 @@ abstract class AbstractAnyDataBinder {
PropagationByResource propByRes = new PropagationByResource();
+ // 1. anyTypeClass to be removed
+ for (String className : anyMod.getAuxClassesToRemove()) {
+ AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+ if (auxClass == null) {
+ LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+ } else {
+ any.remove(auxClass);
+ }
+ }
+
+ // 2. anyTypeClass to be added
+ for (String className : anyMod.getAuxClassesToAdd()) {
+ AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+ if (auxClass == null) {
+ LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+ } else {
+ any.add(auxClass);
+ }
+ }
+
SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
- // 1. resources to be removed
+ // 3. resources to be removed
for (String resourceToBeRemoved : anyMod.getResourcesToRemove()) {
ExternalResource resource = resourceDAO.find(resourceToBeRemoved);
if (resource != null) {
@@ -301,7 +331,7 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Resources to be removed:\n{}", propByRes);
- // 2. resources to be added
+ // 4. resources to be added
for (String resourceToBeAdded : anyMod.getResourcesToAdd()) {
ExternalResource resource = resourceDAO.find(resourceToBeAdded);
if (resource != null) {
@@ -312,16 +342,9 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Resources to be added:\n{}", propByRes);
- Set<ExternalResource> externalResources = new HashSet<>();
- if (any instanceof User) {
- externalResources.addAll(userDAO.findAllResources((User) any));
- } else if (any instanceof Group) {
- externalResources.addAll(((Group) any).getResources());
- } else if (any instanceof AnyObject) {
- externalResources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
- }
+ Set<ExternalResource> resources = getAllResources(any);
- // 3. attributes to be removed
+ // 5. attributes to be removed
for (String attributeToBeRemoved : anyMod.getPlainAttrsToRemove()) {
PlainSchema schema = getPlainSchema(attributeToBeRemoved);
if (schema != null) {
@@ -344,7 +367,7 @@ abstract class AbstractAnyDataBinder {
}
}
- for (ExternalResource resource : externalResources) {
+ for (ExternalResource resource : resources) {
for (MappingItem mapItem : anyUtils.getMappingItems(
resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
@@ -364,7 +387,7 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Attributes to be removed:\n{}", propByRes);
- // 4. attributes to be updated
+ // 6. attributes to be updated
for (AttrMod attributeMod : anyMod.getPlainAttrsToUpdate()) {
PlainSchema schema = getPlainSchema(attributeMod.getSchema());
PlainAttr attr = null;
@@ -372,19 +395,15 @@ abstract class AbstractAnyDataBinder {
attr = any.getPlainAttr(schema.getKey());
if (attr == null) {
attr = anyUtils.newPlainAttr();
+ attr.setOwner(any);
attr.setSchema(schema);
- if (attr.getSchema() == null) {
- LOG.debug("Ignoring {} because no valid schema or template was found", attributeMod);
- } else {
- attr.setOwner(any);
- any.add(attr);
- }
+ any.add(attr);
}
}
if (schema != null && attr != null && attr.getSchema() != null) {
- virtAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, schema.getKey(),
- externalResources, anyUtils.plainIntMappingType(), propByRes);
+ virAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, schema.getKey(),
+ resources, anyUtils.plainIntMappingType(), propByRes);
// 1.1 remove values
Set<Long> valuesToBeRemoved = new HashSet<>();
@@ -429,7 +448,7 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Attributes to be updated:\n{}", propByRes);
- // 5. derived attributes to be removed
+ // 7. derived attributes to be removed
for (String derAttrToBeRemoved : anyMod.getDerAttrsToRemove()) {
DerSchema derSchema = getDerSchema(derAttrToBeRemoved);
if (derSchema != null) {
@@ -440,7 +459,7 @@ abstract class AbstractAnyDataBinder {
derAttrDAO.delete(derAttr);
}
- for (ExternalResource resource : externalResources) {
+ for (ExternalResource resource : resources) {
for (MappingItem mapItem : anyUtils.getMappingItems(
resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
@@ -463,19 +482,18 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Derived attributes to be removed:\n{}", propByRes);
- // 6. derived attributes to be added
+ // 8. derived attributes to be added
for (String derAttrToBeAdded : anyMod.getDerAttrsToAdd()) {
DerSchema derSchema = getDerSchema(derAttrToBeAdded);
if (derSchema != null) {
- virtAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, derSchema.getKey(),
- externalResources, anyUtils.derIntMappingType(), propByRes);
+ virAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, derSchema.getKey(),
+ resources, anyUtils.derIntMappingType(), propByRes);
- DerAttr derAttr = anyUtils.newDerAttr();
- derAttr.setSchema(derSchema);
- if (derAttr.getSchema() == null) {
- LOG.debug("Ignoring {} because no valid schema or template was found", derAttrToBeAdded);
- } else {
+ DerAttr derAttr = any.getDerAttr(derSchema.getKey());
+ if (derAttr == null) {
+ derAttr = anyUtils.newDerAttr();
derAttr.setOwner(any);
+ derAttr.setSchema(derSchema);
any.add(derAttr);
}
}
@@ -483,8 +501,11 @@ abstract class AbstractAnyDataBinder {
LOG.debug("Derived attributes to be added:\n{}", propByRes);
- // Finally, check if mandatory values are missing
- SyncopeClientException requiredValuesMissing = checkMandatory(anyUtils, any);
+ SyncopeClientException requiredValuesMissing = checkMandatory(any);
+ if (!requiredValuesMissing.isEmpty()) {
+ scce.addException(requiredValuesMissing);
+ }
+ requiredValuesMissing = checkMandatoryOnResources(any, resources);
if (!requiredValuesMissing.isEmpty()) {
scce.addException(requiredValuesMissing);
}
@@ -501,6 +522,17 @@ abstract class AbstractAnyDataBinder {
protected void fill(final Any any, final AnyTO anyTO,
final AnyUtils anyUtils, final SyncopeClientCompositeException scce) {
+ // 0. aux classes
+ any.getAuxClasses().clear();
+ for (String className : anyTO.getAuxClasses()) {
+ AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+ if (auxClass == null) {
+ LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+ } else {
+ any.add(auxClass);
+ }
+ }
+
// 1. attributes
SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
@@ -508,7 +540,6 @@ abstract class AbstractAnyDataBinder {
for (AttrTO attributeTO : anyTO.getPlainAttrs()) {
if (attributeTO.getValues() != null && !attributeTO.getValues().isEmpty()) {
PlainSchema schema = getPlainSchema(attributeTO.getSchema());
-
if (schema != null) {
PlainAttr attr = any.getPlainAttr(schema.getKey());
if (attr == null) {
@@ -534,7 +565,6 @@ abstract class AbstractAnyDataBinder {
// 2. derived attributes
for (AttrTO attributeTO : anyTO.getDerAttrs()) {
DerSchema derSchema = getDerSchema(attributeTO.getSchema());
-
if (derSchema != null) {
DerAttr derAttr = anyUtils.newDerAttr();
derAttr.setOwner(any);
@@ -545,8 +575,7 @@ abstract class AbstractAnyDataBinder {
// 3. virtual attributes
for (AttrTO vattrTO : anyTO.getVirAttrs()) {
- VirSchema virSchema = virtAttrHander.getVirSchema(vattrTO.getSchema());
-
+ VirSchema virSchema = virAttrHander.getVirSchema(vattrTO.getSchema());
if (virSchema != null) {
VirAttr virAttr = anyUtils.newVirAttr();
virAttr.setOwner(any);
@@ -555,27 +584,32 @@ abstract class AbstractAnyDataBinder {
}
}
- virtAttrHander.fillVirtual(any, anyTO.getVirAttrs(), anyUtils);
+ SyncopeClientException requiredValuesMissing = checkMandatory(any);
+ if (!requiredValuesMissing.isEmpty()) {
+ scce.addException(requiredValuesMissing);
+ }
+
+ virAttrHander.fillVirtual(any, anyTO.getVirAttrs());
// 4. realm & resources
Realm realm = realmDAO.find(anyTO.getRealm());
if (realm == null) {
SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
- noRealm.getElements().add(
- "Invalid or null realm specified: " + anyTO.getRealm());
+ noRealm.getElements().add("Invalid or null realm specified: " + anyTO.getRealm());
scce.addException(noRealm);
}
any.setRealm(realm);
for (String resourceName : anyTO.getResources()) {
ExternalResource resource = resourceDAO.find(resourceName);
-
- if (resource != null) {
+ if (resource == null) {
+ LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceName);
+ } else {
any.add(resource);
}
}
- SyncopeClientException requiredValuesMissing = checkMandatory(anyUtils, any);
+ requiredValuesMissing = checkMandatoryOnResources(any, getAllResources(any));
if (!requiredValuesMissing.isEmpty()) {
scce.addException(requiredValuesMissing);
}
@@ -588,11 +622,22 @@ abstract class AbstractAnyDataBinder {
protected void fillTO(final AnyTO anyTO,
final String realmFullPath,
+ final Collection<? extends AnyTypeClass> auxClasses,
final Collection<? extends PlainAttr<?>> attrs,
final Collection<? extends DerAttr<?>> derAttrs,
final Collection<? extends VirAttr<?>> virAttrs,
final Collection<? extends ExternalResource> resources) {
+ anyTO.setRealm(realmFullPath);
+
+ CollectionUtils.collect(auxClasses, new Transformer<AnyTypeClass, String>() {
+
+ @Override
+ public String transform(final AnyTypeClass role) {
+ return role.getKey();
+ }
+ }, anyTO.getAuxClasses());
+
AttrTO attributeTO;
for (PlainAttr<?> attr : attrs) {
attributeTO = new AttrTO();
@@ -621,12 +666,29 @@ abstract class AbstractAnyDataBinder {
anyTO.getVirAttrs().add(attributeTO);
}
- anyTO.setRealm(realmFullPath);
for (ExternalResource resource : resources) {
anyTO.getResources().add(resource.getKey());
}
}
+ protected RelationshipTO getRelationshipTO(final Relationship<? extends Any<?, ?, ?>, AnyObject> relationship) {
+ RelationshipTO relationshipTO = new RelationshipTO();
+ relationshipTO.setLeftKey(relationship.getLeftEnd().getKey());
+ relationshipTO.setLeftType(relationship.getLeftEnd().getType().getKey());
+ relationshipTO.setRightKey(relationship.getRightEnd().getKey());
+ relationshipTO.setRightType(relationship.getRightEnd().getType().getKey());
+ return relationshipTO;
+ }
+
+ protected MembershipTO getMembershipTO(final Membership<? extends Any<?, ?, ?>> membership) {
+ MembershipTO membershipTO = new MembershipTO();
+ membershipTO.setLeftKey(membership.getLeftEnd().getKey());
+ membershipTO.setLeftType(membership.getLeftEnd().getType().getKey());
+ membershipTO.setRightKey(membership.getRightEnd().getKey());
+ membershipTO.setGroupName(membership.getRightEnd().getName());
+ return membershipTO;
+ }
+
protected Map<String, String> getConnObjectKeys(final Any<?, ?, ?> any) {
Map<String, String> connObjectKeys = new HashMap<>();
@@ -637,7 +699,7 @@ abstract class AbstractAnyDataBinder {
: ((Group) any).getResources();
for (ExternalResource resource : iterable) {
Provision provision = resource.getProvision(any.getType());
- if (provision.getMapping() != null) {
+ if (provision != null && provision.getMapping() != null) {
MappingItem connObjectKeyItem = anyUtilsFactory.getInstance(any).getConnObjectKeyItem(provision);
if (connObjectKeyItem == null) {
throw new NotFoundException(
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index eb7586d..462a488 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -31,11 +31,13 @@ import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.mod.AnyObjectMod;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.PropagationByResource;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.core.misc.spring.BeanUtils;
import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
@@ -47,7 +49,8 @@ import org.springframework.transaction.annotation.Transactional;
public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements AnyObjectDataBinder {
private static final String[] IGNORE_PROPERTIES = {
- "realm", "memberships", "plainAttrs", "derAttrs", "virAttrs", "resources"
+ "type", "realm", "auxClasses", "relationships", "memberships", "dynGroups",
+ "plainAttrs", "derAttrs", "virAttrs", "resources"
};
@Transactional(readOnly = true)
@@ -62,20 +65,29 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
BeanUtils.copyProperties(anyObject, anyObjectTO, IGNORE_PROPERTIES);
- connObjectUtils.retrieveVirAttrValues(anyObject);
- fillTO(anyObjectTO, anyObject.getRealm().getFullPath(),
+ virAttrHander.retrieveVirAttrValues(anyObject);
+ fillTO(anyObjectTO, anyObject.getRealm().getFullPath(), anyObject.getAuxClasses(),
anyObject.getPlainAttrs(), anyObject.getDerAttrs(), anyObject.getVirAttrs(),
anyObjectDAO.findAllResources(anyObject));
- for (AMembership membership : anyObject.getMemberships()) {
- MembershipTO membershipTO = new MembershipTO();
+ // relationships
+ CollectionUtils.collect(anyObject.getRelationships(), new Transformer<ARelationship, RelationshipTO>() {
- membershipTO.setKey(membership.getKey());
- membershipTO.setRightKey(membership.getRightEnd().getKey());
- membershipTO.setGroupName(membership.getRightEnd().getName());
+ @Override
+ public RelationshipTO transform(final ARelationship relationship) {
+ return AnyObjectDataBinderImpl.this.getRelationshipTO(relationship);
+ }
- anyObjectTO.getMemberships().add(membershipTO);
- }
+ }, anyObjectTO.getRelationships());
+
+ // memberships
+ CollectionUtils.collect(anyObject.getMemberships(), new Transformer<AMembership, MembershipTO>() {
+
+ @Override
+ public MembershipTO transform(final AMembership membership) {
+ return AnyObjectDataBinderImpl.this.getMembershipTO(membership);
+ }
+ }, anyObjectTO.getMemberships());
// dynamic memberships
CollectionUtils.collect(anyObjectDAO.findDynGroupMemberships(anyObject), new Transformer<Group, Long>() {
@@ -93,6 +105,29 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
public void create(final AnyObject anyObject, final AnyObjectTO anyObjectTO) {
SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+ // relationships
+ for (RelationshipTO relationshipTO : anyObjectTO.getRelationships()) {
+ AnyObject otherEnd = anyObjectDAO.find(relationshipTO.getRightKey());
+
+ if (otherEnd == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Ignoring invalid anyObject " + relationshipTO.getRightKey());
+ }
+ } else {
+ ARelationship relationship = null;
+ if (anyObject.getKey() != null) {
+ relationship = anyObject.getRelationship(otherEnd.getKey());
+ }
+ if (relationship == null) {
+ relationship = entityFactory.newEntity(ARelationship.class);
+ relationship.setRightEnd(otherEnd);
+ relationship.setLeftEnd(anyObject);
+
+ anyObject.add(relationship);
+ }
+ }
+ }
+
// memberships
for (MembershipTO membershipTO : anyObjectTO.getMemberships()) {
Group group = groupDAO.find(membershipTO.getRightKey());
@@ -137,11 +172,44 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
// attributes, derived attributes, virtual attributes and resources
propByRes.merge(fill(anyObject, anyObjectMod, anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), scce));
- // store the group ids of membership required to be added
- Set<Long> membershipToBeAddedGroupKeys = new HashSet<>(anyObjectMod.getMembershipsToAdd());
+ Set<String> toBeDeprovisioned = new HashSet<>();
+ Set<String> toBeProvisioned = new HashSet<>();
+
+ // relationships to be removed
+ for (Long anyObjectKey : anyObjectMod.getRelationshipsToRemove()) {
+ LOG.debug("Relationship to be removed for any object {}", anyObjectKey);
+
+ ARelationship relationship = anyObject.getRelationship(anyObjectKey);
+ if (relationship == null) {
+ LOG.warn("Invalid anyObject key specified for relationship to be removed: {}", anyObjectKey);
+ } else {
+ if (!anyObjectMod.getRelationshipsToAdd().contains(anyObjectKey)) {
+ anyObject.remove(relationship);
+ toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+ }
+ }
+ }
+
+ // relationships to be added
+ for (Long anyObjectKey : anyObjectMod.getRelationshipsToAdd()) {
+ LOG.debug("Relationship to be added for any object {}", anyObjectKey);
+
+ AnyObject otherEnd = anyObjectDAO.find(anyObjectKey);
+ if (otherEnd == null) {
+ LOG.debug("Ignoring invalid any object {}", anyObjectKey);
+ } else {
+ ARelationship relationship = anyObject.getRelationship(otherEnd.getKey());
+ if (relationship == null) {
+ relationship = entityFactory.newEntity(ARelationship.class);
+ relationship.setRightEnd(otherEnd);
+ relationship.setLeftEnd(anyObject);
+
+ anyObject.add(relationship);
- final Set<String> toBeDeprovisioned = new HashSet<>();
- final Set<String> toBeProvisioned = new HashSet<>();
+ toBeProvisioned.addAll(otherEnd.getResourceNames());
+ }
+ }
+ }
// memberships to be removed
for (Long groupKey : anyObjectMod.getMembershipsToRemove()) {
@@ -151,9 +219,8 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
if (membership == null) {
LOG.warn("Invalid group key specified for membership to be removed: {}", groupKey);
} else {
- if (membershipToBeAddedGroupKeys.contains(membership.getRightEnd().getKey())) {
+ if (!anyObjectMod.getMembershipsToAdd().contains(groupKey)) {
anyObject.remove(membership);
- } else {
toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
new file mode 100644
index 0000000..5917190
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
@@ -0,0 +1,115 @@
+/*
+ * 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.data;
+
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeClassDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeClassDataBinderImpl implements AnyTypeClassDataBinder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnyTypeClassDataBinder.class);
+
+ @Autowired
+ private PlainSchemaDAO plainSchemaDAO;
+
+ @Autowired
+ private DerSchemaDAO derSchemaDAO;
+
+ @Autowired
+ private VirSchemaDAO virSchemaDAO;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Override
+ public AnyTypeClass create(final AnyTypeClassTO anyTypeClassTO) {
+ AnyTypeClass anyTypeClass = entityFactory.newEntity(AnyTypeClass.class);
+ update(anyTypeClass, anyTypeClassTO);
+ return anyTypeClass;
+ }
+
+ @Override
+ public void update(final AnyTypeClass anyTypeClass, final AnyTypeClassTO anyTypeClassTO) {
+ if (anyTypeClass.getKey() == null) {
+ anyTypeClass.setKey(anyTypeClassTO.getKey());
+ }
+
+ anyTypeClass.getPlainSchemas().clear();
+ for (String schemaName : anyTypeClassTO.getPlainSchemas()) {
+ PlainSchema schema = plainSchemaDAO.find(schemaName);
+ if (schema == null) {
+ LOG.debug("Invalid " + PlainSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+ } else {
+ anyTypeClass.add(schema);
+ }
+ }
+
+ anyTypeClass.getDerSchemas().clear();
+ for (String schemaName : anyTypeClassTO.getDerSchemas()) {
+ DerSchema schema = derSchemaDAO.find(schemaName);
+ if (schema == null) {
+ LOG.debug("Invalid " + DerSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+ } else {
+ anyTypeClass.add(schema);
+ }
+ }
+
+ anyTypeClass.getVirSchemas().clear();
+ for (String schemaName : anyTypeClassTO.getVirSchemas()) {
+ VirSchema schema = virSchemaDAO.find(schemaName);
+ if (schema == null) {
+ LOG.debug("Invalid " + VirSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+ } else {
+ anyTypeClass.add(schema);
+ }
+ }
+ }
+
+ @Override
+ public AnyTypeClassTO getAnyTypeClassTO(final AnyTypeClass anyTypeClass) {
+ AnyTypeClassTO anyTypeClassTO = new AnyTypeClassTO();
+
+ anyTypeClassTO.setKey(anyTypeClass.getKey());
+ for (PlainSchema schema : anyTypeClass.getPlainSchemas()) {
+ anyTypeClassTO.getPlainSchemas().add(schema.getKey());
+ }
+ for (DerSchema schema : anyTypeClass.getDerSchemas()) {
+ anyTypeClassTO.getDerSchemas().add(schema.getKey());
+ }
+ for (VirSchema schema : anyTypeClass.getVirSchemas()) {
+ anyTypeClassTO.getVirSchemas().add(schema.getKey());
+ }
+
+ return anyTypeClassTO;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
new file mode 100644
index 0000000..0e85d3a
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.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.java.data;
+
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeDataBinderImpl implements AnyTypeDataBinder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnyTypeDataBinder.class);
+
+ @Autowired
+ private AnyTypeClassDAO anyTypeClassDAO;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Override
+ public AnyType create(final AnyTypeTO anyTypeTO) {
+ AnyType anyType = entityFactory.newEntity(AnyType.class);
+ update(anyType, anyTypeTO);
+ return anyType;
+ }
+
+ @Override
+ public void update(final AnyType anyType, final AnyTypeTO anyTypeTO) {
+ if (anyType.getKey() == null) {
+ anyType.setKey(anyTypeTO.getKey());
+ }
+ if (anyType.getKind() == null) {
+ anyType.setKind(anyTypeTO.getKind());
+ }
+ if (anyType.getKind() != anyTypeTO.getKind()) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType);
+ sce.getElements().add("AnyTypeKind cannot be changed");
+ throw sce;
+ }
+
+ anyType.getClasses().clear();
+ for (String anyTypeClassName : anyTypeTO.getClasses()) {
+ AnyTypeClass anyTypeClass = anyTypeClassDAO.find(anyTypeClassName);
+ if (anyTypeClass == null) {
+ LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", anyTypeClassName);
+ } else {
+ anyType.add(anyTypeClass);
+ }
+ }
+ }
+
+ @Override
+ public AnyTypeTO getAnyTypeTO(final AnyType anyType) {
+ AnyTypeTO anyTypeTO = new AnyTypeTO();
+
+ anyTypeTO.setKey(anyType.getKey());
+ anyTypeTO.setKind(anyType.getKind());
+ for (AnyTypeClass anyTypeClass : anyType.getClasses()) {
+ anyTypeTO.getClasses().add(anyTypeClass.getKey());
+ }
+
+ return anyTypeTO;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
index fe5668d..3cf65fd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
@@ -47,8 +47,8 @@ public class ConfigurationDataBinderImpl extends AbstractAnyDataBinder implement
ConfTO confTO = new ConfTO();
confTO.setKey(conf.getKey());
- fillTO(confTO, null, conf.getPlainAttrs(),
- conf.getDerAttrs(), conf.getVirAttrs(), Collections.<ExternalResource>emptySet());
+ fillTO(confTO, null, conf.getAuxClasses(),
+ conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs(), Collections.<ExternalResource>emptySet());
return confTO;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index a900e70..a393fda 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -105,7 +105,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
if (groupTO.getADynMembershipCond() != null) {
setDynMembership(group, AnyTypeKind.ANY_OBJECT, groupTO.getADynMembershipCond());
}
- if (groupTO.getADynMembershipCond() != null) {
+ if (groupTO.getUDynMembershipCond() != null) {
setDynMembership(group, AnyTypeKind.USER, groupTO.getUDynMembershipCond());
}
@@ -188,7 +188,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
@Transactional(readOnly = true)
@Override
public GroupTO getGroupTO(final Group group) {
- connObjectUtils.retrieveVirAttrValues(group);
+ virAttrHander.retrieveVirAttrValues(group);
GroupTO groupTO = new GroupTO();
@@ -208,7 +208,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
groupTO.setGroupOwner(group.getGroupOwner().getKey());
}
- fillTO(groupTO, group.getRealm().getFullPath(),
+ fillTO(groupTO, group.getRealm().getFullPath(), group.getAuxClasses(),
group.getPlainAttrs(), group.getDerAttrs(), group.getVirAttrs(), group.getResources());
if (group.getADynMembership() != null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
index eec346e..0d7ee47 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
@@ -19,6 +19,8 @@
package org.apache.syncope.core.provisioning.java.data;
import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.core.provisioning.api.data.NotificationDataBinder;
import org.apache.syncope.common.lib.to.NotificationTO;
@@ -72,23 +74,35 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
@Override
public void update(final Notification notification, final NotificationTO notificationTO) {
BeanUtils.copyProperties(notificationTO, notification, IGNORE_PROPERTIES);
+ notification.setRecipients(notificationTO.getRecipients());
- notification.getAbouts().clear();
+ // 1. add or update all (valid) abouts from TO
for (Map.Entry<String, String> entry : notificationTO.getAbouts().entrySet()) {
if (StringUtils.isNotBlank(entry.getValue())) {
AnyType anyType = anyTypeDAO.find(entry.getKey());
if (anyType == null) {
- LOG.warn("Invalid AnyType {} specified, ignoring...", entry.getKey());
+ LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
} else {
- AnyAbout about = entityFactory.newEntity(AnyAbout.class);
- about.setAnyType(anyType);
- about.setNotification(notification);
-
- notification.add(about);
+ AnyAbout about = notification.getAbout(anyType);
+ if (about == null) {
+ about = entityFactory.newEntity(AnyAbout.class);
+ about.setAnyType(anyType);
+ about.setNotification(notification);
+
+ notification.add(about);
+ }
+ about.set(entry.getValue());
}
}
}
- notification.setRecipients(notificationTO.getRecipients());
+ // 2. remove all abouts not contained in the TO
+ CollectionUtils.filter(notification.getAbouts(), new Predicate<AnyAbout>() {
+
+ @Override
+ public boolean evaluate(final AnyAbout anyAbout) {
+ return notificationTO.getAbouts().containsKey(anyAbout.getAnyType().getKey());
+ }
+ });
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 20b3c58..cb8f979 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -22,6 +22,8 @@ import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.syncope.common.lib.SyncopeClientCompositeException;
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -89,8 +91,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
resource.setKey(resourceTO.getKey());
- if (resourceTO.getConnectorId() != null) {
- ConnInstance connector = connInstanceDAO.find(resourceTO.getConnectorId());
+ if (resourceTO.getConnector() != null) {
+ ConnInstance connector = connInstanceDAO.find(resourceTO.getConnector());
resource.setConnector(connector);
if (!connector.getResources().contains(resource)) {
@@ -108,10 +110,11 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
resource.setPropagationMode(resourceTO.getPropagationMode());
+ // 1. add or update all (valid) provisions from TO
for (ProvisionTO provisionTO : resourceTO.getProvisions()) {
AnyType anyType = anyTypeDAO.find(provisionTO.getAnyType());
if (anyType == null) {
- LOG.warn("Invalid type specified {}, ignoring...", provisionTO.getAnyType());
+ LOG.debug("Invalid AnyType specified {}, ignoring...", provisionTO.getAnyType());
} else {
Provision provision = resource.getProvision(anyType);
if (provision == null) {
@@ -135,14 +138,28 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
if (provisionTO.getMapping() == null) {
provision.setMapping(null);
} else {
- Mapping mapping = entityFactory.newEntity(Mapping.class);
- mapping.setProvision(provision);
- provision.setMapping(mapping);
+ Mapping mapping = provision.getMapping();
+ if (mapping == null) {
+ mapping = entityFactory.newEntity(Mapping.class);
+ mapping.setProvision(provision);
+ provision.setMapping(mapping);
+ } else {
+ mapping.getItems().clear();
+ }
populateMapping(provisionTO.getMapping(), mapping, entityFactory.newEntity(MappingItem.class));
}
}
}
+ // 2. remove all abouts not contained in the TO
+ CollectionUtils.filter(resource.getProvisions(), new Predicate<Provision>() {
+
+ @Override
+ public boolean evaluate(final Provision provision) {
+ return resourceTO.getProvision(provision.getAnyType().getKey()) != null;
+ }
+ });
+
resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
resource.setUpdateTraceLevel(resourceTO.getUpdateTraceLevel());
resource.setDeleteTraceLevel(resourceTO.getDeleteTraceLevel());
@@ -207,8 +224,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
}
}
- // Throw composite exception if there is at least one element set
- // in the composing exceptions
+ // Throw composite exception if there is at least one element set in the composing exceptions
if (!requiredValuesMissing.isEmpty()) {
scce.addException(requiredValuesMissing);
}
@@ -234,9 +250,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
@Override
public ConnInstance getConnInstance(final ResourceTO resourceTO) {
- ConnInstance connInstance = connInstanceDAO.find(resourceTO.getConnectorId());
+ ConnInstance connInstance = connInstanceDAO.find(resourceTO.getConnector());
if (connInstance == null) {
- throw new NotFoundException("Connector '" + resourceTO.getConnectorId() + "'");
+ throw new NotFoundException("Connector '" + resourceTO.getConnector() + "'");
}
final ConnInstance connInstanceClone = SerializationUtils.clone(connInstance);
@@ -279,7 +295,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
// set the connector instance
ConnInstance connector = resource.getConnector();
- resourceTO.setConnectorId(connector == null ? null : connector.getKey());
+ resourceTO.setConnector(connector == null ? null : connector.getKey());
resourceTO.setConnectorDisplayName(connector == null ? null : connector.getDisplayName());
// set the provision information
@@ -295,6 +311,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
provisionTO.setMapping(mappingTO);
populateMappingTO(provision.getMapping(), mappingTO);
}
+
+ resourceTO.getProvisions().add(provisionTO);
}
resourceTO.setEnforceMandatoryCondition(resource.isEnforceMandatoryCondition());
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
index b286043..124bb7f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
@@ -84,7 +84,7 @@ public class RoleDataBinderImpl implements RoleDataBinder {
for (String realmFullPath : roleTO.getRealms()) {
Realm realm = realmDAO.find(realmFullPath);
if (realm == null) {
- LOG.warn("Invalid realm full path {}, ignoring", realmFullPath);
+ LOG.debug("Invalid realm full path {}, ignoring", realmFullPath);
} else {
role.addRealm(realm);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
index e44198b..f20a265 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
@@ -70,7 +70,7 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
boolean hasAttrs = false;
for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
- hasAttrs &= schemaDAO.findAttrs(schema, anyUtils.plainAttrClass()).isEmpty();
+ hasAttrs |= schemaDAO.findAttrs(schema, anyUtils.plainAttrClass()).isEmpty();
}
if (hasAttrs) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index c25b3ed..762cca5 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -19,6 +19,8 @@
package org.apache.syncope.core.provisioning.java.data;
import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.syncope.core.provisioning.api.data.TaskDataBinder;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -72,13 +74,10 @@ import org.springframework.stereotype.Component;
@Component
public class TaskDataBinderImpl implements TaskDataBinder {
- /**
- * Logger.
- */
private static final Logger LOG = LoggerFactory.getLogger(TaskDataBinder.class);
private static final String[] IGNORE_TASK_PROPERTIES = {
- "destinationRealm", "executions", "resource", "matchingRule", "unmatchingRule" };
+ "destinationRealm", "templates", "filters", "executions", "resource", "matchingRule", "unmatchingRule" };
private static final String[] IGNORE_TASK_EXECUTION_PROPERTIES = { "key", "task" };
@@ -100,40 +99,82 @@ public class TaskDataBinderImpl implements TaskDataBinder {
@Autowired
private SchedulerFactoryBean scheduler;
- private void checkJexl(final AnyTO anyTO, final SyncopeClientException sce) {
- for (AttrTO attrTO : anyTO.getPlainAttrs()) {
- if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
- sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ private void checkTemplateJEXL(final SyncTaskTO syncTaskTO) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSyncTask);
+
+ for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
+ for (AttrTO attrTO : entry.getValue().getPlainAttrs()) {
+ if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
+ sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ }
+ }
+
+ for (AttrTO attrTO : entry.getValue().getVirAttrs()) {
+ if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
+ sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ }
}
- }
- for (AttrTO attrTO : anyTO.getVirAttrs()) {
- if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
- sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ if (entry.getValue() instanceof UserTO) {
+ UserTO template = (UserTO) entry.getValue();
+ if (StringUtils.isNotBlank(template.getUsername())
+ && !JexlUtils.isExpressionValid(template.getUsername())) {
+
+ sce.getElements().add("Invalid JEXL: " + template.getUsername());
+ }
+ if (StringUtils.isNotBlank(template.getPassword())
+ && !JexlUtils.isExpressionValid(template.getPassword())) {
+
+ sce.getElements().add("Invalid JEXL: " + template.getPassword());
+ }
+ } else if (entry.getValue() instanceof GroupTO) {
+ GroupTO template = (GroupTO) entry.getValue();
+ if (StringUtils.isNotBlank(template.getName())
+ && !JexlUtils.isExpressionValid(template.getName())) {
+
+ sce.getElements().add("Invalid JEXL: " + template.getName());
+ }
}
}
+
+ if (!sce.isEmpty()) {
+ throw sce;
+ }
}
private void fill(final ProvisioningTask task, final AbstractProvisioningTaskTO taskTO) {
if (task instanceof PushTask && taskTO instanceof PushTaskTO) {
- PushTask pushTask = (PushTask) task;
- PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
-
- for (Map.Entry<String, String> entry : pushTaskTO.getFilters().entrySet()) {
- AnyFilter filter = entityFactory.newEntity(AnyFilter.class);
- filter.setAnyType(anyTypeDAO.find(entry.getKey()));
- filter.set(entry.getValue());
-
- filter.setPushTask(pushTask);
- pushTask.add(filter);
- }
+ final PushTask pushTask = (PushTask) task;
+ final PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
pushTask.setMatchingRule(pushTaskTO.getMatchingRule() == null
? MatchingRule.LINK : pushTaskTO.getMatchingRule());
-
pushTask.setUnmatchingRule(pushTaskTO.getUnmatchingRule() == null
? UnmatchingRule.ASSIGN : pushTaskTO.getUnmatchingRule());
+ for (Map.Entry<String, String> entry : pushTaskTO.getFilters().entrySet()) {
+ AnyType type = anyTypeDAO.find(entry.getKey());
+ if (type == null) {
+ LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
+ } else {
+ AnyFilter filter = pushTask.getFilter(type);
+ if (filter == null) {
+ filter = entityFactory.newEntity(AnyFilter.class);
+ filter.setAnyType(anyTypeDAO.find(entry.getKey()));
+ filter.setPushTask(pushTask);
+ pushTask.add(filter);
+ }
+ filter.set(entry.getValue());
+ }
+ }
+ // remove all filters not contained in the TO
+ CollectionUtils.filter(pushTask.getFilters(), new Predicate<AnyFilter>() {
+
+ @Override
+ public boolean evaluate(final AnyFilter anyFilter) {
+ return pushTaskTO.getFilters().containsKey(anyFilter.getAnyType().getKey());
+ }
+ });
} else if (task instanceof SyncTask && taskTO instanceof SyncTaskTO) {
final SyncTask syncTask = (SyncTask) task;
final SyncTaskTO syncTaskTO = (SyncTaskTO) taskTO;
@@ -142,52 +183,35 @@ public class TaskDataBinderImpl implements TaskDataBinder {
syncTask.setMatchingRule(syncTaskTO.getMatchingRule() == null
? MatchingRule.UPDATE : syncTaskTO.getMatchingRule());
-
syncTask.setUnmatchingRule(syncTaskTO.getUnmatchingRule() == null
? UnmatchingRule.PROVISION : syncTaskTO.getUnmatchingRule());
- SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSyncTask);
- // 1. validate JEXL expressions in user and group templates
+ // validate JEXL expressions from templates and proceed if fine
+ checkTemplateJEXL(syncTaskTO);
for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
- checkJexl(entry.getValue(), sce);
-
- if (entry.getValue() instanceof UserTO) {
- UserTO template = (UserTO) entry.getValue();
- if (StringUtils.isNotBlank(template.getUsername())
- && !JexlUtils.isExpressionValid(template.getUsername())) {
-
- sce.getElements().add("Invalid JEXL: " + template.getUsername());
- }
- if (StringUtils.isNotBlank(template.getPassword())
- && !JexlUtils.isExpressionValid(template.getPassword())) {
-
- sce.getElements().add("Invalid JEXL: " + template.getPassword());
- }
- } else if (entry.getValue() instanceof GroupTO) {
- GroupTO template = (GroupTO) entry.getValue();
- if (StringUtils.isNotBlank(template.getName())
- && !JexlUtils.isExpressionValid(template.getName())) {
-
- sce.getElements().add("Invalid JEXL: " + template.getName());
+ AnyType type = anyTypeDAO.find(entry.getKey());
+ if (type == null) {
+ LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
+ } else {
+ AnyTemplate anyTemplate = syncTask.getTemplate(type);
+ if (anyTemplate == null) {
+ anyTemplate = entityFactory.newEntity(AnyTemplate.class);
+ anyTemplate.setAnyType(type);
+ anyTemplate.setSyncTask(syncTask);
+
+ syncTask.add(anyTemplate);
}
+ anyTemplate.set(entry.getValue());
}
}
- if (!sce.isEmpty()) {
- throw sce;
- }
+ // remove all templates not contained in the TO
+ CollectionUtils.filter(syncTask.getTemplates(), new Predicate<AnyTemplate>() {
- // 2. all JEXL expressions are valid: accept user and group templates
- for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
- AnyType type = anyTypeDAO.find(entry.getKey());
- if (type != null) {
- AnyTemplate anyTemplate = entityFactory.newEntity(AnyTemplate.class);
- anyTemplate.setAnyType(type);
- anyTemplate.set(entry.getValue());
- anyTemplate.setSyncTask(syncTask);
-
- syncTask.add(anyTemplate);
+ @Override
+ public boolean evaluate(final AnyTemplate anyTemplate) {
+ return syncTaskTO.getTemplates().containsKey(anyTemplate.getAnyType().getKey());
}
- }
+ });
syncTask.setFullReconciliation(syncTaskTO.isFullReconciliation());
}
@@ -197,18 +221,13 @@ public class TaskDataBinderImpl implements TaskDataBinder {
task.setPerformUpdate(taskTO.isPerformUpdate());
task.setPerformDelete(taskTO.isPerformDelete());
task.setSyncStatus(taskTO.isSyncStatus());
- task.getActionsClassNames()
- .clear();
- task.getActionsClassNames()
- .addAll(taskTO.getActionsClassNames());
+ task.getActionsClassNames().clear();
+ task.getActionsClassNames().addAll(taskTO.getActionsClassNames());
}
@Override
- public SchedTask createSchedTask(final SchedTaskTO taskTO,
- final TaskUtils taskUtils
- ) {
- final Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
-
+ public SchedTask createSchedTask(final SchedTaskTO taskTO, final TaskUtils taskUtils) {
+ Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
if (taskTOClass == null || !taskTOClass.equals(taskTO.getClass())) {
throw new IllegalArgumentException(
String.format("taskUtils is type %s but task is not: %s", taskTOClass, taskTO.getClass()));
@@ -222,7 +241,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
if (taskUtils.getType() == TaskType.SCHEDULED) {
task.setJobClassName(taskTO.getJobClassName());
} else if (taskTO instanceof AbstractProvisioningTaskTO) {
- final AbstractProvisioningTaskTO provisioningTaskTO = (AbstractProvisioningTaskTO) taskTO;
+ AbstractProvisioningTaskTO provisioningTaskTO = (AbstractProvisioningTaskTO) taskTO;
ExternalResource resource = resourceDAO.find(provisioningTaskTO.getResource());
if (resource == null) {
@@ -237,10 +256,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
}
@Override
- public void updateSchedTask(final SchedTask task,
- final SchedTaskTO taskTO,
- final TaskUtils taskUtils
- ) {
+ public void updateSchedTask(final SchedTask task, final SchedTaskTO taskTO, final TaskUtils taskUtils) {
Class<? extends Task> taskClass = taskUtils.taskClass();
Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
@@ -268,8 +284,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
}
@Override
- public TaskExecTO getTaskExecTO(final TaskExec execution
- ) {
+ public TaskExecTO getTaskExecTO(final TaskExec execution) {
TaskExecTO executionTO = new TaskExecTO();
BeanUtils.copyProperties(execution, executionTO, IGNORE_TASK_EXECUTION_PROPERTIES);
@@ -347,6 +362,10 @@ public class TaskDataBinderImpl implements TaskDataBinder {
? MatchingRule.UPDATE : ((SyncTask) task).getMatchingRule());
((SyncTaskTO) taskTO).setUnmatchingRule(((SyncTask) task).getUnmatchingRule() == null
? UnmatchingRule.PROVISION : ((SyncTask) task).getUnmatchingRule());
+
+ for (AnyTemplate template : ((SyncTask) task).getTemplates()) {
+ ((SyncTaskTO) taskTO).getTemplates().put(template.getAnyType().getKey(), template.get());
+ }
break;
case PUSH:
@@ -362,6 +381,10 @@ public class TaskDataBinderImpl implements TaskDataBinder {
? MatchingRule.LINK : ((PushTask) task).getMatchingRule());
((PushTaskTO) taskTO).setUnmatchingRule(((PushTask) task).getUnmatchingRule() == null
? UnmatchingRule.ASSIGN : ((PushTask) task).getUnmatchingRule());
+
+ for (AnyFilter filter : ((PushTask) task).getFilters()) {
+ ((PushTaskTO) taskTO).getFilters().put(filter.getAnyType().getKey(), filter.get());
+ }
break;
case NOTIFICATION:
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 54d10bc..6c5e0d6 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -32,6 +32,7 @@ import org.apache.syncope.common.lib.SyncopeClientCompositeException;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -49,7 +50,9 @@ import org.apache.syncope.core.misc.security.Encryptor;
import org.apache.syncope.core.misc.spring.BeanUtils;
import org.apache.syncope.core.persistence.api.dao.RoleDAO;
import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.URelationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -58,9 +61,9 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(rollbackFor = { Throwable.class })
public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDataBinder {
- private static final String[] IGNORE_USER_PROPERTIES = {
- "realm", "roles", "memberships", "plainAttrs", "derAttrs", "virAttrs", "resources",
- "securityQuestion", "securityAnswer"
+ private static final String[] IGNORE_PROPERTIES = {
+ "type", "realm", "auxClasses", "roles", "dynRoles", "relationships", "memberships", "dynGroups",
+ "plainAttrs", "derAttrs", "virAttrs", "resources", "securityQuestion", "securityAnswer"
};
@Autowired
@@ -144,6 +147,29 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
}
}
+ // relationships
+ for (RelationshipTO relationshipTO : userTO.getRelationships()) {
+ AnyObject anyObject = anyObjectDAO.find(relationshipTO.getRightKey());
+
+ if (anyObject == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Ignoring invalid anyObject " + relationshipTO.getRightKey());
+ }
+ } else {
+ URelationship relationship = null;
+ if (user.getKey() != null) {
+ relationship = user.getRelationship(anyObject.getKey());
+ }
+ if (relationship == null) {
+ relationship = entityFactory.newEntity(URelationship.class);
+ relationship.setRightEnd(anyObject);
+ relationship.setLeftEnd(user);
+
+ user.add(relationship);
+ }
+ }
+ }
+
// memberships
for (MembershipTO membershipTO : userTO.getMemberships()) {
Group group = groupDAO.find(membershipTO.getRightKey());
@@ -266,11 +292,44 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
// attributes, derived attributes, virtual attributes and resources
propByRes.merge(fill(user, userMod, anyUtilsFactory.getInstance(AnyTypeKind.USER), scce));
- // store the group ids of membership required to be added
- Set<Long> membershipToBeAddedGroupKeys = new HashSet<>(userMod.getMembershipsToAdd());
+ Set<String> toBeDeprovisioned = new HashSet<>();
+ Set<String> toBeProvisioned = new HashSet<>();
+
+ // relationships to be removed
+ for (Long anyObjectKey : userMod.getRelationshipsToRemove()) {
+ LOG.debug("Relationship to be removed for any object {}", anyObjectKey);
+
+ URelationship relationship = user.getRelationship(anyObjectKey);
+ if (relationship == null) {
+ LOG.warn("Invalid anyObject key specified for relationship to be removed: {}", anyObjectKey);
+ } else {
+ if (!userMod.getRelationshipsToAdd().contains(anyObjectKey)) {
+ user.remove(relationship);
+ toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+ }
+ }
+ }
+
+ // relationships to be added
+ for (Long anyObjectKey : userMod.getRelationshipsToAdd()) {
+ LOG.debug("Relationship to be added for any object {}", anyObjectKey);
+
+ AnyObject otherEnd = anyObjectDAO.find(anyObjectKey);
+ if (otherEnd == null) {
+ LOG.debug("Ignoring invalid any object {}", anyObjectKey);
+ } else {
+ URelationship relationship = user.getRelationship(otherEnd.getKey());
+ if (relationship == null) {
+ relationship = entityFactory.newEntity(URelationship.class);
+ relationship.setRightEnd(otherEnd);
+ relationship.setLeftEnd(user);
+
+ user.add(relationship);
- final Set<String> toBeDeprovisioned = new HashSet<>();
- final Set<String> toBeProvisioned = new HashSet<>();
+ toBeProvisioned.addAll(otherEnd.getResourceNames());
+ }
+ }
+ }
// memberships to be removed
for (Long groupKey : userMod.getMembershipsToRemove()) {
@@ -278,11 +337,10 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
UMembership membership = user.getMembership(groupKey);
if (membership == null) {
- LOG.warn("Invalid group key specified for membership to be removed: {}", groupKey);
+ LOG.debug("Invalid group key specified for membership to be removed: {}", groupKey);
} else {
- if (membershipToBeAddedGroupKeys.contains(membership.getRightEnd().getKey())) {
+ if (!userMod.getMembershipsToAdd().contains(groupKey)) {
user.remove(membership);
- } else {
toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
}
}
@@ -312,10 +370,8 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
propByRes.addAll(ResourceOperation.DELETE, toBeDeprovisioned);
propByRes.addAll(ResourceOperation.UPDATE, toBeProvisioned);
- /**
- * In case of new memberships all the current resources have to be updated in order to propagate new group and
- * membership attribute values.
- */
+ // In case of new memberships all current resources need to be updated in order to propagate new group
+ // attribute values.
if (!toBeDeprovisioned.isEmpty() || !toBeProvisioned.isEmpty()) {
currentResources.removeAll(toBeDeprovisioned);
propByRes.addAll(ResourceOperation.UPDATE, currentResources);
@@ -340,25 +396,43 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
public UserTO getUserTO(final User user) {
UserTO userTO = new UserTO();
- BeanUtils.copyProperties(user, userTO, IGNORE_USER_PROPERTIES);
+ BeanUtils.copyProperties(user, userTO, IGNORE_PROPERTIES);
if (user.getSecurityQuestion() != null) {
userTO.setSecurityQuestion(user.getSecurityQuestion().getKey());
}
- connObjectUtils.retrieveVirAttrValues(user);
- fillTO(userTO, user.getRealm().getFullPath(),
+ virAttrHander.retrieveVirAttrValues(user);
+ fillTO(userTO, user.getRealm().getFullPath(), user.getAuxClasses(),
user.getPlainAttrs(), user.getDerAttrs(), user.getVirAttrs(), userDAO.findAllResources(user));
- for (UMembership membership : user.getMemberships()) {
- MembershipTO membershipTO = new MembershipTO();
+ // roles
+ CollectionUtils.collect(user.getRoles(), new Transformer<Role, Long>() {
+
+ @Override
+ public Long transform(final Role role) {
+ return role.getKey();
+ }
+ }, userTO.getRoles());
+
+ // relationships
+ CollectionUtils.collect(user.getRelationships(), new Transformer<URelationship, RelationshipTO>() {
- membershipTO.setKey(membership.getKey());
- membershipTO.setRightKey(membership.getRightEnd().getKey());
- membershipTO.setGroupName(membership.getRightEnd().getName());
+ @Override
+ public RelationshipTO transform(final URelationship relationship) {
+ return UserDataBinderImpl.this.getRelationshipTO(relationship);
+ }
- userTO.getMemberships().add(membershipTO);
- }
+ }, userTO.getRelationships());
+
+ // memberships
+ CollectionUtils.collect(user.getMemberships(), new Transformer<UMembership, MembershipTO>() {
+
+ @Override
+ public MembershipTO transform(final UMembership membership) {
+ return UserDataBinderImpl.this.getMembershipTO(membership);
+ }
+ }, userTO.getMemberships());
// dynamic memberships
CollectionUtils.collect(userDAO.findDynRoleMemberships(user), new Transformer<Role, Long>() {
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index a0469a2..cdc540c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -54,14 +54,13 @@ import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
-import org.apache.syncope.core.misc.ConnObjectUtils;
import org.apache.syncope.core.misc.search.SearchCondConverter;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyAbout;
import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
@@ -143,7 +142,7 @@ public class NotificationManagerImpl implements NotificationManager {
private ToolManager velocityToolManager;
@Autowired
- private ConnObjectUtils connObjectUtils;
+ private VirAttrHandler virAttrHander;
@Autowired
private UserDataBinder userDataBinder;
@@ -154,9 +153,6 @@ public class NotificationManagerImpl implements NotificationManager {
@Autowired
private EntityFactory entityFactory;
- @Autowired
- private AnyUtilsFactory anyUtilsFactory;
-
@Transactional(readOnly = true)
@Override
public long getMaxRetries() {
@@ -177,10 +173,10 @@ public class NotificationManagerImpl implements NotificationManager {
final Map<String, Object> model) {
if (any != null) {
- connObjectUtils.retrieveVirAttrValues(any);
+ virAttrHander.retrieveVirAttrValues(any);
}
- final List<User> recipients = new ArrayList<>();
+ List<User> recipients = new ArrayList<>();
if (notification.getRecipients() != null) {
recipients.addAll(searchDAO.<User>search(SyncopeConstants.FULL_ADMIN_REALMS,
@@ -192,10 +188,10 @@ public class NotificationManagerImpl implements NotificationManager {
recipients.add((User) any);
}
- final Set<String> recipientEmails = new HashSet<>();
- final List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
+ Set<String> recipientEmails = new HashSet<>();
+ List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
for (User recipient : recipients) {
- connObjectUtils.retrieveVirAttrValues(recipient);
+ virAttrHander.retrieveVirAttrValues(recipient);
String email = getRecipientEmail(notification.getRecipientAttrType(),
notification.getRecipientAttrName(), recipient);