You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2015/08/14 10:30:53 UTC

[24/31] syncope git commit: [SYNCOPE-652] More tests and console support

[SYNCOPE-652] More tests and console support


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/74aed4af
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/74aed4af
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/74aed4af

Branch: refs/heads/SYNCOPE-156
Commit: 74aed4af3b0ad072c7cab7e5b5eb196c050e7471
Parents: feba699
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Aug 13 12:30:38 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 13 17:16:51 2015 +0200

----------------------------------------------------------------------
 .../client/console/SyncopeConsoleSession.java   |  43 +++-
 .../syncope/client/console/pages/BasePage.java  |   5 +-
 .../syncope/client/console/pages/Login.java     |  49 +++++
 .../syncope/client/console/pages/Realms.java    |   4 -
 .../client/console/rest/BaseRestClient.java     |   3 -
 .../client/console/rest/RealmRestClient.java    |   2 +-
 .../syncope/client/console/pages/BasePage.html  |   7 +
 .../syncope/client/console/pages/Login.html     |   1 +
 .../syncope/common/lib/types/Entitlement.java   |   2 -
 .../apache/syncope/core/logic/DomainLogic.java  |  11 +-
 .../apache/syncope/core/logic/LoggerLogic.java  |   9 +-
 .../syncope/core/logic/ResourceLogic.java       |   4 -
 .../core/misc/policy/AccountPolicyEnforcer.java |   3 +-
 .../misc/policy/PasswordPolicyEnforcer.java     |   3 +-
 .../core/misc/policy/PolicyEnforcer.java        |  35 ---
 .../core/misc/security/AuthDataAccessor.java    |   4 +-
 .../core/misc/security/PasswordGenerator.java   |   4 +-
 .../core/persistence/jpa/inner/DomainTest.java  |  88 ++++++++
 .../src/test/resources/domains/TwoContent.xml   |  10 +
 fit/core-reference/src/main/webapp/db.jsp       |   3 +-
 .../fit/core/reference/AbstractITCase.java      |  19 +-
 .../fit/core/reference/AbstractTaskITCase.java  |  18 +-
 .../fit/core/reference/ConnectorITCase.java     |   7 +-
 .../fit/core/reference/DomainITCase.java        | 115 ++++++++++
 .../fit/core/reference/MultitenancyITCase.java  | 214 +++++++++++++++++++
 .../fit/core/reference/PushTaskITCase.java      |  20 +-
 .../fit/core/reference/SyncTaskITCase.java      |  35 +--
 27 files changed, 602 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
index 25394c7..8d71645 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java
@@ -19,19 +19,27 @@
 package org.apache.syncope.client.console;
 
 import java.text.DateFormat;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.MediaType;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.DomainTO;
 import org.apache.syncope.common.lib.to.SyncopeTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.DomainService;
 import org.apache.syncope.common.rest.api.service.SyncopeService;
 import org.apache.wicket.Session;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
