syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [51/57] syncope git commit: [SYNCOPE-119] New security model implemented
Date Tue, 21 Apr 2015 09:34:20 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index b67f543..4929d62 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.logic;
 
-import org.apache.syncope.core.misc.security.UnauthorizedGroupException;
 import java.lang.reflect.Method;
 import java.security.AccessControlException;
 import java.util.ArrayList;
@@ -30,19 +29,17 @@ import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.mod.AttrMod;
 import org.apache.syncope.common.lib.mod.StatusMod;
 import org.apache.syncope.common.lib.mod.UserMod;
-import org.apache.syncope.common.lib.to.BulkAction;
-import org.apache.syncope.common.lib.to.BulkActionResult;
-import org.apache.syncope.common.lib.to.BulkActionResult.Status;
-import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.Entitlement;
 import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
@@ -57,7 +54,9 @@ import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 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.security.AuthContextUtil;
+import org.apache.syncope.core.misc.security.AuthContextUtils;
+import org.apache.syncope.core.misc.security.UnauthorizedException;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
@@ -114,25 +113,20 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
     @PreAuthorize("hasRole('USER_LIST')")
     @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
-    public int count() {
-        return userDAO.count(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()));
+    public int count(final List<String> realms) {
+        return userDAO.count(
+                getEffectiveRealms(AuthContextUtils.getAuthorizations().get(Entitlement.USER_LIST), realms));
     }
 
     @PreAuthorize("hasRole('USER_LIST')")
     @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
