Author: ilgrosso Date: Thu Jan 3 16:29:00 2013 New Revision: 1428455 URL: http://svn.apache.org/viewvc?rev=1428455&view=rev Log: [SYNCOPE-260] Alternative, less intrusive fix
Removed: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/Attributable.java Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttr.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/user/UAttr.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/util/SchemaMappingUtil.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/ActivitiUserWorkflowAdapter.java syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/NoOpUserWorkflowAdapter.java Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttr.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttr.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttr.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttr.java Thu Jan 3 16:29:00 2013 @@ -74,13 +74,13 @@ public abstract class AbstractAttr exten public List<String> getValuesAsStrings() { List<String> result; - if (getUniqueValue() != null) { - result = Collections.singletonList(getUniqueValue().getValueAsString()); - } else { + if (getUniqueValue() == null) { result = new ArrayList<String>(getValues().size()); for (AbstractAttrValue attributeValue : getValues()) { result.add(attributeValue.getValueAsString()); } + } else { + result = Collections.singletonList(getUniqueValue().getValueAsString()); } return result; Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/AbstractAttributable.java Thu Jan 3 16:29:00 2013 @@ -21,10 +21,11 @@ package org.apache.syncope.core.persiste import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; -public abstract class AbstractAttributable extends AbstractBaseBean implements Attributable { +public abstract class AbstractAttributable extends AbstractBaseBean { private static final long serialVersionUID = -4801685541488201119L; @@ -41,13 +42,11 @@ public abstract class AbstractAttributab } public <T extends AbstractDerAttr> T getDerivedAttribute(final String derivedSchemaName) { - T result = null; - T derivedAttribute; - for (Iterator<? extends AbstractDerAttr> itor = getDerivedAttributes().iterator(); result == null - && itor.hasNext();) { + for (Iterator<? extends AbstractDerAttr> itor = getDerivedAttributes().iterator(); + result == null && itor.hasNext();) { - derivedAttribute = (T) itor.next(); + T derivedAttribute = (T) itor.next(); if (derivedAttribute.getDerivedSchema() != null && derivedSchemaName.equals(derivedAttribute.getDerivedSchema().getName())) { @@ -59,14 +58,11 @@ public abstract class AbstractAttributab } public <T extends AbstractVirAttr> T getVirtualAttribute(final String virtualSchemaName) { - T result = null; - T virtualAttribute; - for (Iterator<? extends AbstractVirAttr> itor = getVirtualAttributes().iterator(); result == null - && itor.hasNext();) { - - virtualAttribute = (T) itor.next(); + for (Iterator<? extends AbstractVirAttr> itor = getVirtualAttributes().iterator(); + result == null && itor.hasNext();) { + T virtualAttribute = (T) itor.next(); if (virtualAttribute.getVirtualSchema() != null && virtualSchemaName.equals(virtualAttribute.getVirtualSchema().getName())) { @@ -81,7 +77,7 @@ public abstract class AbstractAttributab final Map<AbstractSchema, AbstractAttr> map = new HashMap<AbstractSchema, AbstractAttr>(); for (AbstractAttr attr : getAttributes()) { - map.put((AbstractSchema) attr.getSchema(), attr); + map.put(attr.getSchema(), attr); } return map; @@ -91,7 +87,7 @@ public abstract class AbstractAttributab final Map<AbstractDerSchema, AbstractDerAttr> map = new HashMap<AbstractDerSchema, AbstractDerAttr>(); for (AbstractDerAttr attr : getDerivedAttributes()) { - map.put((AbstractDerSchema) attr.getDerivedSchema(), attr); + map.put(attr.getDerivedSchema(), attr); } return map; @@ -101,12 +97,38 @@ public abstract class AbstractAttributab final Map<AbstractVirSchema, AbstractVirAttr> map = new HashMap<AbstractVirSchema, AbstractVirAttr>(); for (AbstractVirAttr attr : getVirtualAttributes()) { - map.put((AbstractVirSchema) attr.getVirtualSchema(), attr); + map.put(attr.getVirtualSchema(), attr); } return map; } + public abstract Long getId(); + + public abstract <T extends AbstractAttr> boolean addAttribute(T attribute); + + public abstract <T extends AbstractAttr> boolean removeAttribute(T attribute); + + public abstract List<? extends AbstractAttr> getAttributes(); + + public abstract void setAttributes(List<? extends AbstractAttr> attributes); + + public abstract <T extends AbstractDerAttr> boolean addDerivedAttribute(T derivedAttribute); + + public abstract <T extends AbstractDerAttr> boolean removeDerivedAttribute(T derivedAttribute); + + public abstract List<? extends AbstractDerAttr> getDerivedAttributes(); + + public abstract void setDerivedAttributes(List<? extends AbstractDerAttr> derivedAttributes); + + public abstract <T extends AbstractVirAttr> boolean addVirtualAttribute(T virtualAttributes); + + public abstract <T extends AbstractVirAttr> boolean removeVirtualAttribute(T virtualAttribute); + + public abstract List<? extends AbstractVirAttr> getVirtualAttributes(); + + public abstract void setVirtualAttributes(List<? extends AbstractVirAttr> virtualAttributes); + protected abstract Set<ExternalResource> resources(); public boolean addResource(final ExternalResource resource) { Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/user/UAttr.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/user/UAttr.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/user/UAttr.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/persistence/beans/user/UAttr.java Thu Jan 3 16:29:00 2013 @@ -29,9 +29,9 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.validation.Valid; -import org.apache.syncope.core.persistence.beans.AbstractAttributable; import org.apache.syncope.core.persistence.beans.AbstractAttr; import org.apache.syncope.core.persistence.beans.AbstractAttrValue; +import org.apache.syncope.core.persistence.beans.AbstractAttributable; import org.apache.syncope.core.persistence.beans.AbstractSchema; /** Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java Thu Jan 3 16:29:00 2013 @@ -18,12 +18,10 @@ */ package org.apache.syncope.core.policy; +import java.util.AbstractMap.SimpleEntry; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import org.apache.syncope.client.to.UserTO; import org.apache.syncope.core.persistence.beans.PropagationTask; import org.apache.syncope.core.persistence.beans.user.SyncopeUser; @@ -33,6 +31,8 @@ import org.apache.syncope.core.workflow. import org.apache.syncope.core.workflow.WorkflowResult; import org.apache.syncope.types.AccountPolicySpec; import org.apache.syncope.types.PolicyType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; @Component public class AccountPolicyEnforcer extends PolicyEnforcer<AccountPolicySpec, SyncopeUser> { @@ -117,8 +117,9 @@ public class AccountPolicyEnforcer exten // propagate suspension if and only if it is required by policy if (policy.isPropagateSuspension()) { final List<PropagationTask> tasks = propagationManager - .getUpdateTaskIds(new WorkflowResult<Map.Entry<Long, Boolean>>(new DefaultMapEntry(updated - .getResult(), Boolean.FALSE), updated.getPropByRes(), updated.getPerformedTasks())); + .getUpdateTaskIds(new WorkflowResult<Map.Entry<Long, Boolean>>( + new SimpleEntry<Long, Boolean>(updated.getResult(), Boolean.FALSE), + updated.getPropByRes(), updated.getPerformedTasks())); propagationManager.execute(tasks); } Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java Thu Jan 3 16:29:00 2013 @@ -19,11 +19,8 @@ package org.apache.syncope.core.propagation; import java.io.PrintWriter; -import java.io.Serializable; import java.io.StringWriter; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -31,17 +28,14 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import javassist.NotFoundException; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; import org.apache.syncope.client.mod.AttributeMod; import org.apache.syncope.client.to.AttributeTO; import org.apache.syncope.core.init.ConnInstanceLoader; import org.apache.syncope.core.persistence.beans.AbstractAttrValue; +import org.apache.syncope.core.persistence.beans.AbstractAttributable; import org.apache.syncope.core.persistence.beans.AbstractSchema; -import org.apache.syncope.core.persistence.beans.AbstractVirAttr; -import org.apache.syncope.core.persistence.beans.Attributable; import org.apache.syncope.core.persistence.beans.ExternalResource; import org.apache.syncope.core.persistence.beans.PropagationTask; import org.apache.syncope.core.persistence.beans.SchemaMapping; @@ -181,14 +175,14 @@ public class PropagationManager { final PropagationByResource propByRes = wfResult.getPropByRes(); if (propByRes == null || propByRes.isEmpty()) { - return Collections.emptyList(); + return Collections.<PropagationTask>emptyList(); } if (syncResourceNames != null) { propByRes.get(PropagationOperation.CREATE).removeAll(syncResourceNames); } - return provision(user, password, wfResult.getResult().getValue(), false, propByRes); + return provision(user, password, null, null, wfResult.getResult().getValue(), false, propByRes); } /** @@ -263,8 +257,8 @@ public class PropagationManager { SyncopeUser user = getSyncopeUser(wfResult.getResult().getKey()); - return getUpdateTaskIds(user, wfResult.getPropByRes(), password, vAttrsToBeRemoved, vAttrsToBeUpdated, wfResult. - getResult().getValue(), syncResourceNames); + return getUpdateTaskIds(user, wfResult.getPropByRes(), password, vAttrsToBeRemoved, vAttrsToBeUpdated, + wfResult.getResult().getValue(), syncResourceNames); } private List<PropagationTask> getUpdateTaskIds(final SyncopeUser user, final PropagationByResource propByRes, @@ -273,15 +267,15 @@ public class PropagationManager { throws NotFoundException { PropagationByResource localPropByRes = userDataBinder.fillVirtual(user, vAttrsToBeRemoved == null - ? Collections.EMPTY_SET + ? Collections.<String>emptySet() : vAttrsToBeRemoved, vAttrsToBeUpdated == null - ? Collections.EMPTY_SET + ? Collections.<AttributeMod>emptySet() : vAttrsToBeUpdated, AttributableUtil.getInstance(AttributableType.USER)); - if (propByRes != null && !propByRes.isEmpty()) { - localPropByRes.merge(propByRes); - } else { + if (propByRes == null || propByRes.isEmpty()) { localPropByRes.addAll(PropagationOperation.UPDATE, user.getResourceNames()); + } else { + localPropByRes.merge(propByRes); } if (syncResourceNames != null) { @@ -290,15 +284,15 @@ public class PropagationManager { localPropByRes.get(PropagationOperation.DELETE).removeAll(syncResourceNames); } - // Provide a proxy handler in order to take into consideration all the info about virtual attributes to - // be removed/updated as well. - - final Attributable handleObject = (Attributable) Proxy.newProxyInstance( - Attributable.class.getClassLoader(), - new Class<?>[]{Attributable.class, Serializable.class}, - new AttributableHandler(user, vAttrsToBeRemoved, vAttrsToBeUpdated)); + Map<String, AttributeMod> vAttrsToBeUpdatedMap = null; + if (vAttrsToBeUpdated != null) { + vAttrsToBeUpdatedMap = new HashMap<String, AttributeMod>(); + for (AttributeMod attrMod : vAttrsToBeUpdated) { + vAttrsToBeUpdatedMap.put(attrMod.getSchema(), attrMod); + } + } - return provision(handleObject, password, enable, false, localPropByRes); + return provision(user, password, vAttrsToBeRemoved, vAttrsToBeUpdatedMap, enable, false, localPropByRes); } /** @@ -337,7 +331,7 @@ public class PropagationManager { propByRes.get(PropagationOperation.DELETE).remove(syncResourceName); } - return provision(user, null, false, true, propByRes); + return provision(user, null, null, null, false, true, propByRes); } /** @@ -349,47 +343,52 @@ public class PropagationManager { * @return account link + prepare attributes * @throws ClassNotFoundException if schema type for given mapping does not exists in current class loader */ - private Map.Entry<String, Attribute> prepareAttribute( - final SchemaMapping mapping, final Attributable user, final String password) - throws ClassNotFoundException { - - // Retrieve attributable ... - final Attributable attributable = user instanceof Proxy - ? ((AttributableHandler) Proxy.getInvocationHandler(user)).getObject() - : user; + private Map.Entry<String, Attribute> prepareAttribute(final SchemaMapping mapping, final SyncopeUser user, + final String password, final Set<String> vAttrsToBeRemoved, + final Map<String, AttributeMod> vAttrsToBeUpdated) throws ClassNotFoundException { - final List<Attributable> attributables = new ArrayList<Attributable>(); + final List<AbstractAttributable> attributables = new ArrayList<AbstractAttributable>(); switch (mapping.getIntMappingType().getAttributableType()) { case USER: attributables.addAll(Collections.singleton(user)); break; case ROLE: - final List<Membership> memberships = ((SyncopeUser) attributable).getMemberships(); + final List<Membership> memberships = user.getMemberships(); for (Membership membership : memberships) { attributables.add(membership.getSyncopeRole()); } break; case MEMBERSHIP: - attributables.addAll(((SyncopeUser) attributable).getMemberships()); + attributables.addAll(user.getMemberships()); break; default: } - final Entry<AbstractSchema, List<AbstractAttrValue>> entry = - SchemaMappingUtil.getIntValues(mapping, attributables, password, schemaDAO); + final List<AbstractAttrValue> values = + SchemaMappingUtil.getIntValues(mapping, attributables, password, vAttrsToBeRemoved, vAttrsToBeUpdated); - final List<AbstractAttrValue> values = entry.getValue(); - final AbstractSchema schema = entry.getKey(); - final SchemaType schemaType = schema == null ? SchemaType.String : schema.getType(); + AbstractSchema schema = null; + final SchemaType schemaType; + switch (mapping.getIntMappingType()) { + case UserSchema: + case RoleSchema: + case MembershipSchema: + schema = schemaDAO.find(mapping.getIntAttrName(), + SchemaMappingUtil.getIntMappingTypeClass(mapping.getIntMappingType())); + schemaType = schema == null ? SchemaType.String : schema.getType(); + break; + + default: + schemaType = SchemaType.String; + } final String extAttrName = SchemaMappingUtil.getExtAttrName(mapping); LOG.debug("Define mapping for: " + "\n* ExtAttrName " + extAttrName + "\n* is accountId " + mapping.isAccountid() - + "\n* is password " + (mapping.isPassword() || mapping.getIntMappingType().equals( - IntMappingType.Password)) + + "\n* is password " + (mapping.isPassword() || mapping.getIntMappingType() == IntMappingType.Password) + "\n* mandatory condition " + mapping.getMandatoryCondition() + "\n* Schema " + mapping.getIntAttrName() + "\n* IntMappingType " + mapping.getIntMappingType().toString() @@ -406,24 +405,25 @@ public class PropagationManager { } } - Map.Entry<String, Attribute> res; + Map.Entry<String, Attribute> result; if (mapping.isAccountid()) { - res = new DefaultMapEntry(objValues.iterator().next().toString(), null); + result = new SimpleEntry<String, Attribute>(objValues.iterator().next().toString(), null); } else if (mapping.isPassword()) { - res = new DefaultMapEntry(null, + result = new SimpleEntry<String, Attribute>(null, AttributeBuilder.buildPassword(objValues.iterator().next().toString().toCharArray())); } else { if (schema != null && schema.isMultivalue()) { - res = new DefaultMapEntry(null, AttributeBuilder.build(extAttrName, objValues)); + result = new SimpleEntry<String, Attribute>(null, + AttributeBuilder.build(extAttrName, objValues)); } else { - res = new DefaultMapEntry(null, objValues.isEmpty() + result = new SimpleEntry<String, Attribute>(null, objValues.isEmpty() ? AttributeBuilder.build(extAttrName) : AttributeBuilder.build(extAttrName, objValues.iterator().next())); } } - return res; + return result; } /** @@ -435,16 +435,12 @@ public class PropagationManager { * @param resource target resource * @return account link + prepared attributes */ - private Map.Entry<String, Set<Attribute>> prepareAttributes(final Attributable user, final String password, + private Map.Entry<String, Set<Attribute>> prepareAttributes(final SyncopeUser user, final String password, + final Set<String> vAttrsToBeRemoved, final Map<String, AttributeMod> vAttrsToBeUpdated, final Boolean enable, final ExternalResource resource) { - // Retrieve attributable ... - final Attributable attributable = user instanceof Proxy - ? ((AttributableHandler) Proxy.getInvocationHandler(user)).getObject() - : user; - LOG.debug("Preparing resource attributes for {} on resource {} with attributes {}", - new Object[]{attributable, resource, attributable.getAttributes()}); + new Object[]{user, resource, user.getAttributes()}); Set<Attribute> attributes = new HashSet<Attribute>(); String accountId = null; @@ -454,15 +450,15 @@ public class PropagationManager { LOG.debug("Processing schema {}", SchemaMappingUtil.getIntAttrName(mapping)); try { - preparedAttribute = prepareAttribute(mapping, user, password); + preparedAttribute = prepareAttribute(mapping, user, password, vAttrsToBeRemoved, vAttrsToBeUpdated); if (preparedAttribute.getKey() != null) { accountId = preparedAttribute.getKey(); } if (preparedAttribute.getValue() != null) { - final Attribute alreadyAdded = - AttributeUtil.find(preparedAttribute.getValue().getName(), attributes); + final Attribute alreadyAdded = AttributeUtil.find(preparedAttribute.getValue().getName(), + attributes); if (alreadyAdded == null) { attributes.add(preparedAttribute.getValue()); @@ -488,7 +484,7 @@ public class PropagationManager { } // Evaluate AccountLink expression - String evalAccountLink = jexlUtil.evaluate(resource.getAccountLink(), (SyncopeUser) attributable); + String evalAccountLink = jexlUtil.evaluate(resource.getAccountLink(), user); // AccountId must be propagated. It could be a simple attribute for // the target resource or the key (depending on the accountLink) @@ -509,7 +505,7 @@ public class PropagationManager { attributes.add(AttributeBuilder.buildEnabled(enable)); } - return new DefaultMapEntry(accountId, attributes); + return new SimpleEntry<String, Set<Attribute>>(accountId, attributes); } /** @@ -517,23 +513,18 @@ public class PropagationManager { * * @param user user to be provisioned * @param password cleartext password to be provisioned + * @param vAttrsToBeRemoved virtual attributes to be removed + * @param vAttrsToBeUpdated virtual attributes to be added * @param enable whether user must be enabled or not * @param deleteOnResource whether user must be deleted anyway from external resource or not * @param propByRes operation to be performed per resource * @return list of propagation tasks created */ - protected List<PropagationTask> provision( - final Attributable user, - final String password, - final Boolean enable, - final boolean deleteOnResource, final PropagationByResource propByRes) { - - // Retrieve attributable ... - final Attributable attributable = user instanceof Proxy - ? ((AttributableHandler) Proxy.getInvocationHandler(user)).getObject() - : user; + protected List<PropagationTask> provision(final SyncopeUser user, final String password, + final Set<String> vAttrsToBeRemoved, final Map<String, AttributeMod> vAttrsToBeUpdated, + final Boolean enable, final boolean deleteOnResource, final PropagationByResource propByRes) { - LOG.debug("Provisioning with user {}:\n{}", attributable, propByRes); + LOG.debug("Provisioning with user {}:\n{}", user, propByRes); // Avoid duplicates - see javadoc propByRes.purge(); @@ -553,14 +544,14 @@ public class PropagationManager { PropagationTask task = new PropagationTask(); task.setResource(resource); if (!deleteOnResource) { - task.setSyncopeUser((SyncopeUser) attributable); + task.setSyncopeUser(user); } task.setPropagationOperation(operation); task.setPropagationMode(resource.getPropagationMode()); task.setOldAccountId(propByRes.getOldAccountId(resource.getName())); - Map.Entry<String, Set<Attribute>> preparedAttrs = prepareAttributes(user, password, enable, resource); - + Map.Entry<String, Set<Attribute>> preparedAttrs = prepareAttributes(user, password, + vAttrsToBeRemoved, vAttrsToBeUpdated, enable, resource); task.setAccountId(preparedAttrs.getKey()); task.setAttributes(preparedAttrs.getValue()); @@ -748,18 +739,19 @@ public class PropagationManager { LOG.debug("{} not found on external resource: ignoring delete", task.getAccountId()); } else { /* - * We must choose here whether to a. actually delete the provided user from the external - * resource b. just update the provided user data onto the external resource + * We must choose here whether to + * a. actually delete the provided user from the external resource + * b. just update the provided user data onto the external resource * * (a) happens when either there is no user associated with the PropagationTask (this takes * place when the task is generated via UserController.delete()) or the provided updated * user hasn't the current resource assigned (when the task is generated via * UserController.update()). * - * (b) happens when the provided updated user does have the current resource assigned (when - * the task is generated via UserController.update()): this basically means that before such - * update, this user used to have the current resource assigned by more than one mean (for - * example, two different memberships with the same resource). + * (b) happens when the provided updated user does have the current resource assigned + * (when the task is generated via UserController.update()): this basically means that + * before such update, this user used to have the current resource assigned by more than + * one mean (for example, two different memberships with the same resource). */ SyncopeUser user = null; @@ -892,57 +884,4 @@ public class PropagationManager { return null; } } - - public static class AttributableHandler implements InvocationHandler { - - private Attributable object; - - private Set<String> vAttrsToBeRemoved; - - private Map<String, AttributeMod> vAttrsToBeUpdated; - - public AttributableHandler( - final Attributable object, - final Set<String> vAttrsToBeRemoved, - final Set<AttributeMod> vAttrsToBeUpdated) { - this.object = object; - this.vAttrsToBeRemoved = vAttrsToBeRemoved; - - if (vAttrsToBeUpdated != null) { - this.vAttrsToBeUpdated = new HashMap<String, AttributeMod>(vAttrsToBeUpdated.size()); - - for (AttributeMod attrMod : vAttrsToBeUpdated) { - this.vAttrsToBeUpdated.put(attrMod.getSchema(), attrMod); - } - } else { - this.vAttrsToBeUpdated = Collections.EMPTY_MAP; - } - } - - @Override - public Object invoke(final Object proxy, final Method method, final Object[] args) - throws Throwable { - if ("getVirtualAttribute".equals(method.getName()) && args.length == 1 && (args[0] instanceof String)) { - final AbstractVirAttr attr = object.getVirtualAttribute((String) args[0]); - - if (vAttrsToBeUpdated.containsKey((String) args[0])) { - attr.setValues(vAttrsToBeUpdated.get((String) args[0]).getValuesToBeAdded()); - } else if (vAttrsToBeRemoved.contains((String) args[0])) { - if (attr != null) { - attr.getValues().clear(); - } - } else { - throw new RuntimeException("Virtual attribute has not to be updated"); - } - - return attr; - } else { - return method.invoke(object, args); - } - } - - public Attributable getObject() { - return object; - } - } } Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java Thu Jan 3 16:29:00 2013 @@ -18,6 +18,7 @@ */ package org.apache.syncope.core.rest.controller; +import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -25,7 +26,6 @@ import java.util.Map; import java.util.Set; import javassist.NotFoundException; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; import org.apache.syncope.client.mod.UserMod; import org.apache.syncope.client.search.NodeCond; import org.apache.syncope.client.to.MembershipTO; @@ -540,7 +540,8 @@ public class UserController { WorkflowResult<Long> updated = wfAdapter.execute(userTO, taskId); List<PropagationTask> tasks = propagationManager.getUpdateTaskIds(new WorkflowResult<Map.Entry<Long, Boolean>>( - new DefaultMapEntry(updated.getResult(), null), updated.getPropByRes(), updated.getPerformedTasks())); + new SimpleEntry<Long, Boolean>(updated.getResult(), null), + updated.getPropByRes(), updated.getPerformedTasks())); propagationManager.execute(tasks); @@ -610,8 +611,8 @@ public class UserController { getAuthentication().getName()); List<PropagationTask> tasks = propagationManager.getUpdateTaskIds(new WorkflowResult<Map.Entry<Long, Boolean>>( - new DefaultMapEntry(updated.getResult().getKey(), Boolean.TRUE), updated.getPropByRes(), updated. - getPerformedTasks()), updated.getResult().getValue(), null, null); + new SimpleEntry<Long, Boolean>(updated.getResult().getKey(), Boolean.TRUE), + updated.getPropByRes(), updated.getPerformedTasks()), updated.getResult().getValue(), null, null); propagationManager.execute(tasks); final UserTO savedTO = dataBinder.getUserTO(updated.getResult().getKey()); Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/util/SchemaMappingUtil.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/util/SchemaMappingUtil.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/util/SchemaMappingUtil.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/util/SchemaMappingUtil.java Thu Jan 3 16:29:00 2013 @@ -18,7 +18,6 @@ */ package org.apache.syncope.core.util; -import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,14 +26,12 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; +import org.apache.syncope.client.mod.AttributeMod; import org.apache.syncope.core.persistence.beans.AbstractAttr; import org.apache.syncope.core.persistence.beans.AbstractAttrValue; import org.apache.syncope.core.persistence.beans.AbstractAttributable; import org.apache.syncope.core.persistence.beans.AbstractDerAttr; -import org.apache.syncope.core.persistence.beans.AbstractSchema; import org.apache.syncope.core.persistence.beans.AbstractVirAttr; -import org.apache.syncope.core.persistence.beans.Attributable; import org.apache.syncope.core.persistence.beans.SchemaMapping; import org.apache.syncope.core.persistence.beans.membership.MDerSchema; import org.apache.syncope.core.persistence.beans.membership.MSchema; @@ -47,21 +44,18 @@ import org.apache.syncope.core.persisten import org.apache.syncope.core.persistence.beans.user.UDerSchema; import org.apache.syncope.core.persistence.beans.user.USchema; import org.apache.syncope.core.persistence.beans.user.UVirSchema; -import org.apache.syncope.core.persistence.dao.SchemaDAO; -import org.apache.syncope.core.propagation.PropagationManager.AttributableHandler; import org.apache.syncope.types.IntMappingType; import org.identityconnectors.framework.common.objects.OperationalAttributes; import org.identityconnectors.framework.common.objects.Uid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.security.util.Password; public class SchemaMappingUtil { /** * Logger. */ - protected static final Logger LOG = LoggerFactory.getLogger(SchemaMappingUtil.class); + private static final Logger LOG = LoggerFactory.getLogger(SchemaMappingUtil.class); public static String getExtAttrName(final SchemaMapping mapping) { final String name; @@ -136,35 +130,35 @@ public class SchemaMappingUtil { * @param mapping mapping. * @param attributables list of attributables. * @param password password. - * @return schema and attribute values. + * @return attribute values. */ - public static Map.Entry<AbstractSchema, List<AbstractAttrValue>> getIntValues(final SchemaMapping mapping, - final List<Attributable> attributables, final String password, final SchemaDAO schemaDAO) { + public static List<AbstractAttrValue> getIntValues(final SchemaMapping mapping, + final List<AbstractAttributable> attributables, final String password, + final Set<String> vAttrsToBeRemoved, final Map<String, AttributeMod> vAttrsToBeUpdated) { LOG.debug("Get attributes for '{}' and mapping type '{}'", attributables, mapping.getIntMappingType()); - AbstractSchema schema = null; - List<AbstractAttrValue> values = new ArrayList<AbstractAttrValue>(); switch (mapping.getIntMappingType()) { case UserSchema: case RoleSchema: case MembershipSchema: - schema = schemaDAO.find(mapping.getIntAttrName(), SchemaMappingUtil.getIntMappingTypeClass(mapping. - getIntMappingType())); - - for (Attributable attributable : attributables) { + for (AbstractAttributable attributable : attributables) { final AbstractAttr attr = attributable.getAttribute(mapping.getIntAttrName()); - - if (attr != null && attr.getValues() != null) { - values.addAll(schema.isUniqueConstraint() - ? Collections.singletonList(attr.getUniqueValue()) : attr.getValues()); + if (attr != null) { + if (attr.getUniqueValue() != null) { + values.add(attr.getUniqueValue()); + } else if (attr.getValues() != null) { + values.addAll(attr.getValues()); + } } - LOG.debug("Retrieved attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}" - + "\n* Attribute values {}", new Object[]{attr, mapping.getIntAttrName(), - mapping.getIntMappingType(), values}); + LOG.debug("Retrieved attribute {}" + + "\n* IntAttrName {}" + + "\n* IntMappingType {}" + + "\n* Attribute values {}", + attr, mapping.getIntAttrName(), mapping.getIntMappingType(), values); } break; @@ -172,28 +166,39 @@ public class SchemaMappingUtil { case UserVirtualSchema: case RoleVirtualSchema: case MembershipVirtualSchema: - - for (Attributable attributable : attributables) { + for (AbstractAttributable attributable : attributables) { AbstractVirAttr virAttr = attributable.getVirtualAttribute(mapping.getIntAttrName()); - - if (virAttr != null && virAttr.getValues() != null) { - for (String value : virAttr.getValues()) { - AbstractAttrValue attrValue = new UAttrValue(); - attrValue.setStringValue(value); - values.add(attrValue); + if (virAttr != null) { + if (virAttr.getValues() != null) { + for (String value : virAttr.getValues()) { + AbstractAttrValue attrValue = new UAttrValue(); + attrValue.setStringValue(value); + values.add(attrValue); + } + } + if (vAttrsToBeRemoved != null && vAttrsToBeUpdated != null) { + if (vAttrsToBeUpdated.containsKey(mapping.getIntAttrName())) { + virAttr.setValues(vAttrsToBeUpdated.get(mapping.getIntAttrName()).getValuesToBeAdded()); + } else if (vAttrsToBeRemoved.contains(mapping.getIntAttrName())) { + virAttr.getValues().clear(); + } else { + throw new RuntimeException("Virtual attribute has not to be updated"); + } } } - LOG.debug("Retrieved virtual attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}" - + "\n* Attribute values {}", new Object[]{virAttr, mapping.getIntAttrName(), - mapping.getIntMappingType(), values}); + LOG.debug("Retrieved virtual attribute {}" + + "\n* IntAttrName {}" + + "\n* IntMappingType {}" + + "\n* Attribute values {}", + virAttr, mapping.getIntAttrName(), mapping.getIntMappingType(), values); } break; case UserDerivedSchema: case RoleDerivedSchema: case MembershipDerivedSchema: - for (Attributable attributable : attributables) { + for (AbstractAttributable attributable : attributables) { AbstractDerAttr derAttr = attributable.getDerivedAttribute(mapping.getIntAttrName()); if (derAttr != null) { @@ -202,26 +207,24 @@ public class SchemaMappingUtil { values.add(attrValue); } - LOG.debug("Retrieved attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}" - + "\n* Attribute values {}", new Object[]{derAttr, mapping.getIntAttrName(), - mapping.getIntMappingType(), values}); + LOG.debug("Retrieved derived attribute {}" + + "\n* IntAttrName {}" + + "\n* IntMappingType {}" + + "\n* Attribute values {}", + derAttr, mapping.getIntAttrName(), mapping.getIntMappingType(), values); } break; case Username: - for (Attributable attributable : attributables) { + for (AbstractAttributable attributable : attributables) { AbstractAttrValue attrValue = new UAttrValue(); - SyncopeUser user = attributable instanceof Proxy? - (SyncopeUser)((AttributableHandler)Proxy.getInvocationHandler(attributable)).getObject(): - (SyncopeUser)attributable; - - attrValue.setStringValue(user.getUsername()); + attrValue.setStringValue(((SyncopeUser) attributable).getUsername()); values.add(attrValue); } break; case SyncopeUserId: - for (Attributable attributable : attributables) { + for (AbstractAttributable attributable : attributables) { AbstractAttrValue attrValue = new UAttrValue(); attrValue.setStringValue(attributable.getId().toString()); values.add(attrValue); @@ -241,67 +244,9 @@ public class SchemaMappingUtil { default: } - LOG.debug("Retrived values '{}'", values); - - return new DefaultMapEntry(schema, values); - } - - public static List<String> getIntValueAsStrings( - final AbstractAttributable attributable, final SchemaMapping mapping) { - return getIntValueAsStrings(attributable, mapping, null); - } - - public static List<String> getIntValueAsStrings( - final AbstractAttributable attributable, final SchemaMapping mapping, String clearPassword) { - - List<String> value = new ArrayList<String>(); - - if (mapping != null) { - switch (mapping.getIntMappingType()) { - case Username: - if (!(attributable instanceof SyncopeUser)) { - throw new ClassCastException("mappingtype is Username, but attributable is not SyncopeUser: " - + attributable.getClass().getName()); - } - value.add(((SyncopeUser) attributable).getUsername()); - break; - case Password: - if (clearPassword != null) { - value.add(clearPassword); - } - break; - case UserSchema: - case RoleSchema: - case MembershipSchema: - AbstractAttr abstractAttr = attributable.getAttribute(mapping.getIntAttrName()); - if (abstractAttr != null && abstractAttr.getValues() != null) { - value.addAll(abstractAttr.getValuesAsStrings()); - } - break; - case UserVirtualSchema: - case RoleVirtualSchema: - case MembershipVirtualSchema: - AbstractVirAttr abstractVirAttr = attributable.getVirtualAttribute(mapping.getIntAttrName()); - if (abstractVirAttr != null && abstractVirAttr.getValues() != null) { - value.addAll(abstractVirAttr.getValues()); - } - break; - case UserDerivedSchema: - case RoleDerivedSchema: - case MembershipDerivedSchema: - AbstractDerAttr abstractDerAttr = attributable.getDerivedAttribute(mapping.getIntAttrName()); - if (abstractDerAttr != null) { - String abstractDerAttrValue = abstractDerAttr.getValue(attributable.getAttributes()); - if (abstractDerAttrValue != null) { - value.add(abstractDerAttrValue); - } - } - break; - default: - } - } + LOG.debug("Retrieved values '{}'", values); - return value; + return values; } /** @@ -372,30 +317,15 @@ public class SchemaMappingUtil { * Get accountId internal value. * * @param attributable attributable. - * @param mappings collection of SchemaMapping. - * @return accountId internal value. - */ - public static String getAccountIdValue(final AbstractAttributable attributable, - final Collection<SchemaMapping> mappings) { - - final List<String> values = getIntValueAsStrings(attributable, getAccountIdMapping(mappings)); - return values == null || values.isEmpty() - ? null - : values.get(0); - } - - /** - * Get accountId internal value. - * - * @param attributable attributable. - * @param mappings accountId mapping. + * @param mapping accountId mapping. * @return accountId internal value. */ public static String getAccountIdValue(final AbstractAttributable attributable, final SchemaMapping mapping) { - final List<String> values = getIntValueAsStrings(attributable, mapping); + List<AbstractAttrValue> values = getIntValues( + mapping, Collections.<AbstractAttributable>singletonList(attributable), null, null, null); return values == null || values.isEmpty() ? null - : values.get(0); + : values.get(0).getValueAsString(); } public static class SchemaMappingsWrapper { Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/ActivitiUserWorkflowAdapter.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/ActivitiUserWorkflowAdapter.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/ActivitiUserWorkflowAdapter.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/ActivitiUserWorkflowAdapter.java Thu Jan 3 16:29:00 2013 @@ -28,6 +28,7 @@ import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; +import java.util.AbstractMap.SimpleEntry; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -53,7 +54,6 @@ import org.activiti.engine.history.Histo import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; import org.apache.commons.lang.StringUtils; import org.apache.syncope.client.mod.UserMod; import org.apache.syncope.client.to.UserTO; @@ -251,7 +251,8 @@ public class ActivitiUserWorkflowAdapter } } - return new WorkflowResult<Map.Entry<Long, Boolean>>(new DefaultMapEntry(user.getId(), propagateEnable), + return new WorkflowResult<Map.Entry<Long, Boolean>>( + new SimpleEntry<Long, Boolean>(user.getId(), propagateEnable), propByRes, getPerformedTasks(user)); } @@ -324,8 +325,8 @@ public class ActivitiUserWorkflowAdapter Boolean propagateEnable = (Boolean) runtimeService.getVariable(user.getWorkflowId(), PROPAGATE_ENABLE); - return new WorkflowResult<Map.Entry<Long, Boolean>>(new DefaultMapEntry(updated.getId(), propagateEnable), - propByRes, task); + return new WorkflowResult<Map.Entry<Long, Boolean>>(new SimpleEntry<Long, Boolean>(updated.getId(), + propagateEnable), propByRes, task); } @Override @@ -599,7 +600,7 @@ public class ActivitiUserWorkflowAdapter } } - return new DefaultMapEntry(task, formData); + return new SimpleEntry<Task, TaskFormData>(task, formData); } @Override @@ -667,7 +668,8 @@ public class ActivitiUserWorkflowAdapter clearPassword = decrypt(encryptedPwd); } - return new WorkflowResult<Map.Entry<Long, String>>(new DefaultMapEntry(updated.getId(), clearPassword), + return new WorkflowResult<Map.Entry<Long, String>>( + new SimpleEntry<Long, String>(updated.getId(), clearPassword), propByRes, postTasks); } } Modified: syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/NoOpUserWorkflowAdapter.java URL: http://svn.apache.org/viewvc/syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/NoOpUserWorkflowAdapter.java?rev=1428455&r1=1428454&r2=1428455&view=diff ============================================================================== --- syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/NoOpUserWorkflowAdapter.java (original) +++ syncope/branches/1_0_X/core/src/main/java/org/apache/syncope/core/workflow/NoOpUserWorkflowAdapter.java Thu Jan 3 16:29:00 2013 @@ -18,12 +18,12 @@ */ package org.apache.syncope.core.workflow; +import java.util.AbstractMap.SimpleEntry; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import javassist.NotFoundException; -import org.apache.commons.collections.keyvalue.DefaultMapEntry; import org.apache.syncope.client.mod.UserMod; import org.apache.syncope.client.to.UserTO; import org.apache.syncope.client.to.WorkflowDefinitionTO; @@ -82,8 +82,8 @@ public class NoOpUserWorkflowAdapter ext final PropagationByResource propByRes = new PropagationByResource(); propByRes.set(PropagationOperation.CREATE, user.getResourceNames()); - return new WorkflowResult<Map.Entry<Long, Boolean>>(new DefaultMapEntry(user.getId(), propagateEnable), - propByRes, "create"); + return new WorkflowResult<Map.Entry<Long, Boolean>>(new SimpleEntry<Long, Boolean>(user.getId(), + propagateEnable), propByRes, "create"); } @Override @@ -108,8 +108,8 @@ public class NoOpUserWorkflowAdapter ext SyncopeUser updated = userDAO.save(user); - return new WorkflowResult<Map.Entry<Long, Boolean>>(new DefaultMapEntry(updated.getId(), true), propByRes, - "update"); + return new WorkflowResult<Map.Entry<Long, Boolean>>(new SimpleEntry<Long, Boolean>(updated.getId(), true), + propByRes, "update"); } @Override