@@ -51,12 +59,16 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession {
 
     private static final Logger LOG = LoggerFactory.getLogger(SyncopeConsoleSession.class);
 
-    private final SyncopeClientFactoryBean clientFactory;
-
     private final String version;
 
     private final SyncopeTO syncopeTO;
 
+    private final List<String> domains;
+
+    private String domain;
+
+    private final SyncopeClientFactoryBean clientFactory;
+
     private final Map<Class<?>, Object> services = Collections.synchronizedMap(new HashMap<Class<?>, Object>());
 
     private SyncopeClient client;
@@ -88,7 +100,18 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession {
 
         version = ctx.getBean("version", String.class);
 
-        syncopeTO = clientFactory.create(anonymousUser, anonymousKey).getService(SyncopeService.class).info();
+        SyncopeClient anonymousClient = clientFactory.create(anonymousUser, anonymousKey);
+        syncopeTO = anonymousClient.getService(SyncopeService.class).info();
+        domains = new ArrayList<>();
+        domains.add(SyncopeConstants.MASTER_DOMAIN);
+        CollectionUtils.collect(anonymousClient.getService(DomainService.class).list(),
+                new Transformer<DomainTO, String>() {
+
+                    @Override
+                    public String transform(final DomainTO domain) {
+                        return domain.getKey();
+                    }
+                }, domains);
     }
 
     public String getVersion() {
@@ -99,12 +122,24 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession {
         return syncopeTO;
     }
 
+    public List<String> getDomains() {
+        return domains;
+    }
+
+    public void setDomain(final String domain) {
+        this.domain = domain;
+    }
+
+    public String getDomain() {
+        return StringUtils.isBlank(domain) ? SyncopeConstants.MASTER_DOMAIN : domain;
+    }
+
     @Override
     public boolean authenticate(final String username, final String password) {
         boolean authenticated = false;
 
         try {
-            client = clientFactory.create(username, password);
+            client = clientFactory.setDomain(getDomain()).create(username, password);
 
             Pair<Map<String, Set<String>>, UserTO> self = client.self();
             auth = self.getKey();

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 20c3458..a6e737b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -92,11 +92,12 @@ public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
         liContainer = new WebMarkupContainer(getLIContainerId("realms"));
         add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("realms", Realms.class));
-        
+
         liContainer = new WebMarkupContainer(getLIContainerId("topology"));
         add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("topology", Topology.class));
-        
+
+        add(new Label("domain", SyncopeConsoleSession.get().getDomain()));
         add(new BookmarkablePageLink<Page>("logout", Logout.class));
 
         // set 'active' menu item

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
index 8421b00..8d9d5ff 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
@@ -21,8 +21,10 @@ package org.apache.syncope.client.console.pages;
 import java.security.AccessControlException;
 import java.util.Locale;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.NotificationPanel;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.authentication.IAuthenticationStrategy;
@@ -56,6 +58,8 @@ public class Login extends WebPage {
 
     private final DropDownChoice<Locale> languageSelect;
 
+    private final DropDownChoice<String> domainSelect;
+
     public Login(final PageParameters parameters) {
         super(parameters);
         setStatelessHint(true);
@@ -76,6 +80,12 @@ public class Login extends WebPage {
         languageSelect = new LocaleDropDown("language");
         form.add(languageSelect);
 
+        domainSelect = new DomainDropDown("domain");
+        if (SyncopeConsoleSession.get().getDomains().size() == 1) {
+            domainSelect.setOutputMarkupPlaceholderTag(true);
+        }
+        form.add(domainSelect);
+
         AjaxButton submitButton = new AjaxButton("submit", new Model<>(getString("submit"))) {
 
             private static final long serialVersionUID = 429178684321093953L;
@@ -157,4 +167,43 @@ public class Login extends WebPage {
         }
     }
 
+    /**
+     * Inner class which implements (custom) Domain DropDownChoice component.
+     */
+    private class DomainDropDown extends DropDownChoice<String> {
+
+        private static final long serialVersionUID = -7401167913360133325L;
+
+        public DomainDropDown(final String id) {
+            super(id, SyncopeConsoleSession.get().getDomains());
+
+            setModel(new IModel<String>() {
+
+                private static final long serialVersionUID = -1124206668056084806L;
+
+                @Override
+                public String getObject() {
+                    return SyncopeConsoleSession.get().getDomain();
+                }
+
+                @Override
+                public void setObject(final String object) {
+                    SyncopeConsoleSession.get().setDomain(object);
+                }
+
+                @Override
+                public void detach() {
+                    // Empty.
+                }
+            });
+
+            // set default value to Master Domain
+            getModel().setObject(SyncopeConstants.MASTER_DOMAIN);
+        }
+
+        @Override
+        protected boolean wantOnSelectionChangedNotifications() {
+            return true;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index daee99c..011d519 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -40,15 +40,11 @@ import org.apache.wicket.markup.repeater.RepeatingView;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.spring.injection.annot.SpringBean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class Realms extends BasePage {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    protected static final Logger LOG = LoggerFactory.getLogger(Realms.class);
-
     @SpringBean
     private RealmRestClient realmRestClient;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
index 17b2d4f..0e6fe2c 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
@@ -28,9 +28,6 @@ import org.slf4j.LoggerFactory;
 
 public abstract class BaseRestClient implements Serializable {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(BaseRestClient.class);
 
     private static final long serialVersionUID = 1523999867826481989L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
index 06cba4d..6ea095d 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/RealmRestClient.java
@@ -25,7 +25,7 @@ import org.apache.syncope.common.rest.api.service.RealmService;
 import org.springframework.stereotype.Component;
 
 /**
- * Console client for invoking Rest Group's services.
+ * Console client for invoking REST Realm's services.
  */
 @Component
 public class RealmRestClient extends BaseRestClient {

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
index b01e9d9..3a874b8 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
@@ -63,6 +63,13 @@ under the License.
           <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
             <span class="sr-only">Toggle navigation</span>
           </a>
+          <ul class="nav navbar-nav">
+            <li>
+              <a href="#" class="dropdown-toggle">
+                <span class="hidden-xs"><label wicket:id="domain"/></span>
+              </a>
+            </li>
+          </ul>
           <div class="navbar-custom-menu">
             <ul class="nav navbar-nav">
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/client/console/src/main/resources/org/apache/syncope/client/console/pages/Login.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Login.html b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Login.html
index 8eb150b..e6230db 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Login.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Login.html
@@ -51,6 +51,7 @@ under the License.
           <input type="password" wicket:id="password" id="password" class="form-control" 
                  wicket:message="placeholder:password" required="required" />
           <select wicket:id="language" id="language" class="selectpicker"/>
+          <select wicket:id="domain" id="domain" class="selectpicker"/>
           <button wicket:id="submit" type="submit" 
                   class="btn btn-lg btn-primary btn-block btn-signin"><wicket:message key="submit"/></button>
         </form>

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
index bf87c89..ccb4fce 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
@@ -28,8 +28,6 @@ public final class Entitlement {
 
     public static final String ANONYMOUS = "ANONYMOUS";
 
-    public static final String DOMAIN_LIST = "DOMAIN_LIST";
-
     public static final String DOMAIN_CREATE = "DOMAIN_CREATE";
 
     public static final String DOMAIN_READ = "DOMAIN_READ";

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
index 58f717d..c946fb1 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
@@ -27,6 +27,7 @@ import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.to.DomainTO;
 import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.DomainsHolder;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.DomainDAO;
 import org.apache.syncope.core.persistence.api.entity.Domain;
@@ -39,6 +40,9 @@ import org.springframework.stereotype.Component;
 public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
 
     @Autowired
+    private DomainsHolder domainsHolder;
+
+    @Autowired
     private DomainDataBinder binder;
 
     @Autowired
@@ -57,8 +61,7 @@ public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
         return binder.getDomainTO(domain);
     }
 
-    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_LIST + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    @PreAuthorize("isAuthenticated()")
     public List<DomainTO> list() {
         return CollectionUtils.collect(domainDAO.findAll(), new Transformer<Domain, DomainTO>() {
 
@@ -72,6 +75,10 @@ public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
     @PreAuthorize("hasRole('" + Entitlement.DOMAIN_CREATE + "') and authentication.details.domain == "
             + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
     public DomainTO create(final DomainTO domainTO) {
+        if (!domainsHolder.getDomains().keySet().contains(domainTO.getKey())) {
+            throw new NotFoundException("No configuration is available for domain '" + domainTO.getKey());
+        }
+
         return binder.getDomainTO(domainDAO.save(binder.create(domainTO)));
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
index d407dba..d7a4dd7 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
@@ -99,7 +99,8 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
         }, new ArrayList<LoggerTO>());
     }
 
-    @PreAuthorize("hasRole('" + Entitlement.LOG_LIST + "')")
+    @PreAuthorize("hasRole('" + Entitlement.LOG_LIST + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
     @Transactional(readOnly = true)
     public List<LoggerTO> listLogs() {
         return list(LoggerType.LOG);
@@ -165,7 +166,8 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
         return result;
     }
 
-    @PreAuthorize("hasRole('" + Entitlement.LOG_SET_LEVEL + "')")
+    @PreAuthorize("hasRole('" + Entitlement.LOG_SET_LEVEL + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
     public LoggerTO setLogLevel(final String name, final Level level) {
         return setLevel(name, level, LoggerType.LOG);
     }
@@ -206,7 +208,8 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
         return loggerToDelete;
     }
 
-    @PreAuthorize("hasRole('" + Entitlement.LOG_DELETE + "')")
+    @PreAuthorize("hasRole('" + Entitlement.LOG_DELETE + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
     public LoggerTO deleteLog(final String name) {
         return delete(name, LoggerType.LOG);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index df09b5f..f95f7ed 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -50,7 +50,6 @@ import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -89,9 +88,6 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
     @Autowired
     private ConnectorFactory connFactory;
 
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
     @PreAuthorize("hasRole('" + Entitlement.RESOURCE_CREATE + "')")
     public ResourceTO create(final ResourceTO resourceTO) {
         if (StringUtils.isBlank(resourceTO.getKey())) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
index 13ddc84..23740d6 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
@@ -25,11 +25,10 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.springframework.stereotype.Component;
 
 @Component
-public class AccountPolicyEnforcer implements PolicyEnforcer<AccountPolicySpec, User> {
+public class AccountPolicyEnforcer {
 
     private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+");
 
-    @Override
     public boolean enforce(final AccountPolicySpec policy, final PolicyType type, final User user) {
         if (user.getUsername() == null) {
             throw new PolicyEnforceException("Invalid account");

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
index 1313d2e..1458bf3 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
@@ -24,9 +24,8 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.springframework.stereotype.Component;
 
 @Component
-public class PasswordPolicyEnforcer implements PolicyEnforcer<PasswordPolicySpec, User> {
+public class PasswordPolicyEnforcer {
 
-    @Override
     public boolean enforce(final PasswordPolicySpec policy, final PolicyType type, final User user) {
         final String clearPassword = user.getClearPassword();
         final String password = user.getPassword();

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforcer.java
deleted file mode 100644
index 86e6583..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforcer.java
+++ /dev/null
@@ -1,35 +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.policy;
-
-import org.apache.syncope.common.lib.types.PolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-
-public interface PolicyEnforcer<T extends PolicySpec, E> {
-
-    /**
-     * Check the given entity to see if it conforms with the indicated policy.
-     *
-     * @param policy
-     * @param type
-     * @param entity
-     * @return whether user is to be suspended
-     */
-    boolean enforce(final T policy, final PolicyType type, final E entity);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
index 052cc30..f6324a1 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
@@ -44,7 +44,6 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.persistence.api.dao.DomainDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.Domain;
@@ -59,6 +58,7 @@ 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.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -110,7 +110,7 @@ public class AuthDataAccessor {
     public Domain findDomain(final String key) {
         Domain domain = domainDAO.find(key);
         if (domain == null) {
-            throw new NotFoundException("Could not find domain " + key);
+            throw new AuthenticationServiceException("Could not find domain " + key);
         }
         return domain;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
index 44635be..9514f27 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
@@ -56,9 +56,7 @@ public class PasswordGenerator {
     @Autowired
     private RealmDAO realmDAO;
 
-    public String generate(final List<PasswordPolicySpec> ppSpecs)
-            throws InvalidPasswordPolicySpecException {
-
+    public String generate(final List<PasswordPolicySpec> ppSpecs) throws InvalidPasswordPolicySpecException {
         PasswordPolicySpec policySpec = merge(ppSpecs);
 
         check(policySpec);

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DomainTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DomainTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DomainTest.java
new file mode 100644
index 0000000..a447f29
--- /dev/null
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DomainTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.persistence.jpa.inner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class DomainTest extends AbstractTest {
+
+    @Autowired
+    private DomainDAO domainDAO;
+
+    @Test
+    public void find() {
+        Domain two = domainDAO.find("Two");
+        assertNotNull(two);
+        assertEquals(CipherAlgorithm.SHA, two.getAdminCipherAlgorithm());
+
+        assertNull(domainDAO.find("none"));
+    }
+
+    @Test
+    public void findAll() {
+        List<Domain> list = domainDAO.findAll();
+        assertNotNull(list);
+        assertFalse(list.isEmpty());
+        for (Domain domain : list) {
+            assertNotNull(domain);
+        }
+    }
+
+    @Test
+    public void save() {
+        Domain domain = entityFactory.newEntity(Domain.class);
+        domain.setKey("new");
+        domain.setPassword("password", CipherAlgorithm.SSHA512);
+
+        Domain actual = domainDAO.save(domain);
+        assertNotNull(actual);
+        assertEquals(CipherAlgorithm.SSHA512, actual.getAdminCipherAlgorithm());
+        assertNotEquals("password", actual.getAdminPwd());
+    }
+
+    @Test
+    public void delete() {
+        Domain domain = entityFactory.newEntity(Domain.class);
+        domain.setKey("todelete");
+        domain.setPassword("password", CipherAlgorithm.SSHA512);
+
+        Domain actual = domainDAO.save(domain);
+        assertNotNull(actual);
+
+        String key = actual.getKey();
+        assertNotNull(domainDAO.find(key));
+
+        domainDAO.delete(key);
+        assertNull(domainDAO.find(key));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
index 92216fd..39cdae2 100644
--- a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
@@ -121,4 +121,14 @@ under the License.
                 traceLevel="FAILURES"/> 
   <Notification_events Notification_id="2" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>
 
+  <ConnInstance id="100" bundleName="net.tirasa.connid.bundles.ldap" displayName="LDAP"
+                location="${connid.location}"
+                connectorName="net.tirasa.connid.bundles.ldap.LdapConnector"
+                version="${connid.ldap.version}" 
+                jsonConf='[{"schema":{"name":"synchronizePasswords","displayName":"Enable Password Synchronization","helpMessage":"If true, the connector will synchronize passwords. The Password Capture Plugin needs to be installed for password synchronization to work.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"maintainLdapGroupMembership","displayName":"Maintain LDAP Group Membership","helpMessage":"When enabled and a user is renamed or deleted, update any LDAP groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"host","displayName":"Host","helpMessage":"The name or IP address of the host where the LDAP server is running.","type":"jav
 a.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["localhost"]},{"schema":{"name":"passwordHashAlgorithm","displayName":"Password Hash Algorithm","helpMessage":"Indicates the algorithm that the Identity system should use to hash the password. Currently supported values are SSHA, SHA, SSHA1, and SHA1. A blank value indicates that the system will not hash passwords. This will cause cleartext passwords to be stored in LDAP unless the LDAP server performs the hash (Netscape Directory Server and iPlanet Directory Server do).","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["SHA"]},{"schema":{"name":"blockSize","displayName":"Block Size","helpMessage":"The maximum number of accounts that can be in a block when retrieving accounts in blocks.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"valu
 es":[]},{"schema":{"name":"useBlocks","displayName":"Use Blocks","helpMessage":"When performing operations on large numbers of accounts, the accounts are processed in blocks to reduce the amount of memory used by the operation. Select this option to process accounts in blocks.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[false]},{"schema":{"name":"usePagedResultControl","displayName":"Use Paged Result Control","helpMessage":"When enabled, the LDAP Paged Results control is preferred over the VLV control when retrieving accounts.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"port","displayName":"TCP Port","helpMessage":"TCP/IP port number used to communicate with the LDAP server.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[1389]},{"schema":{"nam
 e":"vlvSortAttribute","displayName":"VLV Sort Attribute","helpMessage":"Specify the sort attribute to use for VLV indexes on the resource.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"statusManagementClass","displayName":"Status management class ","helpMessage":"Class to be used to manage enabled/disabled status. If no class is specified then identity status management wont be possible.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.ldap.commons.AttributeStatusManagement"]},{"schema":{"name":"accountObjectClasses","displayName":"Account Object Classes","helpMessage":"The object class or classes that will be used when creating new user objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to s
 eparate multiple object classes. Some object classes may require that you specify all object classes in the class hierarchy.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["inetOrgPerson"]},{"schema":{"name":"accountUserNameAttributes","displayName":"Account User Name Attributes","helpMessage":"Attribute or attributes which holds the account user name. They will be used when authenticating to find the LDAP entry for the user name to authenticate.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid"]},{"schema":{"name":"baseContextsToSynchronize","displayName":"Base Contexts to Synchronize","helpMessage":"One or more starting points in the LDAP tree that will be used to determine if a change should be synchronized. The base contexts attribute will be used to synchronize a change if this property is not set.","type":"[Lja
 va.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"accountSynchronizationFilter","displayName":"LDAP Filter for Accounts to Synchronize","helpMessage":"An optional LDAP filter for the objects to synchronize. Because the change log is for all objects, this filter updates only objects that match the specified filter. If you specify a filter, an object will be synchronized only if it matches the filter and includes a synchronized object class.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"removeLogEntryObjectClassFromFilter","displayName":"Remove Log Entry Object Class from Filter","helpMessage":"If this property is set (the default), the filter used to fetch change log entries does not contain the \"changeLogEntry\" object class, expecting that there are no entri
 es of other object types in the change log.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordDecryptionKey","displayName":"Password Decryption Key","helpMessage":"The key to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"readSchema","displayName":"Read Schema","helpMessage":"If true, the connector will read the schema from the server. If false, the connector will provide a default schema based on the object classes in the configuration. This property must be true in order to use extended object classes.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"ssl","displayName":"SSL","hel
 pMessage":"Select the check box to connect to the LDAP server using SSL.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordAttributeToSynchronize","displayName":"Password Attribute to Synchronize","helpMessage":"The name of the password attribute to synchronize when performing password synchronization.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"accountSearchFilter","displayName":"LDAP Filter for Retrieving Accounts","helpMessage":"An optional LDAP filter to control which accounts are returned from the LDAP resource. If no filter is specified, only accounts that include all specified object classes are returned.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=*"]},{"schema":{"name":"passwordDec
 ryptionInitializationVector","displayName":"Password Decryption Initialization Vector","helpMessage":"The initialization vector to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupMemberAttribute","displayName":"Group Member Attribute","helpMessage":"The name of the group attribute that will be updated with the distinguished name of the user when the user is added to the group.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"failover","displayName":"Failover Servers","helpMessage":"List all servers that should be used for failover in case the preferred server fails. If the preferred server fails, JNDI will connect to the next available server in the list. List all servers in the
  form of \"ldap://ldap.example.com:389/\", which follows the standard LDAP v3 URLs described in RFC 2255. Only the host and port parts of the URL are relevant in this setting.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"modifiersNamesToFilterOut","displayName":"Filter Out Changes By","helpMessage":"The names (DNs) of directory administrators to filter from the changes. Changes with the attribute \"modifiersName\" that match entries in this list will be filtered out. The standard value is the administrator name used by this adapter, to prevent loops. Entries should be of the format \"cn=Directory Manager\".","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupNameAttributes","displayName":"Group Name Attributes","helpMessage":"Attribute or attributes which holds the group nam
 e.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"respectResourcePasswordPolicyChangeAfterReset","displayName":"Respect Resource Password Policy Change-After-Reset","helpMessage":"When this resource is specified in a Login Module (i.e., this resource is a pass-through authentication target) and the resource password policy is configured for change-after-reset, a user whose resource account password has been administratively reset will be required to change that password after successfully authenticating.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overrida
 ble":false,"values":["false"]},{"schema":{"name":"filterWithOrInsteadOfAnd","displayName":"Filter with Or Instead of And","helpMessage":"Normally the the filter used to fetch change log entries is an and-based filter retrieving an interval of change entries. If this property is set, the filter will or together the required change numbers instead.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"principal","displayName":"Principal","helpMessage":"The distinguished name with which to authenticate to the LDAP server.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=admin,ou=system"]},{"schema":{"name":"changeLogBlockSize","displayName":"Change Log Block Size","helpMessage":"The number of change log entries to fetch per query.","type":"int","required":true,"order":0,"confidential":false,"defaultValues":null},
 "overridable":false,"values":[100]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"passwordAttribute","displayName":"Password Attribute","helpMessage":"The name of the LDAP attribute which holds the password. When changing an user password, the new password is set to this attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["userpassword"]},{"schema":{"name":"changeNumberAttribute","displayName":"Change Number Attribute","helpMessage":"The name of the change number attribute
  in the change log entry.","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["changeNumber"]},{"schema":{"name":"objectClassesToSynchronize","displayName":"Object Classes to Synchronize","helpMessage":"The object classes to synchronize. The change log is for all objects; this filters updates to just the listed object classes. You should not list the superclasses of an object class unless you intend to synchronize objects with any of the superclass values. For example, if only \"inetOrgPerson\" objects should be synchronized, but the superclasses of \"inetOrgPerson\" (\"person\", \"organizationalperson\" and \"top\") should be filtered out, then list only \"inetOrgPerson\" here. All objects in LDAP are subclassed from \"top\". For this reason, you should never list \"top\", otherwise no object would be filtered.","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},
 "overridable":false,"values":["inetOrgPerson","groupOfUniqueNames"]},{"schema":{"name":"credentials","displayName":"Password","helpMessage":"Password for the principal.","type":"org.identityconnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["secret"]},{"schema":{"name":"attributesToSynchronize","displayName":"Attributes to Synchronize","helpMessage":"The names of the attributes to synchronize. This ignores updates from the change log if they do not update any of the named attributes. For example, if only \"department\" is listed, then only changes that affect \"department\" will be processed. All other updates are ignored. If blank (the default), then all changes are processed.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"maintainPosixGroupMembership","displayName":"Maintain POSIX Group M
 embership","helpMessage":"When enabled and a user is renamed or deleted, update any POSIX groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["truemaintainLdapGroupMembership"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="100" capability="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capability="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capability="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capability="SEARCH"/>
+  
 </dataset>

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/main/webapp/db.jsp
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/webapp/db.jsp b/fit/core-reference/src/main/webapp/db.jsp
index 2a4c6ac..e54d33e 100644
--- a/fit/core-reference/src/main/webapp/db.jsp
+++ b/fit/core-reference/src/main/webapp/db.jsp
@@ -30,7 +30,6 @@ under the License.
         } catch (SQLException e) {
             getServletConfig().getServletContext().log("Could not start H2 web console (datastore)", e);
         }
-
-        response.sendRedirect("http://localhost:8082");
     }
+    response.sendRedirect("http://localhost:8082");
 %>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
index 7c36611..871155a 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
@@ -56,6 +56,7 @@ import org.apache.syncope.common.rest.api.service.AnyTypeService;
 import org.apache.syncope.common.rest.api.service.CamelRouteService;
 import org.apache.syncope.common.rest.api.service.ConfigurationService;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.common.rest.api.service.DomainService;
 import org.apache.syncope.common.rest.api.service.LoggerService;
 import org.apache.syncope.common.rest.api.service.NotificationService;
 import org.apache.syncope.common.rest.api.service.PolicyService;
@@ -86,20 +87,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 @ContextConfiguration(locations = { "classpath:testJDBCContext.xml" })
 public abstract class AbstractITCase {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractITCase.class);
 
     protected static final String ADMIN_UNAME = "admin";
 
     protected static final String ADMIN_PWD = "password";
 
-    private static final String ADDRESS = "http://localhost:9080/syncope/rest";
+    protected static final String ADDRESS = "http://localhost:9080/syncope/rest";
 
-    private static final String ENV_KEY_CONTENT_TYPE = "jaxrsContentType";
-
-    protected static final SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
+    protected static final String ENV_KEY_CONTENT_TYPE = "jaxrsContentType";
 
     protected static final String RESOURCE_NAME_WS1 = "ws-target-resource-1";
 
@@ -151,10 +147,14 @@ public abstract class AbstractITCase {
 
     protected static String ANONYMOUS_KEY;
 
+    protected static SyncopeClientFactoryBean clientFactory;
+
     protected static SyncopeClient adminClient;
 
     protected static SyncopeService syncopeService;
 
+    protected static DomainService domainService;
+
     protected static AnyTypeClassService anyTypeClassService;
 
     protected static AnyTypeService anyTypeService;
@@ -224,7 +224,9 @@ public abstract class AbstractITCase {
 
     @BeforeClass
     public static void restSetup() {
-        final String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
+        clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
+
+        String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
         if (StringUtils.isNotBlank(envContentType)) {
             clientFactory.setContentType(envContentType);
         }
@@ -233,6 +235,7 @@ public abstract class AbstractITCase {
         adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
 
         syncopeService = adminClient.getService(SyncopeService.class);
+        domainService = adminClient.getService(DomainService.class);
         anyTypeClassService = adminClient.getService(AnyTypeClassService.class);
         anyTypeService = adminClient.getService(AnyTypeService.class);
         relationshipTypeService = adminClient.getService(RelationshipTypeService.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
index 37bf12c..2d9dae1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
@@ -40,6 +40,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.TaskExecTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.rest.api.service.TaskService;
 
 public abstract class AbstractTaskITCase extends AbstractITCase {
 
@@ -51,16 +52,19 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
 
         private final AbstractTaskITCase test;
 
+        private final TaskService taskService;
+
         private final Long taskKey;
 
         private final int maxWaitSeconds;
 
         private final boolean dryRun;
 
-        public ThreadExec(
-                final AbstractTaskITCase test, final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+        public ThreadExec(final AbstractTaskITCase test, final TaskService taskService, final Long taskKey,
+                final int maxWaitSeconds, final boolean dryRun) {
 
             this.test = test;
+            this.taskService = taskService;
             this.taskKey = taskKey;
             this.maxWaitSeconds = maxWaitSeconds;
             this.dryRun = dryRun;
@@ -68,7 +72,7 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
 
         @Override
         public TaskExecTO call() throws Exception {
-            return test.execProvisioningTask(taskKey, maxWaitSeconds, dryRun);
+            return test.execProvisioningTask(taskService, taskKey, maxWaitSeconds, dryRun);
         }
     }
 
@@ -87,7 +91,9 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
         }
     }
 
-    protected TaskExecTO execProvisioningTask(final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+    public static TaskExecTO execProvisioningTask(
+            final TaskService taskService, final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+
         AbstractTaskTO taskTO = taskService.read(taskKey);
         assertNotNull(taskTO);
         assertNotNull(taskTO.getExecutions());
@@ -119,14 +125,14 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
         return taskTO.getExecutions().get(taskTO.getExecutions().size() - 1);
     }
 
-    protected Map<Long, TaskExecTO> execProvisioningTasks(
+    protected Map<Long, TaskExecTO> execProvisioningTasks(final TaskService taskService,
             final Set<Long> taskKeys, final int maxWaitSeconds, final boolean dryRun) throws Exception {
 
         ExecutorService service = Executors.newFixedThreadPool(taskKeys.size());
         List<Future<TaskExecTO>> futures = new ArrayList<>();
 
         for (Long key : taskKeys) {
-            futures.add(service.submit(new ThreadExec(this, key, maxWaitSeconds, dryRun)));
+            futures.add(service.submit(new ThreadExec(this, taskService, key, maxWaitSeconds, dryRun)));
         }
 
         Map<Long, TaskExecTO> res = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
index 583e3d9..44ebf33 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
@@ -193,7 +193,7 @@ public class ConnectorITCase extends AbstractITCase {
         assertNotNull(actual);
         assertEquals(EnumSet.of(ConnectorCapability.ONE_PHASE_CREATE, ConnectorCapability.TWO_PHASES_CREATE),
                 actual.getCapabilities());
-        assertEquals(10, actual.getPoolConf().getMaxObjects().intValue());
+        assertEquals(10, actual.getPoolConf().getMaxObjects(), 0);
 
         // check also for the deletion of the created object
         try {
@@ -232,7 +232,7 @@ public class ConnectorITCase extends AbstractITCase {
         connectorTO.setConnRequestTimeout(20);
 
         // set the connector configuration using PropertyTO
-        Set<ConnConfProperty> conf = new HashSet<ConnConfProperty>();
+        Set<ConnConfProperty> conf = new HashSet<>();
 
         ConnConfPropSchema endpointSchema = new ConnConfPropSchema();
         endpointSchema.setName("endpoint");
@@ -685,7 +685,7 @@ public class ConnectorITCase extends AbstractITCase {
 
     @Test
     public void bulkAction() {
-        final BulkAction bulkAction = new BulkAction();
+        BulkAction bulkAction = new BulkAction();
         bulkAction.setType(BulkAction.Type.DELETE);
 
         ConnInstanceTO conn = connectorService.read(101L);
@@ -727,7 +727,6 @@ public class ConnectorITCase extends AbstractITCase {
 
     @Test
     public void issueSYNCOPE605() {
-
         ConnInstanceTO connectorInstanceTO = connectorService.read(103L);
         assertTrue(connectorInstanceTO.getCapabilities().isEmpty());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/DomainITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/DomainITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/DomainITCase.java
new file mode 100644
index 0000000..e6b1984
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/DomainITCase.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core.reference;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.security.AccessControlException;
+import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.DomainTO;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class DomainITCase extends AbstractITCase {
+
+    @Test
+    public void list() {
+        List<DomainTO> domains = domainService.list();
+        assertNotNull(domains);
+        assertFalse(domains.isEmpty());
+        for (DomainTO domain : domains) {
+            assertNotNull(domain);
+        }
+    }
+
+    @Test
+    public void create() {
+        DomainTO domain = new DomainTO();
+        domain.setKey("last");
+        domain.setAdminCipherAlgorithm(CipherAlgorithm.SSHA512);
+        domain.setAdminPwd("password");
+
+        try {
+            domainService.create(domain);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+    }
+
+    @Test
+    public void update() {
+        DomainTO two = domainService.read("Two");
+        assertNotNull(two);
+        DomainTO origTwo = SerializationUtils.clone(two);
+
+        try {
+            // 1. change admin pwd for domain Two
+            two.setAdminCipherAlgorithm(CipherAlgorithm.AES);
+            two.setAdminPwd("password3");
+            domainService.update(two);
+
+            // 2. attempt to access with old pwd -> fail
+            try {
+                new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("Two").
+                        create(ADMIN_UNAME, "password2").self();
+            } catch (AccessControlException e) {
+                assertNotNull(e);
+            }
+
+            // 3. access with new pwd -> succeed
+            new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("Two").
+                    create(ADMIN_UNAME, "password3").self();
+        } finally {
+            // restore old password
+            domainService.create(origTwo);
+        }
+    }
+
+    @Test
+    public void delete() {
+        DomainTO two = domainService.read("Two");
+        assertNotNull(two);
+
+        try {
+            domainService.delete(two.getKey());
+
+            try {
+                domainService.read(two.getKey());
+                fail();
+            } catch (SyncopeClientException e) {
+                assertEquals(ClientExceptionType.NotFound, e.getType());
+            }
+        } finally {
+            // restore old password
+            two.setAdminPwd("password2");
+            domainService.create(two);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
new file mode 100644
index 0000000..dda5f52
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
@@ -0,0 +1,214 @@
+/*
+ * 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.fit.core.reference;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.security.AccessControlException;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.common.rest.api.service.DomainService;
+import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.rest.api.service.RealmService;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.common.rest.api.service.TaskService;
+import org.apache.syncope.common.rest.api.service.UserService;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class MultitenancyITCase extends AbstractITCase {
+
+    @BeforeClass
+    public static void restSetup() {
+        clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("Two");
+
+        String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
+        if (StringUtils.isNotBlank(envContentType)) {
+            clientFactory.setContentType(envContentType);
+        }
+        LOG.info("Performing IT with content type {}", clientFactory.getContentType().getMediaType());
+
+        adminClient = clientFactory.create(ADMIN_UNAME, "password2");
+    }
+
+    @Test
+    public void masterOnly() {
+        try {
+            adminClient.getService(DomainService.class).read("Two");
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        try {
+            adminClient.getService(LoggerService.class).list(LoggerType.LOG);
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        adminClient.getService(LoggerService.class).list(LoggerType.AUDIT);
+    }
+
+    @Test
+    public void readPlainSchemas() {
+        assertEquals(18, adminClient.getService(SchemaService.class).list(SchemaType.PLAIN).size());
+    }
+
+    @Test
+    public void readRealm() {
+        List<RealmTO> realms = adminClient.getService(RealmService.class).list();
+        assertEquals(1, realms.size());
+        assertEquals(SyncopeConstants.ROOT_REALM, realms.get(0).getName());
+    }
+
+    @Test
+    public void createUser() {
+        assertNull(adminClient.getService(RealmService.class).list().get(0).getPasswordPolicy());
+
+        UserTO user = new UserTO();
+        user.setRealm(SyncopeConstants.ROOT_REALM);
+        user.setUsername(getUUIDString());
+        user.setPassword("password");
+
+        Response response = adminClient.getService(UserService.class).create(user);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+
+        user = response.readEntity(UserTO.class);
+        assertNotNull(user);
+    }
+
+    @Test
+    public void createResourceAndSync() {
+        // read connector
+        ConnInstanceTO conn = adminClient.getService(ConnectorService.class).read(100L);
+        assertNotNull(conn);
+        assertEquals("LDAP", conn.getDisplayName());
+
+        // prepare resource
+        ResourceTO resource = new ResourceTO();
+        resource.setKey("new-ldap-resource");
+        resource.setConnector(conn.getKey());
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resource.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        mapping.setConnObjectLink("'uid=' + username + ',ou=people,o=isp'");
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntAttrName("username");
+        item.setIntMappingType(IntMappingType.Username);
+        item.setExtAttrName("cn");
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setPassword(true);
+        item.setIntMappingType(IntMappingType.Password);
+        item.setExtAttrName("userPassword");
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setMandatoryCondition("true");
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setExtAttrName("sn");
+        item.setMandatoryCondition("true");
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setIntAttrName("email");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setExtAttrName("mail");
+        mapping.add(item);
+
+        // create resource
+        Response response = adminClient.getService(ResourceService.class).create(resource);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        resource = adminClient.getService(ResourceService.class).read(resource.getKey());
+        assertNotNull(resource);
+
+        // create sync task
+        SyncTaskTO task = new SyncTaskTO();
+        task.setName("LDAP Sync Task");
+        task.setDestinationRealm("/");
+        task.setResource(resource.getKey());
+        task.setFullReconciliation(true);
+        task.setPerformCreate(true);
+
+        response = adminClient.getService(TaskService.class).create(task);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        task = adminClient.getService(TaskService.class).read(
+                Long.valueOf(StringUtils.substringAfterLast(response.getLocation().toASCIIString(), "/")));
+        assertNotNull(resource);
+
+        // synchronize
+        TaskExecTO execution = AbstractTaskITCase.execProvisioningTask(
+                adminClient.getService(TaskService.class), task.getKey(), 50, false);
+
+        // verify execution status
+        String status = execution.getStatus();
+        assertNotNull(status);
+        assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
+
+        // verify that synchronized user is found
+        PagedResult<UserTO> matchingUsers = adminClient.getService(UserService.class).search(
+                SyncopeClient.getAnySearchQueryBuilder().realm(SyncopeConstants.ROOT_REALM).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncFromLDAP").query()).
+                build());
+        assertNotNull(matchingUsers);
+        assertEquals(1, matchingUsers.getResult().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
index ca9d8a4..dff129e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
@@ -121,12 +121,12 @@ public class PushTaskITCase extends AbstractTaskITCase {
     public void pushMatchingUnmatchingGroups() {
         assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
 
-        execProvisioningTask(23L, 50, false);
+        execProvisioningTask(taskService, 23L, 50, false);
 
         assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
         assertTrue(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
 
-        execProvisioningTask(23L, 50, false);
+        execProvisioningTask(taskService, 23L, 50, false);
 
         assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
         assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
@@ -145,7 +145,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Unmatching --> Assign --> dryRuyn
         // ------------------------------------------
-        execProvisioningTask(13L, 50, true);
+        execProvisioningTask(taskService, 13L, 50, true);
         assertEquals(0, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='vivaldi'").size());
         assertFalse(userService.read(3L).getResources().contains(RESOURCE_NAME_TESTDB2));
         // ------------------------------------------
@@ -155,7 +155,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         pushTaskIds.add(14L);
         pushTaskIds.add(15L);
         pushTaskIds.add(16L);
-        execProvisioningTasks(pushTaskIds, 50, false);
+        execProvisioningTasks(taskService, pushTaskIds, 50, false);
 
         // ------------------------------------------
         // Unatching --> Ignore
@@ -200,7 +200,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Matching --> Deprovision --> dryRuyn
         // ------------------------------------------
-        execProvisioningTask(19L, 50, true);
+        execProvisioningTask(taskService, 19L, 50, true);
         assertTrue(userService.read(1L).getResources().contains(RESOURCE_NAME_TESTDB2));
         assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='rossini'").size());
         // ------------------------------------------
@@ -210,7 +210,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         pushTaskKeys.add(19L);
         pushTaskKeys.add(16L);
 
-        execProvisioningTasks(pushTaskKeys, 50, false);
+        execProvisioningTasks(taskService, pushTaskKeys, 50, false);
 
         // ------------------------------------------
         // Matching --> Deprovision && Ignore
@@ -231,7 +231,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Matching --> Link
         // ------------------------------------------
-        execProvisioningTask(20L, 50, false);
+        execProvisioningTask(taskService, 20L, 50, false);
         assertTrue(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
         assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
         // ------------------------------------------
@@ -240,7 +240,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         pushTaskKeys.add(21L);
         pushTaskKeys.add(22L);
 
-        execProvisioningTasks(pushTaskKeys, 50, false);
+        execProvisioningTasks(taskService, pushTaskKeys, 50, false);
 
         // ------------------------------------------
         // Matching --> Unlink && Update
@@ -325,7 +325,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
             assertNotNull(push);
 
             // execute the new task
-            TaskExecTO pushExec = execProvisioningTask(push.getKey(), 50, false);
+            TaskExecTO pushExec = execProvisioningTask(taskService, push.getKey(), 50, false);
             assertTrue(PropagationTaskExecStatus.valueOf(pushExec.getStatus()).isSuccessful());
         } finally {
             groupService.delete(groupTO.getKey());
@@ -373,7 +373,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         notification = getObject(responseNotification.getLocation(), NotificationService.class, NotificationTO.class);
         assertNotNull(notification);
 
-        execProvisioningTask(actual.getKey(), 50, false);
+        execProvisioningTask(taskService, actual.getKey(), 50, false);
 
         NotificationTaskTO taskTO = findNotificationTaskBySender("syncope648@syncope.apache.org");
         assertNotNull(taskTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/74aed4af/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
index 9f277fa..4313c00 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
@@ -163,7 +163,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
                     page(1).size(1).build()).getTotalCount();
             assertNotNull(usersPre);
 
-            execProvisioningTask(SYNC_TASK_ID, 50, false);
+            execProvisioningTask(taskService, SYNC_TASK_ID, 50, false);
 
             // after execution of the sync task the user data should have been synced from CSV
             // and processed by user template
@@ -234,7 +234,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             Set<Long> otherSyncTaskKeys = new HashSet<>();
             otherSyncTaskKeys.add(25L);
             otherSyncTaskKeys.add(26L);
-            execProvisioningTasks(otherSyncTaskKeys, 50, false);
+            execProvisioningTasks(taskService, otherSyncTaskKeys, 50, false);
 
             // Matching --> UNLINK
             assertFalse(readUser("test9").getResources().contains(RESOURCE_NAME_CSV));
@@ -246,7 +246,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
     @Test
     public void dryRun() {
-        TaskExecTO execution = execProvisioningTask(SYNC_TASK_ID, 50, true);
+        TaskExecTO execution = execProvisioningTask(taskService, SYNC_TASK_ID, 50, true);
         assertEquals("Execution of task " + execution.getTask() + " failed with message " + execution.getMessage(),
                 "SUCCESS", execution.getStatus());
     }
@@ -254,7 +254,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void reconcileFromDB() {
         // update sync task
-        TaskExecTO execution = execProvisioningTask(7L, 50, false);
+        TaskExecTO execution = execProvisioningTask(taskService, 7L, 50, false);
         assertNotNull(execution.getStatus());
         assertTrue(PropagationTaskExecStatus.valueOf(execution.getStatus()).isSuccessful());
 
@@ -268,7 +268,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         jdbcTemplate.execute("UPDATE TEST SET STATUS=TRUE");
 
         // re-execute the same SyncTask: now user must be active
-        execution = execProvisioningTask(7L, 50, false);
+        execution = execProvisioningTask(taskService, 7L, 50, false);
         assertNotNull(execution.getStatus());
         assertTrue(PropagationTaskExecStatus.valueOf(execution.getStatus()).isSuccessful());
 
@@ -313,14 +313,14 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         ldapCleanup();
 
         // 0. synchronize
-        TaskExecTO execution = execProvisioningTask(11L, 50, false);
+        TaskExecTO execution = execProvisioningTask(taskService, 11L, 50, false);
 
         // 1. verify execution status
         String status = execution.getStatus();
         assertNotNull(status);
         assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
 
-        // 2. verify that synchronized group is found, with expected attributes
+        // 2. verify that synchronized group is found
         PagedResult<GroupTO> matchingGroups = groupService.search(
                 SyncopeClient.getAnySearchQueryBuilder().realm(SyncopeConstants.ROOT_REALM).
                 fiql(SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("testLDAPGroup").query()).
@@ -328,6 +328,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertNotNull(matchingGroups);
         assertEquals(1, matchingGroups.getResult().size());
 
+        // 3. verify that synchronized user is found
         PagedResult<UserTO> matchingUsers = userService.search(
                 SyncopeClient.getAnySearchQueryBuilder().realm(SyncopeConstants.ROOT_REALM).
                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncFromLDAP").query()).
@@ -351,7 +352,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertNull(groupTO.getGroupOwner());
 
         // SYNCOPE-317
-        execProvisioningTask(11L, 50, false);
+        execProvisioningTask(taskService, 11L, 50, false);
     }
 
     @Test
@@ -383,7 +384,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         }
 
         // 3. synchronize
-        execProvisioningTask(28L, 50, false);
+        execProvisioningTask(taskService, 28L, 50, false);
 
         // 4. verify that printer was re-created in Syncope
         matchingPrinters = anyObjectService.search(
@@ -456,7 +457,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             assertFalse(actual.getTemplates().get(AnyTypeKind.USER.name()).getResources().isEmpty());
             assertFalse(((UserTO) actual.getTemplates().get(AnyTypeKind.USER.name())).getMemberships().isEmpty());
 
-            TaskExecTO execution = execProvisioningTask(actual.getKey(), 50, false);
+            TaskExecTO execution = execProvisioningTask(taskService, actual.getKey(), 50, false);
             final String status = execution.getStatus();
             assertNotNull(status);
             assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
@@ -475,7 +476,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void issueSYNCOPE230() {
         // 1. read SyncTask for resource-db-sync (table TESTSYNC on external H2)
-        execProvisioningTask(10L, 50, false);
+        execProvisioningTask(taskService, 10L, 50, false);
 
         // 3. read e-mail address for user created by the SyncTask first execution
         UserTO userTO = readUser("issuesyncope230");
@@ -488,7 +489,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         jdbcTemplate.execute("UPDATE TESTSYNC SET email='updatedSYNCOPE230@syncope.apache.org'");
 
         // 5. re-execute the SyncTask
-        execProvisioningTask(10L, 50, false);
+        execProvisioningTask(taskService, 10L, 50, false);
 
         // 6. verify that the e-mail was updated
         userTO = readUser("issuesyncope230");
@@ -550,7 +551,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
         userService.update(userMod);
 
-        execProvisioningTask(actual.getKey(), 50, false);
+        execProvisioningTask(taskService, actual.getKey(), 50, false);
 
         SyncTaskTO executed = taskService.read(actual.getKey());
         assertEquals(1, executed.getExecutions().size());
@@ -574,7 +575,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             assertEquals(1, userTO.getPropagationStatusTOs().size());
             assertTrue(userTO.getPropagationStatusTOs().get(0).getStatus().isSuccessful());
 
-            TaskExecTO taskExecTO = execProvisioningTask(24L, 50, false);
+            TaskExecTO taskExecTO = execProvisioningTask(taskService, 24L, 50, false);
 
             assertNotNull(taskExecTO.getStatus());
             assertTrue(PropagationTaskExecStatus.valueOf(taskExecTO.getStatus()).isSuccessful());
@@ -623,7 +624,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         task.getTemplates().put(AnyTypeKind.USER.name(), template);
 
         taskService.update(task);
-        execProvisioningTask(task.getKey(), 50, false);
+        execProvisioningTask(taskService, task.getKey(), 50, false);
 
         // check for sync policy
         userTO = userService.read(userTO.getKey());
@@ -680,7 +681,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(actual.getKey(), syncTask.getKey());
         assertEquals(actual.getJobDelegateClassName(), syncTask.getJobDelegateClassName());
 
-        TaskExecTO execution = execProvisioningTask(syncTask.getKey(), 50, false);
+        TaskExecTO execution = execProvisioningTask(taskService, syncTask.getKey(), 50, false);
         final String status = execution.getStatus();
         assertNotNull(status);
         assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
@@ -757,7 +758,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(actual.getKey(), syncTask.getKey());
         assertEquals(actual.getJobDelegateClassName(), syncTask.getJobDelegateClassName());
 
-        TaskExecTO execution = execProvisioningTask(syncTask.getKey(), 50, false);
+        TaskExecTO execution = execProvisioningTask(taskService, syncTask.getKey(), 50, false);
         String status = execution.getStatus();
         assertNotNull(status);
         assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());