syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [4/5] syncope git commit: [SYNCOPE-670] Merge from 1_2_X
Date Fri, 22 May 2015 10:24:43 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/22a9e12e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
----------------------------------------------------------------------
diff --cc core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
index 14c00c7,0000000..58202b7
mode 100644,000000..100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
@@@ -1,312 -1,0 +1,312 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.core.provisioning.java;
 +
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Set;
 +import org.apache.commons.lang3.StringUtils;
 +import org.apache.syncope.common.lib.mod.AttrMod;
 +import org.apache.syncope.common.lib.to.AttrTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.IntMappingType;
 +import org.apache.syncope.common.lib.types.MappingPurpose;
 +import org.apache.syncope.common.lib.types.PropagationByResource;
 +import org.apache.syncope.common.lib.types.ResourceOperation;
 +import org.apache.syncope.core.persistence.api.dao.MembershipDAO;
 +import org.apache.syncope.core.persistence.api.dao.UserDAO;
 +import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
 +import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 +import org.apache.syncope.core.persistence.api.entity.Attributable;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtils;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
 +import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 +import org.apache.syncope.core.persistence.api.entity.MappingItem;
 +import org.apache.syncope.core.persistence.api.entity.Subject;
 +import org.apache.syncope.core.persistence.api.entity.VirAttr;
 +import org.apache.syncope.core.persistence.api.entity.VirSchema;
 +import org.apache.syncope.core.persistence.api.entity.membership.MVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.membership.MVirAttrTemplate;
 +import org.apache.syncope.core.persistence.api.entity.membership.Membership;
 +import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.group.GVirAttrTemplate;
 +import org.apache.syncope.core.persistence.api.entity.group.Group;
 +import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.user.UVirSchema;
 +import org.apache.syncope.core.persistence.api.entity.user.User;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Component;
 +import org.springframework.transaction.annotation.Transactional;
 +
 +@Component
 +@Transactional(rollbackFor = { Throwable.class })
 +public class VirAttrHandler {
 +
 +    private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
 +
 +    @Autowired
 +    private VirSchemaDAO virSchemaDAO;
 +
 +    @Autowired
 +    private VirAttrDAO virAttrDAO;
 +
 +    @Autowired
 +    private UserDAO userDAO;
 +
 +    @Autowired
 +    private MembershipDAO membershipDAO;
 +
 +    @Autowired
 +    private AttributableUtilsFactory attrUtilsFactory;
 +
 +    public <T extends VirSchema> T getVirSchema(final String virSchemaName, final Class<T> reference) {
 +        T virtualSchema = null;
 +        if (StringUtils.isNotBlank(virSchemaName)) {
 +            virtualSchema = virSchemaDAO.find(virSchemaName, reference);
 +
 +            if (virtualSchema == null) {
 +                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
 +            }
 +        }
 +
 +        return virtualSchema;
 +    }
 +
 +    public void setVirAttrSchema(final Attributable<?, ?, ?> attributable,
 +            final VirAttr virAttr, final VirSchema virSchema) {
 +
 +        if (virAttr instanceof UVirAttr) {
 +            ((UVirAttr) virAttr).setSchema((UVirSchema) virSchema);
 +        } else if (virAttr instanceof GVirAttr) {
 +            GVirAttrTemplate template = ((Group) attributable).
 +                    getAttrTemplate(GVirAttrTemplate.class, virSchema.getKey());
 +            if (template != null) {
 +                ((GVirAttr) virAttr).setTemplate(template);
 +            }
 +        } else if (virAttr instanceof MVirAttr) {
 +            MVirAttrTemplate template =
 +                    ((Membership) attributable).getGroup().
 +                    getAttrTemplate(MVirAttrTemplate.class, virSchema.getKey());
 +            if (template != null) {
 +                ((MVirAttr) virAttr).setTemplate(template);
 +            }
 +        }
 +    }
 +
 +    public void updateOnResourcesIfMappingMatches(final AttributableUtils attrUtils, final String schemaKey,
 +            final Set<ExternalResource> resources, final IntMappingType mappingType,
 +            final PropagationByResource propByRes) {
 +
 +        for (ExternalResource resource : resources) {
 +            for (MappingItem mapItem : attrUtils.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
 +                if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
 +                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 +                }
 +            }
 +        }
 +    }
 +
 +    @SuppressWarnings({ "unchecked", "rawtypes" })
 +    public PropagationByResource fillVirtual(final Attributable attributable,
 +            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated,
 +            final AttributableUtils attrUtils) {
 +
 +        PropagationByResource propByRes = new PropagationByResource();
 +
 +        Set<ExternalResource> externalResources = new HashSet<>();
 +        if (attributable instanceof User) {
 +            externalResources.addAll(userDAO.findAllResources((User) attributable));
 +        } else if (attributable instanceof Group) {
 +            externalResources.addAll(((Group) attributable).getResources());
 +        } else if (attributable instanceof Membership) {
 +            externalResources.addAll(userDAO.findAllResources(((Membership) attributable).getUser()));
 +            externalResources.addAll(((Membership) attributable).getGroup().getResources());
 +        }
 +
 +        // 1. virtual attributes to be removed
 +        for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
 +            VirSchema virSchema = getVirSchema(vAttrToBeRemoved, attrUtils.virSchemaClass());
 +            if (virSchema != null) {
 +                VirAttr virAttr = attributable.getVirAttr(virSchema.getKey());
 +                if (virAttr == null) {
 +                    LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
 +                } else {
 +                    attributable.removeVirAttr(virAttr);
 +                    virAttrDAO.delete(virAttr);
 +                }
 +
 +                for (ExternalResource resource : externalResources) {
 +                    for (MappingItem mapItem : attrUtils.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
 +                        if (virSchema.getKey().equals(mapItem.getIntAttrName())
 +                                && mapItem.getIntMappingType() == attrUtils.virIntMappingType()) {
 +
 +                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 +
 +                            // Using virtual attribute as AccountId must be avoided
 +                            if (mapItem.isAccountid() && virAttr != null && !virAttr.getValues().isEmpty()) {
 +                                propByRes.addOldAccountId(resource.getKey(), virAttr.getValues().get(0));
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +
 +        LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
 +
 +        // 2. virtual attributes to be updated
 +        for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
 +            VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema(), attrUtils.virSchemaClass());
 +            VirAttr virAttr = null;
 +            if (virSchema != null) {
 +                virAttr = attributable.getVirAttr(virSchema.getKey());
 +                if (virAttr == null) {
 +                    virAttr = attrUtils.newVirAttr();
 +                    setVirAttrSchema(attributable, virAttr, virSchema);
 +                    if (virAttr.getSchema() == null) {
 +                        LOG.debug("Ignoring {} because no valid schema or template was found", vAttrToBeUpdated);
 +                    } else {
 +                        attributable.addVirAttr(virAttr);
 +                    }
 +                }
 +            }
 +
 +            if (virSchema != null && virAttr != null && virAttr.getSchema() != null) {
 +                if (attributable instanceof Subject) {
 +                    updateOnResourcesIfMappingMatches(attrUtils, virSchema.getKey(),
 +                            externalResources, attrUtils.derIntMappingType(), propByRes);
 +                } else if (attributable instanceof Membership) {
 +                    updateOnResourcesIfMappingMatches(attrUtils, virSchema.getKey(),
 +                            externalResources, IntMappingType.MembershipVirtualSchema, propByRes);
 +                }
 +
 +                final List<String> values = new ArrayList<>(virAttr.getValues());
 +                values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
 +                values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
 +
 +                virAttr.getValues().clear();
 +                virAttr.getValues().addAll(values);
 +
 +                // Owner cannot be specified before otherwise a virtual attribute remove will be invalidated.
 +                virAttr.setOwner(attributable);
 +            }
 +        }
 +
 +        LOG.debug("Virtual attributes to be added:\n{}", propByRes);
 +
 +        return propByRes;
 +    }
 +
 +    /**
 +     * Add virtual attributes and specify values to be propagated.
 +     *
 +     * @param attributable attributable.
 +     * @param vAttrs virtual attributes to be added.
 +     * @param attrUtils attributable util.
 +     */
 +    @SuppressWarnings({ "unchecked", "rawtypes" })
 +    public void fillVirtual(final Attributable attributable, final Collection<AttrTO> vAttrs,
 +            final AttributableUtils attrUtils) {
 +
 +        for (AttrTO attributeTO : vAttrs) {
 +            VirAttr virAttr = attributable.getVirAttr(attributeTO.getSchema());
 +            if (virAttr == null) {
 +                VirSchema virSchema = getVirSchema(attributeTO.getSchema(), attrUtils.virSchemaClass());
 +                if (virSchema != null) {
 +                    virAttr = attrUtils.newVirAttr();
 +                    setVirAttrSchema(attributable, virAttr, virSchema);
 +                    if (virAttr.getSchema() == null) {
 +                        LOG.debug("Ignoring {} because no valid schema or template was found", attributeTO);
 +                    } else {
 +                        virAttr.setOwner(attributable);
 +                        attributable.addVirAttr(virAttr);
 +                        virAttr.getValues().clear();
 +                        virAttr.getValues().addAll(attributeTO.getValues());
 +                    }
 +                }
 +            } else {
 +                virAttr.getValues().clear();
 +                virAttr.getValues().addAll(attributeTO.getValues());
 +            }
 +        }
 +    }
 +
 +    /**
 +     * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
 +     *
 +     * @param key user id
 +     * @param vAttrsToBeRemoved virtual attributes to be removed.
 +     * @param vAttrsToBeUpdated virtual attributes to be updated.
 +     * @return operations to be performed on external resources for virtual attributes changes
 +     */
 +    public PropagationByResource fillVirtual(
 +            final Long key, final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
 +
 +        return fillVirtual(
 +                userDAO.authFetch(key),
 +                vAttrsToBeRemoved,
 +                vAttrsToBeUpdated,
 +                attrUtilsFactory.getInstance(AttributableType.USER));
 +    }
 +
 +    private Set<String> getAttrNames(final List<? extends VirAttr> virAttrs) {
 +        final Set<String> virAttrNames = new HashSet<>();
 +        for (VirAttr attr : virAttrs) {
 +            virAttrNames.add(attr.getSchema().getKey());
 +        }
 +        return virAttrNames;
 +    }
 +
 +    /**
 +     * SYNCOPE-501: build membership virtual attribute changes in case no other changes were made.
 +     *
 +     * @param key user key
 +     * @param groupKey group key
 +     * @param membershipKey membership key
 +     * @param vAttrsToBeRemoved virtual attributes to be removed.
 +     * @param vAttrsToBeUpdated virtual attributes to be updated.
 +     * @param isRemoval flag to check if fill is on removed or added membership
 +     * @return operations to be performed on external resources for membership virtual attributes changes
 +     */
 +    public PropagationByResource fillMembershipVirtual(
 +            final Long key, final Long groupKey, final Long membershipKey, final Set<String> vAttrsToBeRemoved,
 +            final Set<AttrMod> vAttrsToBeUpdated, final boolean isRemoval) {
 +
-         final Membership membership = membershipKey == null
++        Membership membership = membershipKey == null
 +                ? userDAO.authFetch(key).getMembership(groupKey)
 +                : membershipDAO.authFetch(membershipKey);
 +
 +        return membership == null ? new PropagationByResource() : isRemoval
 +                ? fillVirtual(
 +                        membership,
 +                        getAttrNames(membership.getVirAttrs()),
 +                        vAttrsToBeUpdated,
 +                        attrUtilsFactory.getInstance(AttributableType.MEMBERSHIP))
 +                : fillVirtual(
 +                        membership,
 +                        vAttrsToBeRemoved,
 +                        vAttrsToBeUpdated,
 +                        attrUtilsFactory.getInstance(AttributableType.MEMBERSHIP));
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/22a9e12e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
----------------------------------------------------------------------
diff --cc core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index 2939095,0000000..d21afc5
mode 100644,000000..100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@@ -1,550 -1,0 +1,549 @@@
 +/*
 + * 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.propagation;
 +
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import org.apache.commons.collections4.CollectionUtils;
 +import org.apache.commons.collections4.Predicate;
 +import org.apache.commons.lang3.tuple.Pair;
 +import org.apache.syncope.common.lib.mod.AttrMod;
 +import org.apache.syncope.common.lib.mod.MembershipMod;
 +import org.apache.syncope.common.lib.mod.UserMod;
 +import org.apache.syncope.common.lib.to.AttrTO;
 +import org.apache.syncope.common.lib.to.MembershipTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.MappingPurpose;
 +import org.apache.syncope.common.lib.types.PropagationByResource;
 +import org.apache.syncope.common.lib.types.ResourceOperation;
 +import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 +import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 +import org.apache.syncope.core.persistence.api.dao.UserDAO;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtils;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
 +import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 +import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 +import org.apache.syncope.core.persistence.api.entity.MappingItem;
 +import org.apache.syncope.core.persistence.api.entity.Subject;
 +import org.apache.syncope.core.persistence.api.entity.VirAttr;
 +import org.apache.syncope.core.persistence.api.entity.membership.Membership;
 +import org.apache.syncope.core.persistence.api.entity.group.Group;
 +import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 +import org.apache.syncope.core.persistence.api.entity.user.User;
 +import org.apache.syncope.core.provisioning.api.WorkflowResult;
 +import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 +import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 +import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 +import org.apache.syncope.core.misc.ConnObjectUtils;
 +import org.apache.syncope.core.misc.MappingUtils;
 +import org.apache.syncope.core.misc.jexl.JexlUtils;
 +import org.identityconnectors.framework.common.objects.Attribute;
 +import org.identityconnectors.framework.common.objects.AttributeBuilder;
 +import org.identityconnectors.framework.common.objects.AttributeUtil;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.transaction.annotation.Transactional;
 +
 +/**
 + * Manage the data propagation to external resources.
 + */
 +@Transactional(rollbackFor = { Throwable.class })
 +public class PropagationManagerImpl implements PropagationManager {
 +
 +    /**
 +     * Logger.
 +     */
 +    protected static final Logger LOG = LoggerFactory.getLogger(PropagationManager.class);
 +
 +    /**
 +     * User DAO.
 +     */
 +    @Autowired
 +    protected UserDAO userDAO;
 +
 +    /**
 +     * Group DAO.
 +     */
 +    @Autowired
 +    protected GroupDAO groupDAO;
 +
 +    /**
 +     * Resource DAO.
 +     */
 +    @Autowired
 +    protected ExternalResourceDAO resourceDAO;
 +
 +    @Autowired
 +    protected EntityFactory entityFactory;
 +
 +    /**
 +     * ConnObjectUtils.
 +     */
 +    @Autowired
 +    protected ConnObjectUtils connObjectUtils;
 +
 +    @Autowired
 +    protected AttributableUtilsFactory attrUtilsFactory;
 +
 +    @Autowired
 +    protected VirAttrHandler virAttrHandler;
 +
 +    @Override
 +    public List<PropagationTask> getUserCreateTasks(
 +            final Long key,
 +            final Boolean enable,
 +            final PropagationByResource propByRes,
 +            final String password,
 +            final Collection<AttrTO> vAttrs,
 +            final Collection<MembershipTO> membershipTOs,
 +            final Collection<String> noPropResourceNames) {
 +
 +        User user = userDAO.authFetch(key);
 +        if (vAttrs != null && !vAttrs.isEmpty()) {
 +            virAttrHandler.fillVirtual(user, vAttrs, attrUtilsFactory.getInstance(AttributableType.USER));
 +        }
 +        for (final Membership membership : user.getMemberships()) {
 +            if (membership.getVirAttrs() != null && !membership.getVirAttrs().isEmpty()) {
 +                MembershipTO membershipTO = CollectionUtils.find(membershipTOs, new Predicate<MembershipTO>() {
 +
 +                    @Override
 +                    public boolean evaluate(final MembershipTO membershipTO) {
 +                        return membershipTO.getGroupKey() == membership.getGroup().getKey();
 +                    }
 +                });
 +                if (membershipTO != null) {
 +                    virAttrHandler.fillVirtual(membership,
 +                            membershipTO.getVirAttrs(), attrUtilsFactory.getInstance(AttributableType.MEMBERSHIP));
 +                }
 +            }
 +        }
 +        return getCreateTaskIds(user, password, enable, propByRes, noPropResourceNames);
 +    }
 +
 +    /**
 +     * Create the group on every associated resource.
 +     *
 +     * @param wfResult group to be propagated (and info associated), as per result from workflow
 +     * @param vAttrs virtual attributes to be set
 +     * @param noPropResourceNames external resources performing not to be considered for propagation
 +     * @return list of propagation tasks
 +     */
 +    @Override
 +    public List<PropagationTask> getGroupCreateTasks(
 +            final WorkflowResult<Long> wfResult,
 +            final Collection<AttrTO> vAttrs,
 +            final Collection<String> noPropResourceNames) {
 +
 +        return getGroupCreateTasks(wfResult.getResult(), vAttrs, wfResult.getPropByRes(), noPropResourceNames);
 +    }
 +
 +    /**
 +     * Create the group on every associated resource.
 +     *
 +     * @param key group key
 +     * @param vAttrs virtual attributes to be set
 +     * @param propByRes operation to be performed per resource
 +     * @param noPropResourceNames external resources performing not to be considered for propagation
 +     * @return list of propagation tasks
 +     */
 +    @Override
 +    public List<PropagationTask> getGroupCreateTasks(
 +            final Long key,
 +            final Collection<AttrTO> vAttrs,
 +            final PropagationByResource propByRes,
 +            final Collection<String> noPropResourceNames) {
 +
 +        Group group = groupDAO.authFetch(key);
 +        if (vAttrs != null && !vAttrs.isEmpty()) {
 +            virAttrHandler.fillVirtual(group, vAttrs, attrUtilsFactory.getInstance(AttributableType.GROUP));
 +        }
 +
 +        return getCreateTaskIds(group, null, null, propByRes, noPropResourceNames);
 +    }
 +
 +    protected List<PropagationTask> getCreateTaskIds(final Subject<?, ?, ?> subject,
 +            final String password, final Boolean enable,
 +            final PropagationByResource propByRes,
 +            final Collection<String> noPropResourceNames) {
 +
 +        if (propByRes == null || propByRes.isEmpty()) {
 +            return Collections.<PropagationTask>emptyList();
 +        }
 +
 +        if (noPropResourceNames != null) {
 +            propByRes.get(ResourceOperation.CREATE).removeAll(noPropResourceNames);
 +        }
 +
 +        return createTasks(subject, password, true, null, null, null, null, enable, false, propByRes);
 +    }
 +
 +    /**
 +     * Performs update on each resource associated to the user excluding the specified into 'resourceNames' parameter.
 +     *
 +     * @param user to be propagated
 +     * @param enable whether user must be enabled or not
 +     * @param noPropResourceNames external resource names not to be considered for propagation
 +     * @return list of propagation tasks
 +     */
 +    @Override
 +    public List<PropagationTask> getUserUpdateTasks(final User user, final Boolean enable,
 +            final Collection<String> noPropResourceNames) {
 +
 +        return getUpdateTasks(
 +                user, // user to be updated on external resources
 +                null, // no password
 +                false,
 +                enable, // status to be propagated
 +                Collections.<String>emptySet(), // no virtual attributes to be managed
 +                Collections.<AttrMod>emptySet(), // no virtual attributes to be managed
 +                null, // no propagation by resources
 +                noPropResourceNames,
 +                Collections.<MembershipMod>emptySet());
 +    }
 +
 +    /**
 +     * Performs update on each resource associated to the user.
 +     *
 +     * @param wfResult user to be propagated (and info associated), as per result from workflow
 +     * @param changePwd whether password should be included for propagation attributes or not
 +     * @param noPropResourceNames external resources not to be considered for propagation
 +     * @return list of propagation tasks
 +     */
 +    @Override
 +    public List<PropagationTask> getUserUpdateTasks(final WorkflowResult<Pair<UserMod, Boolean>> wfResult,
 +            final boolean changePwd, final Collection<String> noPropResourceNames) {
 +
 +        User user = userDAO.authFetch(wfResult.getResult().getKey().getKey());
 +        return getUpdateTasks(user,
 +                wfResult.getResult().getKey().getPassword(),
 +                changePwd,
 +                wfResult.getResult().getValue(),
 +                wfResult.getResult().getKey().getVirAttrsToRemove(),
 +                wfResult.getResult().getKey().getVirAttrsToUpdate(),
 +                wfResult.getPropByRes(),
 +                noPropResourceNames,
 +                wfResult.getResult().getKey().getMembershipsToAdd());
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getUserUpdateTasks(final WorkflowResult<Pair<UserMod, Boolean>> wfResult) {
 +        UserMod userMod = wfResult.getResult().getKey();
 +
 +        // Propagate password update only to requested resources
 +        List<PropagationTask> tasks = new ArrayList<>();
 +        if (userMod.getPwdPropRequest() == null) {
 +            // a. no specific password propagation request: generate propagation tasks for any resource associated
 +            tasks = getUserUpdateTasks(wfResult, false, null);
 +        } else {
 +            // b. generate the propagation task list in two phases: first the ones containing password,
 +            // the the rest (with no password)
 +            final PropagationByResource origPropByRes = new PropagationByResource();
 +            origPropByRes.merge(wfResult.getPropByRes());
 +
 +            Set<String> pwdResourceNames = new HashSet<>(userMod.getPwdPropRequest().getResourceNames());
 +            Collection<String> currentResourceNames = userDAO.findAllResourceNames(userDAO.authFetch(userMod.getKey()));
 +            pwdResourceNames.retainAll(currentResourceNames);
 +            PropagationByResource pwdPropByRes = new PropagationByResource();
 +            pwdPropByRes.addAll(ResourceOperation.UPDATE, pwdResourceNames);
 +            if (!pwdPropByRes.isEmpty()) {
 +                Set<String> toBeExcluded = new HashSet<>(currentResourceNames);
 +                toBeExcluded.addAll(userMod.getResourcesToAdd());
 +                toBeExcluded.removeAll(pwdResourceNames);
 +                tasks.addAll(getUserUpdateTasks(wfResult, true, toBeExcluded));
 +            }
 +
-             final PropagationByResource nonPwdPropByRes = new PropagationByResource();
++            PropagationByResource nonPwdPropByRes = new PropagationByResource();
 +            nonPwdPropByRes.merge(origPropByRes);
 +            nonPwdPropByRes.removeAll(pwdResourceNames);
 +            nonPwdPropByRes.purge();
 +            if (!nonPwdPropByRes.isEmpty()) {
 +                tasks.addAll(getUserUpdateTasks(wfResult, false, pwdResourceNames));
 +            }
 +        }
 +
 +        return tasks;
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getGroupUpdateTasks(final WorkflowResult<Long> wfResult,
 +            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated,
 +            final Set<String> noPropResourceNames) {
 +
 +        Group group = groupDAO.authFetch(wfResult.getResult());
 +        return getUpdateTasks(group, null, false, null,
 +                vAttrsToBeRemoved, vAttrsToBeUpdated, wfResult.getPropByRes(), noPropResourceNames,
 +                Collections.<MembershipMod>emptySet());
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getUpdateTasks(final Subject<?, ?, ?> subject,
 +            final String password, final boolean changePwd, final Boolean enable,
 +            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated,
 +            final PropagationByResource propByRes, final Collection<String> noPropResourceNames,
 +            final Set<MembershipMod> membershipsToAdd) {
 +
 +        PropagationByResource localPropByRes = virAttrHandler.fillVirtual(subject, vAttrsToBeRemoved == null
 +                ? Collections.<String>emptySet()
 +                : vAttrsToBeRemoved, vAttrsToBeUpdated == null
 +                        ? Collections.<AttrMod>emptySet()
 +                        : vAttrsToBeUpdated, attrUtilsFactory.getInstance(subject));
 +
 +        // SYNCOPE-458 fill membership virtual attributes
 +        Collection<String> resourceNames;
 +        if (subject instanceof User) {
 +            User user = (User) subject;
 +            resourceNames = userDAO.findAllResourceNames(user);
 +            for (final Membership membership : user.getMemberships()) {
 +                if (membership.getVirAttrs() != null && !membership.getVirAttrs().isEmpty()) {
-                     final MembershipMod membershipMod = CollectionUtils.find(membershipsToAdd,
-                             new Predicate<MembershipMod>() {
- 
-                                 @Override
-                                 public boolean evaluate(final MembershipMod membershipMod) {
-                                     return membershipMod.getGroup() == membership.getGroup().getKey();
-                                 }
-                             });
-                     if (membershipMod != null) {
-                         virAttrHandler.fillVirtual(membership, membershipMod.getVirAttrsToRemove() == null
++                    MembershipMod membMod = CollectionUtils.find(membershipsToAdd, new Predicate<MembershipMod>() {
++
++                        @Override
++                        public boolean evaluate(final MembershipMod membershipMod) {
++                            return membershipMod.getGroup() == membership.getGroup().getKey();
++                        }
++                    });
++                    if (membMod != null) {
++                        virAttrHandler.fillVirtual(membership, membMod.getVirAttrsToRemove() == null
 +                                ? Collections.<String>emptySet()
-                                 : membershipMod.getVirAttrsToRemove(),
-                                 membershipMod.getVirAttrsToUpdate() == null ? Collections.<AttrMod>emptySet()
-                                         : membershipMod.getVirAttrsToUpdate(), attrUtilsFactory.getInstance(
++                                : membMod.getVirAttrsToRemove(),
++                                membMod.getVirAttrsToUpdate() == null ? Collections.<AttrMod>emptySet()
++                                        : membMod.getVirAttrsToUpdate(), attrUtilsFactory.getInstance(
 +                                        AttributableType.MEMBERSHIP));
 +                    }
 +                }
 +            }
 +        } else {
 +            resourceNames = subject.getResourceNames();
 +        }
 +
 +        if (propByRes == null || propByRes.isEmpty()) {
 +            localPropByRes.addAll(ResourceOperation.UPDATE, resourceNames);
 +        } else {
 +            localPropByRes.merge(propByRes);
 +        }
 +
 +        if (noPropResourceNames != null) {
 +            localPropByRes.removeAll(noPropResourceNames);
 +        }
 +
 +        Map<String, AttrMod> vAttrsToBeUpdatedMap = null;
 +        if (vAttrsToBeUpdated != null) {
 +            vAttrsToBeUpdatedMap = new HashMap<>();
 +            for (AttrMod attrMod : vAttrsToBeUpdated) {
 +                vAttrsToBeUpdatedMap.put(attrMod.getSchema(), attrMod);
 +            }
 +        }
 +
 +        // SYNCOPE-458 fill membership virtual attributes to be updated map
 +        Map<String, AttrMod> membVAttrsToBeUpdatedMap = new HashMap<>();
 +        for (MembershipMod membershipMod : membershipsToAdd) {
 +            for (AttrMod attrMod : membershipMod.getVirAttrsToUpdate()) {
 +                membVAttrsToBeUpdatedMap.put(attrMod.getSchema(), attrMod);
 +            }
 +        }
 +
 +        // SYNCOPE-458 fill membership virtual attributes to be removed set
 +        final Set<String> membVAttrsToBeRemoved = new HashSet<>();
 +        for (MembershipMod membershipMod : membershipsToAdd) {
 +            membVAttrsToBeRemoved.addAll(membershipMod.getVirAttrsToRemove());
 +        }
 +
 +        return createTasks(subject, password, changePwd,
 +                vAttrsToBeRemoved, vAttrsToBeUpdatedMap, membVAttrsToBeRemoved, membVAttrsToBeUpdatedMap, enable, false,
 +                localPropByRes);
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getUserDeleteTasks(final Long userKey, final Collection<String> noPropResourceNames) {
 +
 +        User user = userDAO.authFetch(userKey);
 +        return getDeleteTaskIds(user, userDAO.findAllResourceNames(user), noPropResourceNames);
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getUserDeleteTasks(
 +            final Long userKey, final Set<String> resourceNames, final Collection<String> noPropResourceNames) {
 +
 +        User user = userDAO.authFetch(userKey);
 +        return getDeleteTaskIds(user, resourceNames, noPropResourceNames);
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getUserDeleteTasks(final WorkflowResult<Long> wfResult) {
 +        User user = userDAO.authFetch(wfResult.getResult());
 +        return createTasks(user, null, false, null, null, null, null, false, true, wfResult.getPropByRes());
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getGroupDeleteTasks(final Long groupKey) {
 +
 +        return getGroupDeleteTasks(groupKey, Collections.<String>emptySet());
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getGroupDeleteTasks(final Long groupKey, final String noPropResourceName) {
 +
 +        return getGroupDeleteTasks(groupKey, Collections.<String>singleton(noPropResourceName));
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getGroupDeleteTasks(
 +            final Long groupKey, final Collection<String> noPropResourceNames) {
 +
 +        Group group = groupDAO.authFetch(groupKey);
 +        return getDeleteTaskIds(group, group.getResourceNames(), noPropResourceNames);
 +    }
 +
 +    @Override
 +    public List<PropagationTask> getGroupDeleteTasks(
 +            final Long groupKey, final Set<String> resourceNames, final Collection<String> noPropResourceNames) {
 +
 +        Group group = groupDAO.authFetch(groupKey);
 +        return getDeleteTaskIds(group, resourceNames, noPropResourceNames);
 +    }
 +
 +    protected List<PropagationTask> getDeleteTaskIds(
 +            final Subject<?, ?, ?> subject,
 +            final Collection<String> resourceNames,
 +            final Collection<String> noPropResourceNames) {
 +
-         final PropagationByResource propByRes = new PropagationByResource();
++        PropagationByResource propByRes = new PropagationByResource();
 +        propByRes.set(ResourceOperation.DELETE, resourceNames);
 +        if (noPropResourceNames != null && !noPropResourceNames.isEmpty()) {
 +            propByRes.get(ResourceOperation.DELETE).removeAll(noPropResourceNames);
 +        }
 +        return createTasks(subject, null, false, null, null, null, null, false, true, propByRes);
 +    }
 +
 +    /**
 +     * Create propagation tasks.
 +     *
 +     * @param subject user / group to be provisioned
 +     * @param password cleartext password to be provisioned
 +     * @param changePwd whether password should be included for propagation attributes or not
 +     * @param vAttrsToBeRemoved virtual attributes to be removed
 +     * @param vAttrsToBeUpdated virtual attributes to be added
 +     * @param membVAttrsToBeRemoved membership virtual attributes to be removed
 +     * @param membVAttrsToBeUpdatedMap membership virtual attributes to be added
 +     * @param enable whether user must be enabled or not
 +     * @param deleteOnResource whether user / group 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> createTasks(final Subject<?, ?, ?> subject,
 +            final String password, final boolean changePwd,
 +            final Set<String> vAttrsToBeRemoved, final Map<String, AttrMod> vAttrsToBeUpdated,
 +            final Set<String> membVAttrsToBeRemoved, final Map<String, AttrMod> membVAttrsToBeUpdatedMap,
 +            final Boolean enable, final boolean deleteOnResource, final PropagationByResource propByRes) {
 +
 +        LOG.debug("Provisioning subject {}:\n{}", subject, propByRes);
 +
 +        final AttributableUtils attrUtils = attrUtilsFactory.getInstance(subject);
 +
 +        if (!propByRes.get(ResourceOperation.CREATE).isEmpty()
 +                && vAttrsToBeRemoved != null && vAttrsToBeUpdated != null) {
 +
 +            connObjectUtils.retrieveVirAttrValues(subject, attrUtils);
 +
 +            // update vAttrsToBeUpdated as well
 +            for (VirAttr virAttr : subject.getVirAttrs()) {
 +                final String schema = virAttr.getSchema().getKey();
 +
 +                final AttrMod attributeMod = new AttrMod();
 +                attributeMod.setSchema(schema);
 +                attributeMod.getValuesToBeAdded().addAll(virAttr.getValues());
 +
 +                vAttrsToBeUpdated.put(schema, attributeMod);
 +            }
 +        }
 +
 +        // Avoid duplicates - see javadoc
 +        propByRes.purge();
 +        LOG.debug("After purge: {}", propByRes);
 +
-         final List<PropagationTask> tasks = new ArrayList<>();
++        List<PropagationTask> tasks = new ArrayList<>();
 +
 +        for (ResourceOperation operation : ResourceOperation.values()) {
 +            for (String resourceName : propByRes.get(operation)) {
 +                final ExternalResource resource = resourceDAO.find(resourceName);
 +                if (resource == null) {
 +                    LOG.error("Invalid resource name specified: {}, ignoring...", resourceName);
 +                } else if (attrUtils.getMappingItems(resource, MappingPurpose.PROPAGATION).isEmpty()) {
 +                    LOG.warn("Requesting propagation for {} but no propagation mapping provided for {}",
 +                            attrUtils.getType(), resource);
 +                } else {
 +                    PropagationTask task = entityFactory.newEntity(PropagationTask.class);
 +                    task.setResource(resource);
 +                    task.setObjectClassName(connObjectUtils.fromSubject(subject).getObjectClassValue());
 +                    task.setSubjectType(attrUtils.getType());
 +                    if (!deleteOnResource) {
 +                        task.setSubjectKey(subject.getKey());
 +                    }
 +                    task.setPropagationOperation(operation);
 +                    task.setPropagationMode(resource.getPropagationMode());
 +                    task.setOldAccountId(propByRes.getOldAccountId(resource.getKey()));
 +
 +                    Pair<String, Set<Attribute>> preparedAttrs = MappingUtils.prepareAttributes(attrUtils, subject,
 +                            password, changePwd, vAttrsToBeRemoved, vAttrsToBeUpdated, membVAttrsToBeRemoved,
 +                            membVAttrsToBeUpdatedMap, enable, resource);
 +                    task.setAccountId(preparedAttrs.getKey());
 +
 +                    // Check if any of mandatory attributes (in the mapping) is missing or not received any value: 
 +                    // if so, add special attributes that will be evaluated by PropagationTaskExecutor
 +                    List<String> mandatoryMissing = new ArrayList<>();
 +                    List<String> mandatoryNullOrEmpty = new ArrayList<>();
 +                    for (MappingItem item : attrUtils.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
 +                        if (!item.isAccountid()
 +                                && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), subject)) {
 +
 +                            Attribute attr = AttributeUtil.find(item.getExtAttrName(), preparedAttrs.getValue());
 +                            if (attr == null) {
 +                                mandatoryMissing.add(item.getExtAttrName());
 +                            } else if (attr.getValue() == null || attr.getValue().isEmpty()) {
 +                                mandatoryNullOrEmpty.add(item.getExtAttrName());
 +                            }
 +                        }
 +                    }
 +                    if (!mandatoryMissing.isEmpty()) {
 +                        preparedAttrs.getValue().add(AttributeBuilder.build(
 +                                PropagationTaskExecutor.MANDATORY_MISSING_ATTR_NAME, mandatoryMissing));
 +                    }
 +                    if (!mandatoryNullOrEmpty.isEmpty()) {
 +                        preparedAttrs.getValue().add(AttributeBuilder.build(
 +                                PropagationTaskExecutor.MANDATORY_NULL_OR_EMPTY_ATTR_NAME, mandatoryNullOrEmpty));
 +                    }
 +
 +                    task.setAttributes(preparedAttrs.getValue());
 +                    tasks.add(task);
 +
 +                    LOG.debug("PropagationTask created: {}", task);
 +                }
 +            }
 +        }
 +
 +        return tasks;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/22a9e12e/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
----------------------------------------------------------------------
diff --cc core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
index 4fe02ba,0000000..3c910fa
mode 100644,000000..100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
@@@ -1,134 -1,0 +1,134 @@@
 +/*
 + * 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.rest.cxf.service;
 +
 +import java.io.IOException;
 +import java.io.OutputStream;
 +import java.net.URI;
 +import java.util.List;
 +import javax.ws.rs.core.HttpHeaders;
 +import javax.ws.rs.core.Response;
 +import javax.ws.rs.core.StreamingOutput;
 +import org.apache.syncope.common.lib.to.PagedResult;
 +import org.apache.syncope.common.lib.to.ReportExecTO;
 +import org.apache.syncope.common.lib.to.ReportTO;
 +import org.apache.syncope.common.lib.types.JobAction;
 +import org.apache.syncope.common.lib.types.JobStatusType;
 +import org.apache.syncope.common.lib.types.ReportExecExportFormat;
 +import org.apache.syncope.common.lib.wrap.ReportletConfClass;
 +import org.apache.syncope.common.rest.api.CollectionWrapper;
 +import org.apache.syncope.common.rest.api.RESTHeaders;
 +import org.apache.syncope.common.rest.api.beans.ListQuery;
 +import org.apache.syncope.common.rest.api.service.ReportService;
 +import org.apache.syncope.core.logic.ReportLogic;
 +import org.apache.syncope.core.persistence.api.entity.ReportExec;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Service;
 +
 +@Service
 +public class ReportServiceImpl extends AbstractServiceImpl implements ReportService {
 +
 +    @Autowired
 +    private ReportLogic logic;
 +
 +    @Override
 +    public Response create(final ReportTO reportTO) {
 +        ReportTO createdReportTO = logic.create(reportTO);
 +        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(createdReportTO.getKey())).build();
 +        return Response.created(location).
 +                header(RESTHeaders.RESOURCE_ID, createdReportTO.getKey()).
 +                build();
 +    }
 +
 +    @Override
 +    public void update(final Long reportKey, final ReportTO reportTO) {
 +        reportTO.setKey(reportKey);
 +        logic.update(reportTO);
 +    }
 +
 +    @Override
 +    public PagedResult<ReportTO> list(final ListQuery listQuery) {
 +        return buildPagedResult(
 +                logic.list(
 +                        listQuery.getPage(),
 +                        listQuery.getSize(),
 +                        getOrderByClauses(listQuery.getOrderBy())),
 +                listQuery.getPage(),
 +                listQuery.getSize(),
 +                logic.count());
 +    }
 +
 +    @Override
 +    public List<ReportletConfClass> getReportletConfClasses() {
 +        return CollectionWrapper.wrap(logic.getReportletConfClasses(), ReportletConfClass.class);
 +    }
 +
 +    @Override
 +    public ReportTO read(final Long reportKey) {
 +        return logic.read(reportKey);
 +    }
 +
 +    @Override
 +    public ReportExecTO readExecution(final Long executionKey) {
 +        return logic.readExecution(executionKey);
 +    }
 +
 +    @Override
 +    public Response exportExecutionResult(final Long executionKey, final ReportExecExportFormat fmt) {
 +        final ReportExecExportFormat format = (fmt == null) ? ReportExecExportFormat.XML : fmt;
 +        final ReportExec reportExec = logic.getAndCheckReportExec(executionKey);
 +        StreamingOutput sout = new StreamingOutput() {
 +
 +            @Override
 +            public void write(final OutputStream os) throws IOException {
 +                logic.exportExecutionResult(os, reportExec, format);
 +            }
 +        };
 +        String disposition = "attachment; filename=" + reportExec.getReport().getName() + "." + format.name().
 +                toLowerCase();
 +        return Response.ok(sout).
 +                header(HttpHeaders.CONTENT_DISPOSITION, disposition).
 +                build();
 +    }
 +
 +    @Override
 +    public ReportExecTO execute(final Long reportKey) {
 +        return logic.execute(reportKey);
 +    }
 +
 +    @Override
 +    public void delete(final Long reportKey) {
 +        logic.delete(reportKey);
 +    }
 +
 +    @Override
 +    public void deleteExecution(final Long executionKey) {
 +        logic.deleteExecution(executionKey);
 +    }
 +
 +    @Override
-     public List<ReportExecTO> list(final JobStatusType type) {
-         return logic.list(type, ReportExecTO.class);
++    public List<ReportExecTO> listJobs(final JobStatusType type) {
++        return logic.listJobs(type, ReportExecTO.class);
 +    }
 +
 +    @Override
-     public void process(final JobAction action, final Long reportId) {
-         logic.process(action, reportId);
++    public void actionJob(final Long reportKey, final JobAction action) {
++        logic.actionJob(reportKey, action);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/22a9e12e/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
----------------------------------------------------------------------
diff --cc core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
index 957891a,0000000..9da72aa
mode 100644,000000..100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
@@@ -1,179 -1,0 +1,179 @@@
 +/*
 + * 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.rest.cxf.service;
 +
 +import java.net.URI;
 +import java.util.List;
 +import javax.ws.rs.BadRequestException;
 +import javax.ws.rs.core.Response;
 +import org.apache.syncope.common.lib.to.AbstractTaskTO;
 +import org.apache.syncope.common.lib.to.BulkAction;
 +import org.apache.syncope.common.lib.to.BulkActionResult;
 +import org.apache.syncope.common.lib.to.PagedResult;
 +import org.apache.syncope.common.lib.to.PushTaskTO;
 +import org.apache.syncope.common.lib.to.ReportExecTO;
 +import org.apache.syncope.common.lib.to.SchedTaskTO;
 +import org.apache.syncope.common.lib.to.SyncTaskTO;
 +import org.apache.syncope.common.lib.to.TaskExecTO;
 +import org.apache.syncope.common.lib.types.JobAction;
 +import org.apache.syncope.common.lib.types.JobStatusType;
 +import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
 +import org.apache.syncope.common.lib.types.TaskType;
 +import org.apache.syncope.common.rest.api.RESTHeaders;
 +import org.apache.syncope.common.rest.api.beans.ListQuery;
 +import org.apache.syncope.common.rest.api.service.TaskService;
 +import org.apache.syncope.core.logic.TaskLogic;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Service;
 +
 +@Service
 +public class TaskServiceImpl extends AbstractServiceImpl implements TaskService {
 +
 +    @Autowired
 +    private TaskLogic logic;
 +
 +    @Override
 +    public <T extends SchedTaskTO> Response create(final T taskTO) {
 +        T createdTask;
 +        if (taskTO instanceof SyncTaskTO || taskTO instanceof PushTaskTO || taskTO instanceof SchedTaskTO) {
 +            createdTask = logic.createSchedTask(taskTO);
 +        } else {
 +            throw new BadRequestException();
 +        }
 +
 +        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(createdTask.getKey())).build();
 +        return Response.created(location).
 +                header(RESTHeaders.RESOURCE_ID, createdTask.getKey()).
 +                build();
 +    }
 +
 +    @Override
 +    public void delete(final Long taskKey) {
 +        logic.delete(taskKey);
 +    }
 +
 +    @Override
 +    public void deleteExecution(final Long executionKey) {
 +        logic.deleteExecution(executionKey);
 +    }
 +
 +    @Override
 +    public TaskExecTO execute(final Long taskKey, final boolean dryRun) {
 +        return logic.execute(taskKey, dryRun);
 +    }
 +
 +    @SuppressWarnings("unchecked")
 +    @Override
 +    public <T extends AbstractTaskTO> PagedResult<T> list(final TaskType taskType, final ListQuery listQuery) {
 +        return (PagedResult<T>) buildPagedResult(
 +                logic.list(
 +                        taskType,
 +                        listQuery.getPage(),
 +                        listQuery.getSize(),
 +                        getOrderByClauses(listQuery.getOrderBy())),
 +                listQuery.getPage(),
 +                listQuery.getSize(),
 +                logic.count(taskType));
 +    }
 +
 +    @Override
 +    public <T extends AbstractTaskTO> T read(final Long taskKey) {
 +        return logic.read(taskKey);
 +    }
 +
 +    @Override
 +    public TaskExecTO readExecution(final Long executionKey) {
 +        return logic.readExecution(executionKey);
 +    }
 +
 +    @Override
 +    public void report(final Long executionKey, final ReportExecTO reportExec) {
 +        reportExec.setKey(executionKey);
 +        logic.report(
 +                executionKey, PropagationTaskExecStatus.fromString(reportExec.getStatus()), reportExec.getMessage());
 +    }
 +
 +    @Override
 +    public void update(final Long taskKey, final AbstractTaskTO taskTO) {
 +        taskTO.setKey(taskKey);
 +        if (taskTO instanceof SyncTaskTO) {
 +            logic.updateSync((SyncTaskTO) taskTO);
 +        } else if (taskTO instanceof SchedTaskTO) {
 +            logic.updateSched((SchedTaskTO) taskTO);
 +        } else {
 +            throw new BadRequestException();
 +        }
 +    }
 +
 +    @Override
 +    public BulkActionResult bulk(final BulkAction bulkAction) {
 +        BulkActionResult result = new BulkActionResult();
 +
 +        switch (bulkAction.getOperation()) {
 +            case DELETE:
 +                for (String taskKey : bulkAction.getTargets()) {
 +                    try {
 +                        result.add(logic.delete(Long.valueOf(taskKey)).getKey(), BulkActionResult.Status.SUCCESS);
 +                    } catch (Exception e) {
 +                        LOG.error("Error performing delete for task {}", taskKey, e);
 +                        result.add(taskKey, BulkActionResult.Status.FAILURE);
 +                    }
 +                }
 +                break;
 +
 +            case DRYRUN:
 +                for (String taskKey : bulkAction.getTargets()) {
 +                    try {
 +                        logic.execute(Long.valueOf(taskKey), true);
 +                        result.add(taskKey, BulkActionResult.Status.SUCCESS);
 +                    } catch (Exception e) {
 +                        LOG.error("Error performing dryrun for task {}", taskKey, e);
 +                        result.add(taskKey, BulkActionResult.Status.FAILURE);
 +                    }
 +                }
 +                break;
 +
 +            case EXECUTE:
 +                for (String taskKey : bulkAction.getTargets()) {
 +                    try {
 +                        logic.execute(Long.valueOf(taskKey), false);
 +                        result.add(taskKey, BulkActionResult.Status.SUCCESS);
 +                    } catch (Exception e) {
 +                        LOG.error("Error performing execute for task {}", taskKey, e);
 +                        result.add(taskKey, BulkActionResult.Status.FAILURE);
 +                    }
 +                }
 +                break;
 +
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
-     public List<TaskExecTO> list(final JobStatusType type) {
-         return logic.list(type, TaskExecTO.class);
++    public List<TaskExecTO> listJobs(final JobStatusType type) {
++        return logic.listJobs(type, TaskExecTO.class);
 +    }
 +
 +    @Override
-     public void process(final JobAction action, final Long taskId) {
-         logic.process(action, taskId);
++    public void actionJob(final Long taskKey, final JobAction action) {
++        logic.actionJob(taskKey, action);
 +    }
 +}


Mime
View raw message