-    public int searchCount(final SearchCond searchCondition) {
-        return searchDAO.count(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()),
-                searchCondition, SubjectType.USER);
-    }
-
-    @PreAuthorize("hasRole('USER_LIST')")
-    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
-    @Override
-    public List<UserTO> list(final int page, final int size, final List<OrderByClause> orderBy) {
-        final Set<Long> adminGroupKeys = GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames());
+    public List<UserTO> list(
+            final int page, final int size, final List<OrderByClause> orderBy, final List<String> realms) {
 
-        return CollectionUtils.collect(userDAO.findAll(adminGroupKeys, page, size, orderBy),
+        return CollectionUtils.collect(userDAO.findAll(
+                getEffectiveRealms(AuthContextUtils.getAuthorizations().get(Entitlement.USER_LIST), realms),
+                page, size, orderBy),
                 new Transformer<User, UserTO>() {
 
                     @Override
@@ -142,11 +136,12 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
                 }, new ArrayList<UserTO>());
     }
 
-    @PreAuthorize("isAuthenticated() "
-            + "and not(hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
+    @PreAuthorize("isAuthenticated()")
     @Transactional(readOnly = true)
-    public UserTO readSelf() {
-        return binder.getAuthenticatedUserTO();
+    public Pair<String, UserTO> readSelf() {
+        return ImmutablePair.of(
+                POJOHelper.serialize(AuthContextUtils.getAuthorizations()),
+                binder.getAuthenticatedUserTO());
     }
 
     @PreAuthorize("hasRole('USER_READ')")
@@ -156,14 +151,23 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         return binder.getUserTO(key);
     }
 
-    @PreAuthorize("hasRole('USER_LIST')")
-    @Transactional(readOnly = true)
+    @PreAuthorize("hasRole('USER_SEARCH')")
+    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
+    @Override
+    public int searchCount(final SearchCond searchCondition, final List<String> realms) {
+        return searchDAO.count(
+                getEffectiveRealms(AuthContextUtils.getAuthorizations().get(Entitlement.USER_SEARCH), realms),
+                searchCondition, SubjectType.USER);
+    }
+
+    @PreAuthorize("hasRole('USER_SEARCH')")
+    @Transactional(readOnly = true, rollbackFor = { Throwable.class })
     @Override
     public List<UserTO> search(final SearchCond searchCondition, final int page, final int size,
-            final List<OrderByClause> orderBy) {
+            final List<OrderByClause> orderBy, final List<String> realms) {
 
-        final List<User> matchingUsers = searchDAO.search(GroupEntitlementUtil.getGroupKeys(AuthContextUtil.
-                getOwnedEntitlementNames()),
+        final List<User> matchingUsers = searchDAO.search(
+                getEffectiveRealms(AuthContextUtils.getAuthorizations().get(Entitlement.USER_SEARCH), realms),
                 searchCondition, page, size, orderBy, SubjectType.USER);
         return CollectionUtils.collect(matchingUsers, new Transformer<User, UserTO>() {
 
@@ -174,24 +178,22 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         }, new ArrayList<UserTO>());
     }
 
-    @PreAuthorize("isAnonymous() or hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+    @PreAuthorize("isAnonymous() or hasRole('ANONYMOUS')")
     public UserTO createSelf(final UserTO userTO, final boolean storePassword) {
         return doCreate(userTO, storePassword);
     }
 
     @PreAuthorize("hasRole('USER_CREATE')")
     public UserTO create(final UserTO userTO, final boolean storePassword) {
-        Collection<Long> requestGroupIds = CollectionUtils.removeAll(
-                CollectionUtils.collect(userTO.getMemberships(), new Transformer<MembershipTO, Long>() {
-
-                    @Override
-                    public Long transform(final MembershipTO membership) {
-                        return membership.getGroupId();
-                    }
-                }, new ArrayList<Long>()),
-                GroupEntitlementUtil.getGroupKeys(AuthContextUtil.getOwnedEntitlementNames()));
-        if (!requestGroupIds.isEmpty()) {
-            throw new UnauthorizedGroupException(requestGroupIds);
+        if (userTO.getRealm() == null) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
+            throw sce;
+        }
+        Set<String> effectiveRealms = getEffectiveRealms(
+                AuthContextUtils.getAuthorizations().get(Entitlement.USER_CREATE),
+                Collections.singleton(userTO.getRealm()));
+        if (effectiveRealms.isEmpty()) {
+            throw new UnauthorizedException(SubjectType.USER, null);
         }
 
         return doCreate(userTO, storePassword);
@@ -209,8 +211,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         return savedTO;
     }
 
-    @PreAuthorize("isAuthenticated() "
-            + "and not(hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
+    @PreAuthorize("isAuthenticated() and not(hasRole('ANONYMOUS'))")
     public UserTO updateSelf(final UserMod userMod) {
         UserTO userTO = binder.getAuthenticatedUserTO();
 
@@ -284,7 +285,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         return savedTO;
     }
 
-    @PreAuthorize("isAnonymous() or hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+    @PreAuthorize("isAnonymous() or hasRole('ANONYMOUS')")
     @Transactional
     public void requestPasswordReset(final String username, final String securityAnswer) {
         if (username == null) {
@@ -305,7 +306,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         provisioningManager.requestPasswordReset(user.getKey());
     }
 
-    @PreAuthorize("isAnonymous() or hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+    @PreAuthorize("isAnonymous() or hasRole('ANONYMOUS')")
     @Transactional
     public void confirmPasswordReset(final String token, final String password) {
         User user = userDAO.findByToken(token);
@@ -315,8 +316,7 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         provisioningManager.confirmPasswordReset(user, token, password);
     }
 
-    @PreAuthorize("isAuthenticated() "
-            + "and not(hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
+    @PreAuthorize("isAuthenticated() and not(hasRole('ANONYMOUS'))")
     public UserTO deleteSelf() {
         UserTO userTO = binder.getAuthenticatedUserTO();
 
@@ -354,59 +354,6 @@ public class UserLogic extends AbstractSubjectLogic<UserTO, UserMod> {
         return deletedTO;
     }
 
-    @PreAuthorize("(hasRole('USER_DELETE') and #bulkAction.operation == #bulkAction.operation.DELETE) or "
-            + "(hasRole('USER_UPDATE') and "
-            + "(#bulkAction.operation == #bulkAction.operation.REACTIVATE or "
-            + "#bulkAction.operation == #bulkAction.operation.SUSPEND))")
-    public BulkActionResult bulk(final BulkAction bulkAction) {
-        BulkActionResult res = new BulkActionResult();
-
-        switch (bulkAction.getOperation()) {
-            case DELETE:
-                for (String key : bulkAction.getTargets()) {
-                    try {
-                        res.add(delete(Long.valueOf(key)).getKey(), Status.SUCCESS);
-                    } catch (Exception e) {
-                        LOG.error("Error performing delete for user {}", key, e);
-                        res.add(key, Status.FAILURE);
-                    }
-                }
-                break;
-
-            case SUSPEND:
-                for (String key : bulkAction.getTargets()) {
-                    StatusMod statusMod = new StatusMod();
-                    statusMod.setKey(Long.valueOf(key));
-                    statusMod.setType(StatusMod.ModType.SUSPEND);
-                    try {
-                        res.add(status(statusMod).getKey(), Status.SUCCESS);
-                    } catch (Exception e) {
-                        LOG.error("Error performing suspend for user {}", key, e);
-                        res.add(key, Status.FAILURE);
-                    }
-                }
-                break;
-
-            case REACTIVATE:
-                for (String key : bulkAction.getTargets()) {
-                    StatusMod statusMod = new StatusMod();
-                    statusMod.setKey(Long.valueOf(key));
-                    statusMod.setType(StatusMod.ModType.REACTIVATE);
-                    try {
-                        res.add(status(statusMod).getKey(), Status.SUCCESS);
-                    } catch (Exception e) {
-                        LOG.error("Error performing reactivate for user {}", key, e);
-                        res.add(key, Status.FAILURE);
-                    }
-                }
-                break;
-
-            default:
-        }
-
-        return res;
-    }
-
     @PreAuthorize("hasRole('USER_UPDATE')")
     @Transactional(rollbackFor = { Throwable.class })
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
index d15eef9..69c95f0 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.logic;
 
 import java.lang.reflect.Method;
-import java.util.AbstractMap;
 import java.util.List;
-import java.util.Map;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.mod.AbstractAttributableMod;
 import org.apache.syncope.common.lib.mod.UserMod;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -70,9 +70,9 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         UserMod userMod = new UserMod();
         userMod.setKey(userTO.getKey());
 
-        List<PropagationTask> tasks = propagationManager.getUserUpdateTaskIds(
-                new WorkflowResult<Map.Entry<UserMod, Boolean>>(
-                        new AbstractMap.SimpleEntry<UserMod, Boolean>(userMod, null),
+        List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
+                new WorkflowResult<Pair<UserMod, Boolean>>(
+                        new ImmutablePair<UserMod, Boolean>(userMod, null),
                         updated.getPropByRes(), updated.getPerformedTasks()));
 
         taskExecutor.execute(tasks);
@@ -110,9 +110,9 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         if (updated.getResult() instanceof UserMod
                 && updated.getPropByRes() != null && !updated.getPropByRes().isEmpty()) {
 
-            List<PropagationTask> tasks = propagationManager.getUserUpdateTaskIds(
-                    new WorkflowResult<Map.Entry<UserMod, Boolean>>(
-                            new AbstractMap.SimpleEntry<>((UserMod) updated.getResult(), Boolean.TRUE),
+            List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
+                    new WorkflowResult<Pair<UserMod, Boolean>>(
+                            new ImmutablePair<>((UserMod) updated.getResult(), Boolean.TRUE),
                             updated.getPropByRes(),
                             updated.getPerformedTasks()));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java
index 88d42fd..9e40ff1 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java
@@ -31,7 +31,7 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 import org.apache.syncope.core.misc.AuditManager;
-import org.apache.syncope.core.misc.ExceptionUtil;
+import org.apache.syncope.core.misc.ExceptionUtils2;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
@@ -186,7 +186,7 @@ public class NotificationJob implements Job {
 
                     execution.setStatus(Status.NOT_SENT.name());
                     if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) {
-                        execution.setMessage(ExceptionUtil.getFullStackTrace(e));
+                        execution.setMessage(ExceptionUtils2.getFullStackTrace(e));
                     }
 
                     auditManager.audit(

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
index 38c96c6..d564335 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
@@ -22,8 +22,8 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.GroupReportletConf;
 import org.apache.syncope.common.lib.report.GroupReportletConf.Feature;
 import org.apache.syncope.common.lib.to.AbstractAttributableTO;
@@ -31,8 +31,6 @@ import org.apache.syncope.common.lib.to.AbstractSubjectTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
-import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -51,9 +49,6 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     private static final int PAGE_SIZE = 10;
 
     @Autowired
-    private EntitlementDAO entitlementDAO;
-
-    @Autowired
     private GroupDAO groupDAO;
 
     @Autowired
@@ -62,13 +57,14 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     @Autowired
     private GroupDataBinder groupDataBinder;
 
-    private List<Group> getPagedgroups(final int page) {
-        final Set<Long> adminGroupIds = GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
-        final List<Group> result;
+    private List<Group> getPagedGroups(final int page) {
+        List<Group> result;
+
         if (StringUtils.isBlank(conf.getMatchingCond())) {
-            result = groupDAO.findAll();
+            result = groupDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, page, PAGE_SIZE);
         } else {
-            result = searchDAO.search(adminGroupIds, SearchCondConverter.convert(conf.getMatchingCond()),
+            result = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
+                    SearchCondConverter.convert(conf.getMatchingCond()),
                     page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), SubjectType.GROUP);
         }
 
@@ -76,11 +72,9 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     }
 
     private int count() {
-        Set<Long> adminGroupIds = GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
-
         return StringUtils.isBlank(conf.getMatchingCond())
-                ? groupDAO.findAll().size()
-                : searchDAO.count(adminGroupIds,
+                ? groupDAO.count(SyncopeConstants.FULL_ADMIN_REALMS)
+                : searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
                         SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.GROUP);
     }
 
@@ -236,20 +230,6 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
 
             doExtractAttributes(handler, groupTO, conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs());
 
-            if (conf.getFeatures().contains(Feature.entitlements)) {
-                handler.startElement("", "", "entitlements", null);
-
-                for (String ent : groupTO.getEntitlements()) {
-                    atts.clear();
-
-                    atts.addAttribute("", "", "id", ReportXMLConst.XSD_STRING, String.valueOf(ent));
-
-                    handler.startElement("", "", "entitlement", atts);
-                    handler.endElement("", "", "entitlement");
-                }
-
-                handler.endElement("", "", "entitlements");
-            }
             // to get resources associated to a group
             if (conf.getFeatures().contains(Feature.resources)) {
                 doExtractResources(handler, groupTO);
@@ -322,7 +302,7 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     protected void doExtract(final ContentHandler handler) throws SAXException, ReportException {
         doExtractConf(handler);
         for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
-            doExtract(handler, getPagedgroups(i));
+            doExtract(handler, getPagedGroups(i));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java
index 7d03b61..e07612a 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java
@@ -40,7 +40,7 @@ import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
 import org.apache.syncope.core.logic.ReportLogic;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
-import org.apache.syncope.core.misc.ExceptionUtil;
+import org.apache.syncope.core.misc.ExceptionUtils2;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
 import org.quartz.JobExecutionContext;
@@ -167,7 +167,7 @@ public class ReportJob implements Job {
                                 ? e.getCause()
                                 : e;
                         reportExecutionMessage.
-                                append(ExceptionUtil.getFullStackTrace(t)).
+                                append(ExceptionUtils2.getFullStackTrace(t)).
                                 append("\n==================\n");
                     }
                 }
@@ -182,7 +182,7 @@ public class ReportJob implements Job {
             }
         } catch (Exception e) {
             execution.setStatus(ReportExecStatus.FAILURE);
-            reportExecutionMessage.append(ExceptionUtil.getFullStackTrace(e));
+            reportExecutionMessage.append(ExceptionUtils2.getFullStackTrace(e));
 
             throw new JobExecutionException(e, true);
         } finally {

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index f0023fc..02976f6 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -22,8 +22,8 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.UserReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
 import org.apache.syncope.common.lib.to.AbstractAttributableTO;
@@ -32,8 +32,6 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.persistence.api.GroupEntitlementUtil;
-import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
 import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -54,9 +52,6 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     private static final int PAGE_SIZE = 10;
 
     @Autowired
-    private EntitlementDAO entitlementDAO;
-
-    @Autowired
     private UserDAO userDAO;
 
     @Autowired
@@ -69,13 +64,13 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     private GroupDataBinder groupDataBinder;
 
     private List<User> getPagedUsers(final int page) {
-        final Set<Long> adminGroupIds = GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
+        List<User> result;
 
-        final List<User> result;
         if (StringUtils.isBlank(conf.getMatchingCond())) {
-            result = userDAO.findAll(adminGroupIds, page, PAGE_SIZE);
+            result = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, page, PAGE_SIZE);
         } else {
-            result = searchDAO.search(adminGroupIds, SearchCondConverter.convert(conf.getMatchingCond()),
+            result = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
+                    SearchCondConverter.convert(conf.getMatchingCond()),
                     page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), SubjectType.USER);
         }
 
@@ -83,11 +78,10 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     }
 
     private int count() {
-        Set<Long> adminGroupIds = GroupEntitlementUtil.getGroupKeys(entitlementDAO.findAll());
-
         return StringUtils.isBlank(conf.getMatchingCond())
-                ? userDAO.count(adminGroupIds)
-                : searchDAO.count(adminGroupIds, SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.USER);
+                ? userDAO.count(SyncopeConstants.FULL_ADMIN_REALMS)
+                : searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
+                        SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.USER);
     }
 
     private void doExtractResources(final ContentHandler handler, final AbstractSubjectTO subjectTO)
@@ -280,17 +274,18 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
                     atts.clear();
 
                     atts.addAttribute("", "", "id", ReportXMLConst.XSD_LONG, String.valueOf(memb.getKey()));
-                    atts.addAttribute("", "", "groupId", ReportXMLConst.XSD_LONG, String.valueOf(memb.getGroupId()));
-                    atts.addAttribute("", "", "groupName", ReportXMLConst.XSD_STRING, String.valueOf(memb.getGroupName()));
+                    atts.addAttribute("", "", "groupId", ReportXMLConst.XSD_LONG, String.valueOf(memb.getGroupKey()));
+                    atts.addAttribute("", "", "groupName", ReportXMLConst.XSD_STRING, String.
+                            valueOf(memb.getGroupName()));
                     handler.startElement("", "", "membership", atts);
 
                     doExtractAttributes(handler, memb, memb.getPlainAttrMap().keySet(), memb.getDerAttrMap()
                             .keySet(), memb.getVirAttrMap().keySet());
 
                     if (conf.getFeatures().contains(Feature.resources)) {
-                        Membership actualMemb = user.getMembership(memb.getGroupId());
+                        Membership actualMemb = user.getMembership(memb.getGroupKey());
                         if (actualMemb == null) {
-                            LOG.warn("Unexpected: cannot find membership for group {} for user {}", memb.getGroupId(),
+                            LOG.warn("Unexpected: cannot find membership for group {} for user {}", memb.getGroupKey(),
                                     user);
                         } else {
                             doExtractResources(handler, groupDataBinder.getGroupTO(actualMemb.getGroup()));

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/resources/report/groupReportlet2csv.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2csv.xsl b/core/logic/src/main/resources/report/groupReportlet2csv.xsl
index 06730dc..86fe635 100644
--- a/core/logic/src/main/resources/report/groupReportlet2csv.xsl
+++ b/core/logic/src/main/resources/report/groupReportlet2csv.xsl
@@ -62,18 +62,6 @@ under the License.
           <xsl:value-of select="$groupAttr/."/>
           <xsl:text>"</xsl:text>
         </xsl:when>
-        <xsl:when test="name($attrs/*[name(.)=$nameAttr]/*[name(.)='entitlement']) 
-                        and count($attrs/*[name(.)=$nameAttr]/node()) &gt; 0">
-          <xsl:text>"</xsl:text>       
-          <xsl:for-each select="$attrs/*/entitlement">
-            <xsl:variable name="value" select="@id"/>
-            <xsl:value-of select="$value"/>
-            <xsl:if test="position() != last()">
-              <xsl:value-of select="$delimiter"/>
-            </xsl:if>
-          </xsl:for-each>
-          <xsl:text>"</xsl:text>
-        </xsl:when>
         <xsl:when test="name($attrs/*[name(.)=$nameAttr]/*[name(.)='resource']) 
                         and count($attrs/*[name(.)=$nameAttr]/node()) &gt; 0">
           <xsl:text>"</xsl:text>       

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/resources/report/groupReportlet2fo.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2fo.xsl b/core/logic/src/main/resources/report/groupReportlet2fo.xsl
index c83eb31..e95d170 100644
--- a/core/logic/src/main/resources/report/groupReportlet2fo.xsl
+++ b/core/logic/src/main/resources/report/groupReportlet2fo.xsl
@@ -102,19 +102,6 @@ under the License.
         </xsl:otherwise>
       </xsl:choose>
       
-      <!--entitlements-->
-      <xsl:choose>
-        <xsl:when test="entitlements/entitlement">
-          <xsl:call-template name="entitlements">
-            <xsl:with-param name="label">Entitlements</xsl:with-param>
-            <xsl:with-param name="node" select="entitlements/entitlement"/>
-          </xsl:call-template>
-        </xsl:when>
-        <xsl:otherwise>
-          <fo:block color="red" font-size="9pt" space-after="3mm">THIS GROUP HASN'T ANY ENTITLEMENT</fo:block>
-        </xsl:otherwise>
-      </xsl:choose>
-      
       <xsl:choose>
         <xsl:when test="users/user">
           <fo:block font-size="11pt" font-weight="bold">Users</fo:block>
@@ -184,36 +171,6 @@ under the License.
       </fo:table-body>
     </fo:table>
   </xsl:template>
-  <!--entitlements template-->
-  <xsl:template name="entitlements">
-    <xsl:param name="label"/>
-    <xsl:param name="node"/>
-    <fo:block font-size="11pt" font-weight="bold" space-after="2mm" space-before="5mm">
-      <xsl:value-of select="$label"/>
-    </fo:block>
-    <fo:table table-layout="fixed" space-after="7mm">
-      <fo:table-column/>
-      <!--<fo:table-column/>-->
-      <fo:table-header>
-        <fo:table-row height="7mm" background-color="(#ccccba)">
-          <fo:table-cell>
-            <fo:block font-weight="bold">Name</fo:block>
-          </fo:table-cell>
-        </fo:table-row>
-      </fo:table-header>
-      <fo:table-body>
-        <xsl:for-each select="$node">
-          <fo:table-row height="4mm" background-color="(#ccccff)">
-            <fo:table-cell>
-              <fo:block>
-                <xsl:value-of select="@id"/>
-              </fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </xsl:for-each>
-      </fo:table-body>
-    </fo:table>
-  </xsl:template>
   
   <xsl:template name="groupResources">
     <xsl:param name="node"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/main/resources/report/groupReportlet2html.xsl
----------------------------------------------------------------------
diff --git a/core/logic/src/main/resources/report/groupReportlet2html.xsl b/core/logic/src/main/resources/report/groupReportlet2html.xsl
index ce36c6b..7e2a52f 100644
--- a/core/logic/src/main/resources/report/groupReportlet2html.xsl
+++ b/core/logic/src/main/resources/report/groupReportlet2html.xsl
@@ -88,18 +88,6 @@ under the License.
       </xsl:choose>
       
       <xsl:choose>
-        <xsl:when test="entitlements/entitlement">
-          <xsl:call-template name="entitlements">
-            <xsl:with-param name="label">Entitlements: </xsl:with-param>
-            <xsl:with-param name="node" select="entitlements/entitlement"/>
-          </xsl:call-template>
-        </xsl:when>
-        <xsl:otherwise>
-          <h5>THIS GROUP HASN'T ANY ENTITLEMENT</h5>
-        </xsl:otherwise>
-      </xsl:choose>
-      
-      <xsl:choose>
         <xsl:when test="users/user">
           <h4>Users</h4>
           <xsl:for-each select="users/user">
@@ -118,30 +106,6 @@ under the License.
       
     </xsl:for-each>
   </xsl:template>
- 
-  <!--entitlement template-->
-  <xsl:template name="entitlements">
-    <xsl:param name="label"/>
-    <xsl:param name="node"/>
-
-    <h4>
-      <xsl:value-of select="$label"/>
-    </h4>
-    
-    <table>
-      
-      <tbody>
-        <xsl:for-each select="$node">
-          <tr>
-            <td>
-              <xsl:value-of select="@id"/>
-            </td>
-          </tr>
-        </xsl:for-each>
-      </tbody>
-    </table>
-  </xsl:template>
-
 
   <xsl:template name="attributes">
     <xsl:param name="label"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java
----------------------------------------------------------------------
diff --git a/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java b/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java
index 4555189..47ea2a9 100644
--- a/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java
+++ b/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java
@@ -26,6 +26,7 @@ import com.icegreen.greenmail.util.GreenMail;
 import com.icegreen.greenmail.util.ServerSetup;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Random;
@@ -37,6 +38,8 @@ import javax.mail.Folder;
 import javax.mail.Message;
 import javax.mail.Session;
 import javax.mail.Store;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder;
@@ -47,22 +50,23 @@ import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.Entitlement;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
-import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
 import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtilFactory;
-import org.apache.syncope.core.persistence.api.entity.Entitlement;
+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.Notification;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainSchema;
 import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 import org.apache.syncope.core.logic.notification.NotificationJob;
+import org.apache.syncope.core.misc.security.SyncopeGrantedAuthority;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -77,7 +81,6 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
@@ -119,10 +122,10 @@ public class NotificationTest {
     private String adminUser;
 
     @Autowired
-    private EntitlementDAO entitlementDAO;
+    private NotificationDAO notificationDAO;
 
     @Autowired
-    private NotificationDAO notificationDAO;
+    private RealmDAO realmDAO;
 
     @Autowired
     private TaskDAO taskDAO;
@@ -155,7 +158,7 @@ public class NotificationTest {
     private EntityFactory entityFactory;
 
     @Autowired
-    private AttributableUtilFactory attrUtilFactory;
+    private AttributableUtilsFactory attrUtilsFactory;
 
     @BeforeClass
     public static void startGreenMail() {
@@ -190,6 +193,7 @@ public class NotificationTest {
         UserTO userTO = new UserTO();
         userTO.setPassword("password123");
         userTO.setUsername(uid);
+        userTO.setRealm("/even/two");
 
         userTO.getPlainAttrs().add(attributeTO("fullname", uid));
         userTO.getPlainAttrs().add(attributeTO("firstname", uid));
@@ -205,12 +209,16 @@ public class NotificationTest {
 
     @Before
     public void setupSecurity() {
-        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
-        for (Entitlement entitlement : entitlementDAO.findAll()) {
-            authorities.add(new SimpleGrantedAuthority(entitlement.getKey()));
-        }
+        List<GrantedAuthority> authorities = CollectionUtils.collect(Arrays.asList(Entitlement.values()),
+                new Transformer<Entitlement, GrantedAuthority>() {
+
+                    @Override
+                    public GrantedAuthority transform(final Entitlement entitlement) {
+                        return new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM);
+                    }
+                }, new ArrayList<GrantedAuthority>());
 
-        UserDetails userDetails = new User(adminUser, "FAKE_PASSWORD", true, true, true, true, authorities);
+        UserDetails userDetails = new User(adminUser, "FAKE_PASSWORD", authorities);
         Authentication authentication = new TestingAuthenticationToken(userDetails, "FAKE_PASSWORD", authorities);
         SecurityContextHolder.getContext().setAuthentication(authentication);
     }
@@ -279,7 +287,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -336,7 +344,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -389,7 +397,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -439,7 +447,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -447,7 +455,7 @@ public class NotificationTest {
         // 3. Set number of retries
         CPlainAttr maxRetries = entityFactory.newEntity(CPlainAttr.class);
         maxRetries.setSchema(plainSchemaDAO.find("notification.maxRetries", CPlainSchema.class));
-        maxRetries.addValue("5", attrUtilFactory.getInstance(AttributableType.CONFIGURATION));
+        maxRetries.addValue("5", attrUtilsFactory.getInstance(AttributableType.CONFIGURATION));
         confDAO.save(maxRetries);
         confDAO.flush();
 
@@ -476,7 +484,7 @@ public class NotificationTest {
         // 8. reset number of retries
         maxRetries = entityFactory.newEntity(CPlainAttr.class);
         maxRetries.setSchema(plainSchemaDAO.find("notification.maxRetries", CPlainSchema.class));
-        maxRetries.addValue("0", attrUtilFactory.getInstance(AttributableType.CONFIGURATION));
+        maxRetries.addValue("0", attrUtilsFactory.getInstance(AttributableType.CONFIGURATION));
         confDAO.save(maxRetries);
         confDAO.flush();
     }
@@ -510,7 +518,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -571,7 +579,7 @@ public class NotificationTest {
         // 2. create user
         UserTO userTO = getUniqueSampleTO(MAIL_ADDRESS);
         MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setGroupId(7);
+        membershipTO.setGroupKey(7);
         userTO.getMemberships().add(membershipTO);
 
         userLogic.create(userTO, true);
@@ -612,7 +620,7 @@ public class NotificationTest {
         // 2. create group
         GroupTO groupTO = new GroupTO();
         groupTO.setName("group446");
-        groupTO.setParent(1L);
+        groupTO.setRealm("/even/two");
 
         GroupTO createdGroup = groupLogic.create(groupTO);
         assertNotNull(createdGroup);

http://git-wip-us.apache.org/repos/asf/syncope/blob/65d652af/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtil.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtil.java b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtil.java
deleted file mode 100644
index 182e2c7..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtil.java
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * 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.misc;
-
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
-import org.apache.syncope.core.misc.security.PasswordGenerator;
-import org.apache.syncope.core.misc.security.SecureRandomUtil;
-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.lang3.StringUtils;
-import org.apache.syncope.common.lib.AttributableOperations;
-import org.apache.syncope.common.lib.mod.AbstractAttributableMod;
-import org.apache.syncope.common.lib.to.AbstractAttributableTO;
-import org.apache.syncope.common.lib.to.AbstractSubjectTO;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
-import org.apache.syncope.common.lib.to.MembershipTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.AttrSchemaType;
-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.PasswordPolicySpec;
-import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
-import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
-import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
-import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
-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.Attributable;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtil;
-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.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-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.SyncTask;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
-import org.apache.syncope.core.misc.security.Encryptor;
-import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
-import org.apache.syncope.core.misc.jexl.JexlUtil;
-import org.identityconnectors.common.Base64;
-import org.identityconnectors.common.security.GuardedByteArray;
-import org.identityconnectors.common.security.GuardedString;
-import org.identityconnectors.framework.common.objects.Attribute;
-import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.identityconnectors.framework.common.objects.ObjectClass;
-import org.identityconnectors.framework.common.objects.OperationOptions;
-import org.identityconnectors.framework.common.objects.Uid;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-@Component
-public class ConnObjectUtil {
-
-    /**
-     * Logger.
-     */
-    private static final Logger LOG = LoggerFactory.getLogger(ConnObjectUtil.class);
-
-    @Autowired
-    private PolicyDAO policyDAO;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private ExternalResourceDAO resourceDAO;
-
-    @Autowired
-    private PlainSchemaDAO plainSchemaDAO;
-
-    @Autowired
-    private PasswordGenerator pwdGen;
-
-    private final Encryptor encryptor = Encryptor.getInstance();
-
-    /**
-     * Virtual attribute cache.
-     */
-    @Autowired
-    private VirAttrCache virAttrCache;
-
-    public ObjectClass fromSubject(final Subject<?, ?, ?> subject) {
-        if (subject == null) {
-            throw new IllegalArgumentException("No ObjectClass could be provided for " + subject);
-        }
-
-        ObjectClass result = null;
-        if (subject instanceof User) {
-            result = ObjectClass.ACCOUNT;
-        }
-        if (subject instanceof Group) {
-            result = ObjectClass.GROUP;
-        }
-
-        return result;
-    }
-
-    /**
-     * Build a UserTO / GroupTO out of connector object attributes and schema mapping.
-     *
-     * @param obj connector object
-     * @param syncTask synchronization task
-     * @param attrUtil AttributableUtil
-     * @param <T> user/group
-     * @return UserTO for the user to be created
-     */
-    @Transactional(readOnly = true)
-    public <T extends AbstractSubjectTO> T getSubjectTO(final ConnectorObject obj, final SyncTask syncTask,
-            final AttributableUtil attrUtil) {
-
-        T subjectTO = getSubjectTOFromConnObject(obj, syncTask, attrUtil);
-
-        // (for users) if password was not set above, generate
-        if (subjectTO instanceof UserTO && StringUtils.isBlank(((UserTO) subjectTO).getPassword())) {
-            final UserTO userTO = (UserTO) subjectTO;
-
-            List<PasswordPolicySpec> ppSpecs = new ArrayList<>();
-
-            PasswordPolicy globalPP = policyDAO.getGlobalPasswordPolicy();
-            if (globalPP != null && globalPP.getSpecification(PasswordPolicySpec.class) != null) {
-                ppSpecs.add(globalPP.getSpecification(PasswordPolicySpec.class));
-            }
-
-            for (MembershipTO memb : userTO.getMemberships()) {
-                Group group = groupDAO.find(memb.getGroupId());
-                if (group != null && group.getPasswordPolicy() != null
-                        && group.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
-
-                    ppSpecs.add(group.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
-                }
-            }
-
-            for (String resName : userTO.getResources()) {
-                ExternalResource resource = resourceDAO.find(resName);
-                if (resource != null && resource.getPasswordPolicy() != null
-                        && resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
-
-                    ppSpecs.add(resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
-                }
-            }
-
-            String password;
-            try {
-                password = pwdGen.generate(ppSpecs);
-            } catch (InvalidPasswordPolicySpecException e) {
-                LOG.error("Could not generate policy-compliant random password for {}", userTO, e);
-
-                password = SecureRandomUtil.generateRandomPassword(16);
-            }
-            userTO.setPassword(password);
-        }
-
-        return subjectTO;
-    }
-
-    /**
-     * Build an UserMod out of connector object attributes and schema mapping.
-     *
-     * @param key user to be updated
-     * @param obj connector object
-     * @param original subject to get diff from
-     * @param syncTask synchronization task
-     * @param attrUtil AttributableUtil
-     * @param <T> user/group
-     * @return modifications for the user/group to be updated
-     */
-    @SuppressWarnings("unchecked")
-    @Transactional(readOnly = true)
-    public <T extends AbstractAttributableMod> T getAttributableMod(final Long key, final ConnectorObject obj,
-            final AbstractAttributableTO original, final SyncTask syncTask, final AttributableUtil attrUtil) {
-
-        final AbstractAttributableTO updated = getSubjectTOFromConnObject(obj, syncTask, attrUtil);
-        updated.setKey(key);
-
-        if (AttributableType.USER == attrUtil.getType()) {
-            // update password if and only if password is really changed
-            final User user = userDAO.authFetch(key);
-            if (StringUtils.isBlank(((UserTO) updated).getPassword())
-                    || encryptor.verify(((UserTO) updated).getPassword(),
-                            user.getCipherAlgorithm(), user.getPassword())) {
-
-                ((UserTO) updated).setPassword(null);
-            }
-
-            for (MembershipTO membTO : ((UserTO) updated).getMemberships()) {
-                Membership memb = user.getMembership(membTO.getGroupId());
-                if (memb != null) {
-                    membTO.setKey(memb.getKey());
-                }
-            }
-
-            return (T) AttributableOperations.diff(((UserTO) updated), ((UserTO) original), true);
-        }
-        if (AttributableType.GROUP == attrUtil.getType()) {
-            // reading from connector object cannot change entitlements
-            ((GroupTO) updated).getEntitlements().addAll(((GroupTO) original).getEntitlements());
-            return (T) AttributableOperations.diff(((GroupTO) updated), ((GroupTO) original), true);
-        }
-
-        return null;
-    }
-
-    private <T extends AbstractSubjectTO> T getSubjectTOFromConnObject(final ConnectorObject obj,
-            final SyncTask syncTask, final AttributableUtil attrUtil) {
-
-        final T subjectTO = attrUtil.newSubjectTO();
-
-        // 1. fill with data from connector object
-        for (MappingItem item : attrUtil.getUidToMappingItems(
-                syncTask.getResource(), MappingPurpose.SYNCHRONIZATION)) {
-
-            Attribute attribute = obj.getAttributeByName(item.getExtAttrName());
-
-            AttrTO attributeTO;
-            switch (item.getIntMappingType()) {
-                case UserId:
-                case GroupId:
-                    break;
-
-                case Password:
-                    if (subjectTO instanceof UserTO && attribute != null && attribute.getValue() != null
-                            && !attribute.getValue().isEmpty()) {
-
-                        ((UserTO) subjectTO).setPassword(getPassword(attribute.getValue().get(0)));
-                    }
-                    break;
-
-                case Username:
-                    if (subjectTO instanceof UserTO) {
-                        ((UserTO) subjectTO).setUsername(attribute == null || attribute.getValue().isEmpty()
-                                || attribute.getValue().get(0) == null
-                                        ? null
-                                        : attribute.getValue().get(0).toString());
-                    }
-                    break;
-
-                case GroupName:
-                    if (subjectTO instanceof GroupTO) {
-                        ((GroupTO) subjectTO).setName(attribute == null || attribute.getValue().isEmpty()
-                                || attribute.getValue().get(0) == null
-                                        ? null
-                                        : attribute.getValue().get(0).toString());
-                    }
-                    break;
-
-                case GroupOwnerSchema:
-                    if (subjectTO instanceof GroupTO && attribute != null) {
-                        // using a special attribute (with schema "", that will be ignored) for carrying the
-                        // GroupOwnerSchema value
-                        attributeTO = new AttrTO();
-                        attributeTO.setSchema(StringUtils.EMPTY);
-                        if (attribute.getValue().isEmpty() || attribute.getValue().get(0) == null) {
-                            attributeTO.getValues().add(StringUtils.EMPTY);
-                        } else {
-                            attributeTO.getValues().add(attribute.getValue().get(0).toString());
-                        }
-
-                        ((GroupTO) subjectTO).getPlainAttrs().add(attributeTO);
-                    }
-                    break;
-
-                case UserPlainSchema:
-                case GroupPlainSchema:
-                    attributeTO = new AttrTO();
-                    attributeTO.setSchema(item.getIntAttrName());
-
-                    PlainSchema schema = plainSchemaDAO.find(item.getIntAttrName(), attrUtil.plainSchemaClass());
-
-                    for (Object value : attribute == null || attribute.getValue() == null
-                            ? Collections.emptyList()
-                            : attribute.getValue()) {
-
-                        AttrSchemaType schemaType = schema == null ? AttrSchemaType.String : schema.getType();
-                        if (value != null) {
-                            final PlainAttrValue attrValue = attrUtil.newPlainAttrValue();
-                            switch (schemaType) {
-                                case String:
-                                    attrValue.setStringValue(value.toString());
-                                    break;
-
-                                case Binary:
-                                    attrValue.setBinaryValue((byte[]) value);
-                                    break;
-
-                                default:
-                                    try {
-                                        attrValue.parseValue(schema, value.toString());
-                                    } catch (ParsingValidationException e) {
-                                        LOG.error("While parsing provided value {}", value, e);
-                                        attrValue.setStringValue(value.toString());
-                                        schemaType = AttrSchemaType.String;
-                                    }
-                                    break;
-                            }
-                            attributeTO.getValues().add(attrValue.getValueAsString(schemaType));
-                        }
-                    }
-
-                    subjectTO.getPlainAttrs().add(attributeTO);
-                    break;
-
-                case UserDerivedSchema:
-                case GroupDerivedSchema:
-                    attributeTO = new AttrTO();
-                    attributeTO.setSchema(item.getIntAttrName());
-                    subjectTO.getDerAttrs().add(attributeTO);
-                    break;
-
-                case UserVirtualSchema:
-                case GroupVirtualSchema:
-                    attributeTO = new AttrTO();
-                    attributeTO.setSchema(item.getIntAttrName());
-
-                    for (Object value : attribute == null || attribute.getValue() == null
-                            ? Collections.emptyList()
-                            : attribute.getValue()) {
-
-                        if (value != null) {
-                            attributeTO.getValues().add(value.toString());
-                        }
-                    }
-
-                    subjectTO.getVirAttrs().add(attributeTO);
-                    break;
-
-                default:
-            }
-        }
-
-        // 2. add data from defined template (if any)
-        AbstractSubjectTO template = AttributableType.USER == attrUtil.getType()
-                ? syncTask.getUserTemplate() : syncTask.getGroupTemplate();
-
-        if (template != null) {
-            if (template instanceof UserTO) {
-                if (StringUtils.isNotBlank(((UserTO) template).getUsername())) {
-                    String evaluated = JexlUtil.evaluate(((UserTO) template).getUsername(), subjectTO);
-                    if (StringUtils.isNotBlank(evaluated)) {
-                        ((UserTO) subjectTO).setUsername(evaluated);
-                    }
-                }
-
-                if (StringUtils.isNotBlank(((UserTO) template).getPassword())) {
-                    String evaluated = JexlUtil.evaluate(((UserTO) template).getPassword(), subjectTO);
-                    if (StringUtils.isNotBlank(evaluated)) {
-                        ((UserTO) subjectTO).setPassword(evaluated);
-                    }
-                }
-
-                Map<Long, MembershipTO> currentMembs = ((UserTO) subjectTO).getMembershipMap();
-                for (MembershipTO membTO : ((UserTO) template).getMemberships()) {
-                    MembershipTO membTBU;
-                    if (currentMembs.containsKey(membTO.getGroupId())) {
-                        membTBU = currentMembs.get(membTO.getGroupId());
-                    } else {
-                        membTBU = new MembershipTO();
-                        membTBU.setGroupId(membTO.getGroupId());
-                        ((UserTO) subjectTO).getMemberships().add(membTBU);
-                    }
-                    fillFromTemplate(membTBU, membTO);
-                }
-            }
-            if (template instanceof GroupTO) {
-                if (StringUtils.isNotBlank(((GroupTO) template).getName())) {
-                    String evaluated = JexlUtil.evaluate(((GroupTO) template).getName(), subjectTO);
-                    if (StringUtils.isNotBlank(evaluated)) {
-                        ((GroupTO) subjectTO).setName(evaluated);
-                    }
-                }
-
-                if (((GroupTO) template).getParent() != 0) {
-                    final Group parentGroup = groupDAO.find(((GroupTO) template).getParent());
-                    if (parentGroup != null) {
-                        ((GroupTO) subjectTO).setParent(parentGroup.getKey());
-                    }
-                }
-
-                if (((GroupTO) template).getUserOwner() != null) {
-                    final User userOwner = userDAO.find(((GroupTO) template).getUserOwner());
-                    if (userOwner != null) {
-                        ((GroupTO) subjectTO).setUserOwner(userOwner.getKey());
-                    }
-                }
-                if (((GroupTO) template).getGroupOwner() != null) {
-                    final Group groupOwner = groupDAO.find(((GroupTO) template).getGroupOwner());
-                    if (groupOwner != null) {
-                        ((GroupTO) subjectTO).setGroupOwner(groupOwner.getKey());
-                    }
-                }
-
-                ((GroupTO) subjectTO).getEntitlements().addAll(((GroupTO) template).getEntitlements());
-
-                ((GroupTO) subjectTO).getGPlainAttrTemplates().addAll(((GroupTO) template).getGPlainAttrTemplates());
-                ((GroupTO) subjectTO).getGDerAttrTemplates().addAll(((GroupTO) template).getGDerAttrTemplates());
-                ((GroupTO) subjectTO).getGVirAttrTemplates().addAll(((GroupTO) template).getGVirAttrTemplates());
-                ((GroupTO) subjectTO).getMPlainAttrTemplates().addAll(((GroupTO) template).getMPlainAttrTemplates());
-                ((GroupTO) subjectTO).getMDerAttrTemplates().addAll(((GroupTO) template).getMDerAttrTemplates());
-                ((GroupTO) subjectTO).getMVirAttrTemplates().addAll(((GroupTO) template).getMVirAttrTemplates());
-
-                ((GroupTO) subjectTO).setAccountPolicy(((GroupTO) template).getAccountPolicy());
-                ((GroupTO) subjectTO).setPasswordPolicy(((GroupTO) template).getPasswordPolicy());
-
-                ((GroupTO) subjectTO).setInheritOwner(((GroupTO) template).isInheritOwner());
-                ((GroupTO) subjectTO).setInheritTemplates(((GroupTO) template).isInheritTemplates());
-                ((GroupTO) subjectTO).setInheritPlainAttrs(((GroupTO) template).isInheritPlainAttrs());
-                ((GroupTO) subjectTO).setInheritDerAttrs(((GroupTO) template).isInheritDerAttrs());
-                ((GroupTO) subjectTO).setInheritVirAttrs(((GroupTO) template).isInheritVirAttrs());
-                ((GroupTO) subjectTO).setInheritPasswordPolicy(((GroupTO) template).isInheritPasswordPolicy());
-                ((GroupTO) subjectTO).setInheritAccountPolicy(((GroupTO) template).isInheritAccountPolicy());
-            }
-
-            fillFromTemplate(subjectTO, template);
-
-            for (String resource : template.getResources()) {
-                subjectTO.getResources().add(resource);
-            }
-        }
-
-        return subjectTO;
-    }
-
-    /**
-     * Extract password value from passed value (if instance of GuardedString or GuardedByteArray).
-     *
-     * @param pwd received from the underlying connector
-     * @return password value
-     */
-    public String getPassword(final Object pwd) {
-        final StringBuilder result = new StringBuilder();
-
-        if (pwd instanceof GuardedString) {
-            ((GuardedString) pwd).access(new GuardedString.Accessor() {
-
-                @Override
-                public void access(final char[] clearChars) {
-                    result.append(clearChars);
-                }
-            });
-        } else if (pwd instanceof GuardedByteArray) {
-            ((GuardedByteArray) pwd).access(new GuardedByteArray.Accessor() {
-
-                @Override
-                public void access(final byte[] clearBytes) {
-                    result.append(new String(clearBytes));
-                }
-            });
-        } else if (pwd instanceof String) {
-            result.append((String) pwd);
-        } else {
-            result.append(pwd.toString());
-        }
-
-        return result.toString();
-    }
-
-    /**
-     * Get connector object TO from a connector object.
-     *
-     * @param connObject connector object.
-     * @return connector object TO.
-     */
-    public ConnObjectTO getConnObjectTO(final ConnectorObject connObject) {
-        final ConnObjectTO connObjectTO = new ConnObjectTO();
-
-        for (Attribute attr : connObject.getAttributes()) {
-            AttrTO attrTO = new AttrTO();
-            attrTO.setSchema(attr.getName());
-
-            if (attr.getValue() != null) {
-                for (Object value : attr.getValue()) {
-                    if (value != null) {
-                        if (value instanceof GuardedString || value instanceof GuardedByteArray) {
-                            attrTO.getValues().add(getPassword(value));
-                        } else if (value instanceof byte[]) {
-                            attrTO.getValues().add(Base64.encode((byte[]) value));
-                        } else {
-                            attrTO.getValues().add(value.toString());
-                        }
-                    }
-                }
-            }
-
-            connObjectTO.getPlainAttrs().add(attrTO);
-        }
-
-        return connObjectTO;
-    }
-
-    /**
-     * Query connected external resources for values to populated virtual attributes associated with the given owner.
-     *
-     * @param owner user or group
-     * @param attrUtil attributable util
-     */
-    public void retrieveVirAttrValues(final Attributable<?, ?, ?> owner, final AttributableUtil attrUtil) {
-        final ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext();
-        final ConnectorFactory connFactory = context.getBean(ConnectorFactory.class);
-
-        final IntMappingType type = attrUtil.getType() == AttributableType.USER
-                ? IntMappingType.UserVirtualSchema : attrUtil.getType() == AttributableType.GROUP
-                        ? IntMappingType.GroupVirtualSchema : IntMappingType.MembershipVirtualSchema;
-
-        final Map<String, ConnectorObject> externalResources = new HashMap<>();
-
-        // -----------------------
-        // Retrieve virtual attribute values if and only if they have not been retrieved yet
-        // -----------------------
-        for (VirAttr virAttr : owner.getVirAttrs()) {
-            // reset value set
-            if (virAttr.getValues().isEmpty()) {
-                retrieveVirAttrValue(owner, virAttr, attrUtil, type, externalResources, connFactory);
-            }
-        }
-        // -----------------------
-    }
-
-    private void retrieveVirAttrValue(
-            final Attributable<?, ?, ?> owner,
-            final VirAttr virAttr,
-            final AttributableUtil attrUtil,
-            final IntMappingType type,
-            final Map<String, ConnectorObject> externalResources,
-            final ConnectorFactory connFactory) {
-
-        final String schemaName = virAttr.getSchema().getKey();
-        final VirAttrCacheValue virAttrCacheValue = virAttrCache.get(attrUtil.getType(), owner.getKey(), schemaName);
-
-        LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
-
-        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
-            // cached ...
-            LOG.debug("Values found in cache {}", virAttrCacheValue);
-            virAttr.getValues().clear();
-            virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
-        } else {
-            // not cached ...
-            LOG.debug("Need one or more remote connections");
-
-            final VirAttrCacheValue toBeCached = new VirAttrCacheValue();
-
-            // SYNCOPE-458 if virattr owner is a Membership, owner must become user involved in membership because 
-            // membership mapping is contained in user mapping
-            final Subject<?, ?, ?> realOwner = owner instanceof Membership
-                    ? ((Membership) owner).getUser()
-                    : (Subject) owner;
-
-            final Set<ExternalResource> targetResources = owner instanceof Membership
-                    ? getTargetResource(virAttr, type, attrUtil, realOwner.getResources())
-                    : getTargetResource(virAttr, type, attrUtil);
-
-            for (ExternalResource resource : targetResources) {
-                LOG.debug("Search values into {}", resource.getKey());
-                try {
-                    final List<MappingItem> mappings = attrUtil.getMappingItems(resource, MappingPurpose.BOTH);
-
-                    final ConnectorObject connectorObject;
-
-                    if (externalResources.containsKey(resource.getKey())) {
-                        connectorObject = externalResources.get(resource.getKey());
-                    } else {
-                        LOG.debug("Perform connection to {}", resource.getKey());
-                        final String accountId = attrUtil.getAccountIdItem(resource) == null
-                                ? null
-                                : MappingUtil.getAccountIdValue(
-                                        realOwner, resource, attrUtil.getAccountIdItem(resource));
-
-                        if (StringUtils.isBlank(accountId)) {
-                            throw new IllegalArgumentException("No AccountId found for " + resource.getKey());
-                        }
-
-                        final Connector connector = connFactory.getConnector(resource);
-
-                        final OperationOptions oo =
-                                connector.getOperationOptions(MappingUtil.getMatchingMappingItems(mappings, type));
-
-                        connectorObject = connector.getObject(fromSubject(realOwner), new Uid(accountId), oo);
-                        externalResources.put(resource.getKey(), connectorObject);
-                    }
-
-                    if (connectorObject != null) {
-                        // ask for searched virtual attribute value
-                        final List<MappingItem> virAttrMappings =
-                                MappingUtil.getMatchingMappingItems(mappings, schemaName, type);
-
-                        // the same virtual attribute could be mapped with one or more external attribute 
-                        for (MappingItem mapping : virAttrMappings) {
-                            final Attribute attribute = connectorObject.getAttributeByName(mapping.getExtAttrName());
-
-                            if (attribute != null && attribute.getValue() != null) {
-                                for (Object obj : attribute.getValue()) {
-                                    if (obj != null) {
-                                        virAttr.getValues().add(obj.toString());
-                                    }
-                                }
-                            }
-                        }
-
-                        toBeCached.setResourceValues(resource.getKey(), new HashSet<String>(virAttr.getValues()));
-
-                        LOG.debug("Retrieved values {}", virAttr.getValues());
-                    }
-                } catch (Exception e) {
-                    LOG.error("Error reading connector object from {}", resource.getKey(), e);
-
-                    if (virAttrCacheValue != null) {
-                        toBeCached.forceExpiring();
-                        LOG.debug("Search for a cached value (even expired!) ...");
-                        final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
-                        if (cachedValues != null) {
-                            LOG.debug("Use cached value {}", cachedValues);
-                            virAttr.getValues().addAll(cachedValues);
-                            toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
-                        }
-                    }
-                }
-            }
-
-            virAttrCache.put(attrUtil.getType(), owner.getKey(), schemaName, toBeCached);
-        }
-    }
-
-    private Set<ExternalResource> getTargetResource(
-            final VirAttr attr, final IntMappingType type, final AttributableUtil attrUtil) {
-
-        final Set<ExternalResource> resources = new HashSet<>();
-
-        if (attr.getOwner() instanceof Subject) {
-            for (ExternalResource res : ((Subject<?, ?, ?>) attr.getOwner()).getResources()) {
-                if (!MappingUtil.getMatchingMappingItems(
-                        attrUtil.getMappingItems(res, MappingPurpose.BOTH),
-                        attr.getSchema().getKey(), type).isEmpty()) {
-
-                    resources.add(res);
-                }
-            }
-        }
-
-        return resources;
-    }
-
-    private Set<ExternalResource> getTargetResource(final VirAttr attr, final IntMappingType type,
-            final AttributableUtil attrUtil, final Set<? extends ExternalResource> ownerResources) {
-
-        final Set<ExternalResource> resources = new HashSet<>();
-
-        for (ExternalResource res : ownerResources) {
-            if (!MappingUtil.getMatchingMappingItems(
-                    attrUtil.getMappingItems(res, MappingPurpose.BOTH),
-                    attr.getSchema().getKey(), type).isEmpty()) {
-
-                resources.add(res);
-            }
-        }
-
-        return resources;
-    }
-
-    private void fillFromTemplate(final AbstractAttributableTO attributableTO, final AbstractAttributableTO template) {
-        Map<String, AttrTO> currentAttrMap = attributableTO.getPlainAttrMap();
-        for (AttrTO templateAttr : template.getPlainAttrs()) {
-            if (templateAttr.getValues() != null && !templateAttr.getValues().isEmpty()
-                    && (!currentAttrMap.containsKey(templateAttr.getSchema())
-                    || currentAttrMap.get(templateAttr.getSchema()).getValues().isEmpty())) {
-
-                attributableTO.getPlainAttrs().add(evaluateAttrTemplate(attributableTO, templateAttr));
-            }
-        }
-
-        currentAttrMap = attributableTO.getDerAttrMap();
-        for (AttrTO templateDerAttr : template.getDerAttrs()) {
-            if (!currentAttrMap.containsKey(templateDerAttr.getSchema())) {
-                attributableTO.getDerAttrs().add(templateDerAttr);
-            }
-        }
-
-        currentAttrMap = attributableTO.getVirAttrMap();
-        for (AttrTO templateVirAttr : template.getVirAttrs()) {
-            if (templateVirAttr.getValues() != null && !templateVirAttr.getValues().isEmpty()
-                    && (!currentAttrMap.containsKey(templateVirAttr.getSchema())
-                    || currentAttrMap.get(templateVirAttr.getSchema()).getValues().isEmpty())) {
-
-                attributableTO.getVirAttrs().add(evaluateAttrTemplate(attributableTO, templateVirAttr));
-            }
-        }
-    }
-
-    private AttrTO evaluateAttrTemplate(final AbstractAttributableTO attributableTO, final AttrTO template) {
-        AttrTO result = new AttrTO();
-        result.setSchema(template.getSchema());
-
-        if (template.getValues() != null && !template.getValues().isEmpty()) {
-            for (String value : template.getValues()) {
-                String evaluated = JexlUtil.evaluate(value, attributableTO);
-                if (StringUtils.isNotBlank(evaluated)) {
-                    result.getValues().add(evaluated);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Transform a
-     * <code>Collection</code> of {@link Attribute} instances into a {@link Map}. The key to each element in the map is
-     * the <i>name</i> of an
-     * <code>Attribute</code>. The value of each element in the map is the
-     * <code>Attribute</code> instance with that name. <br/> Different from the original because: <ul> <li>map keys are
-     * transformed toUpperCase()</li> <li>returned map is mutable</li> </ul>
-     *
-     * @param attributes set of attribute to transform to a map.
-     * @return a map of string and attribute.
-     *
-     * @see org.identityconnectors.framework.common.objects.AttributeUtil#toMap(java.util.Collection)
-     */
-    public Map<String, Attribute> toMap(final Collection<? extends Attribute> attributes) {
-        final Map<String, Attribute> map = new HashMap<>();
-        for (Attribute attr : attributes) {
-            map.put(attr.getName().toUpperCase(), attr);
-        }
-        return map;
-    }
-}


Mime
View raw message