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);
