syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [02/18] syncope git commit: [SYNCOPE-956] Core implementation
Date Tue, 10 Oct 2017 06:36:51 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
index 1d64ace..4e40e83 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
@@ -68,7 +68,6 @@ import org.opensaml.saml.saml2.core.AuthnContext;
 import org.opensaml.saml.saml2.core.AuthnContextClassRef;
 import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
 import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.saml2.core.AuthnStatement;
 import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.LogoutResponse;
@@ -448,14 +447,14 @@ public class SAML2SPLogic extends AbstractSAML2Logic<AbstractBaseBean> {
         if (assertion.getConditions().getNotOnOrAfter() != null) {
             responseTO.setNotOnOrAfter(assertion.getConditions().getNotOnOrAfter().toDate());
         }
-        for (AuthnStatement authnStmt : assertion.getAuthnStatements()) {
+        assertion.getAuthnStatements().forEach(authnStmt -> {
             responseTO.setSessionIndex(authnStmt.getSessionIndex());
 
             responseTO.setAuthInstant(authnStmt.getAuthnInstant().toDate());
             if (authnStmt.getSessionNotOnOrAfter() != null) {
                 responseTO.setNotOnOrAfter(authnStmt.getSessionNotOnOrAfter().toDate());
             }
-        }
+        });
 
         for (AttributeStatement attrStmt : assertion.getAttributeStatements()) {
             for (Attribute attr : attrStmt.getAttributes()) {
@@ -469,11 +468,11 @@ public class SAML2SPLogic extends AbstractSAML2Logic<AbstractBaseBean> {
 
                     AttrTO attrTO = new AttrTO();
                     attrTO.setSchema(attrName);
-                    for (XMLObject value : attr.getAttributeValues()) {
-                        if (value.getDOM() != null) {
-                            attrTO.getValues().add(value.getDOM().getTextContent());
-                        }
-                    }
+                    attr.getAttributeValues().stream().
+                            filter(value -> value.getDOM() != null).
+                            forEachOrdered(value -> {
+                                attrTO.getValues().add(value.getDOM().getTextContent());
+                            });
                     responseTO.getAttrs().add(attrTO);
                 }
             }
@@ -481,7 +480,7 @@ public class SAML2SPLogic extends AbstractSAML2Logic<AbstractBaseBean> {
 
         final List<String> matchingUsers = keyValue == null
                 ? Collections.<String>emptyList()
-                : userManager.findMatchingUser(keyValue, idp.getConnObjectKeyItem());
+                : userManager.findMatchingUser(keyValue, idp.getKey());
         LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
 
         String username;

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
index 9b4e497..487478b 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
@@ -31,7 +31,6 @@ import java.util.Base64;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.SAML2IdPTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -41,9 +40,7 @@ import org.opensaml.saml.saml2.metadata.Endpoint;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.KeyDescriptor;
-import org.opensaml.saml.saml2.metadata.NameIDFormat;
 import org.opensaml.saml.saml2.metadata.SingleLogoutService;
-import org.opensaml.saml.saml2.metadata.SingleSignOnService;
 import org.opensaml.xmlsec.signature.X509Data;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -75,21 +72,21 @@ public class SAML2IdPEntity {
 
         IDPSSODescriptor idpdescriptor = entityDescriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
 
-        for (SingleSignOnService sso : idpdescriptor.getSingleSignOnServices()) {
+        idpdescriptor.getSingleSignOnServices().forEach(sso -> {
             LOG.debug("[{}] Add SSO binding {}({})", id, sso.getBinding(), sso.getLocation());
             this.ssoBindings.put(sso.getBinding(), sso);
-        }
+        });
 
-        for (SingleLogoutService slo : idpdescriptor.getSingleLogoutServices()) {
+        idpdescriptor.getSingleLogoutServices().forEach(slo -> {
             LOG.debug("[{}] Add SLO binding '{}'\n\tLocation: '{}'\n\tResponse Location: '{}'",
                     id, slo.getBinding(), slo.getLocation(), slo.getResponseLocation());
             this.sloBindings.put(slo.getBinding(), slo);
-        }
+        });
 
-        for (NameIDFormat nameIDFormat : idpdescriptor.getNameIDFormats()) {
+        idpdescriptor.getNameIDFormats().forEach(nameIDFormat -> {
             LOG.debug("[{}] Add NameIDFormat '{}'", id, nameIDFormat.getFormat());
             nameIDFormats.add(nameIDFormat.getFormat());
-        }
+        });
 
         CertificateFactory cf = CertificateFactory.getInstance("X.509");
 
@@ -125,6 +122,10 @@ public class SAML2IdPEntity {
         return id;
     }
 
+    public String getKey() {
+        return idpTO.getKey();
+    }
+
     public boolean isCreateUnmatching() {
         return idpTO.isCreateUnmatching();
     }
@@ -149,16 +150,12 @@ public class SAML2IdPEntity {
         return idpTO.getConnObjectKeyItem();
     }
 
-    public List<ItemTO> getItems() {
-        return idpTO.getItems();
-    }
-
     public UserTO getUserTemplate() {
         return idpTO.getUserTemplate();
     }
 
-    public Set<String> getActionsClassNames() {
-        return idpTO.getActionsClassNames();
+    public List<String> getActions() {
+        return idpTO.getActions();
     }
 
     public Endpoint getSSOLocation(final SAML2BindingType bindingType) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
index 2245fc7..4083a45 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
@@ -29,17 +29,20 @@ import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.SAML2IdPDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 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.SAML2IdP;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
@@ -65,12 +68,18 @@ public class SAML2UserManager {
     private static final Logger LOG = LoggerFactory.getLogger(SAML2UserManager.class);
 
     @Autowired
+    private SAML2IdPDAO idpDAO;
+
+    @Autowired
     private UserDAO userDAO;
 
     @Autowired
     private PlainSchemaDAO plainSchemaDAO;
 
     @Autowired
+    private ImplementationDAO implementationDAO;
+
+    @Autowired
     private IntAttrNameParser intAttrNameParser;
 
     @Autowired
@@ -86,11 +95,17 @@ public class SAML2UserManager {
     private UserDataBinder binder;
 
     @Transactional(readOnly = true)
-    public List<String> findMatchingUser(final String keyValue, final ItemTO connObjectKeyItem) {
+    public List<String> findMatchingUser(final String keyValue, final String idpKey) {
         List<String> result = new ArrayList<>();
 
+        SAML2IdP idp = idpDAO.find(idpKey);
+        if (idp == null) {
+            LOG.warn("Invalid IdP: {}", idpKey);
+            return result;
+        }
+
         String transformed = keyValue;
-        for (ItemTransformer transformer : MappingUtils.getItemTransformers(connObjectKeyItem)) {
+        for (ItemTransformer transformer : MappingUtils.getItemTransformers(idp.getConnObjectKeyItem().get())) {
             List<Object> output = transformer.beforePull(
                     null,
                     null,
@@ -100,7 +115,8 @@ public class SAML2UserManager {
             }
         }
 
-        IntAttrName intAttrName = intAttrNameParser.parse(connObjectKeyItem.getIntAttrName(), AnyTypeKind.USER);
+        IntAttrName intAttrName = intAttrNameParser.parse(
+                idp.getConnObjectKeyItem().get().getIntAttrName(), AnyTypeKind.USER);
 
         if (intAttrName.getField() != null) {
             switch (intAttrName.getField()) {
@@ -156,23 +172,34 @@ public class SAML2UserManager {
     private List<SAML2IdPActions> getActions(final SAML2IdPEntity idp) {
         List<SAML2IdPActions> actions = new ArrayList<>();
 
-        idp.getActionsClassNames().forEach((className) -> {
-            try {
-                Class<?> actionsClass = Class.forName(className);
-                SAML2IdPActions idpActions = (SAML2IdPActions) ApplicationContextProvider.getBeanFactory().
-                        createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-
-                actions.add(idpActions);
-            } catch (Exception e) {
-                LOG.warn("Class '{}' not found", className, e);
+        idp.getActions().forEach(key -> {
+            Implementation impl = implementationDAO.find(key);
+            if (impl == null) {
+                LOG.warn("Invalid implementation: {}", key);
+            } else {
+                try {
+                    Class<?> actionsClass = Class.forName(impl.getBody());
+                    SAML2IdPActions idpActions = (SAML2IdPActions) ApplicationContextProvider.getBeanFactory().
+                            createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+
+                    actions.add(idpActions);
+                } catch (Exception e) {
+                    LOG.warn("Class '{}' not found", impl.getBody(), e);
+                }
             }
         });
 
         return actions;
     }
 
-    private void fill(final SAML2IdPEntity idp, final SAML2LoginResponseTO responseTO, final UserTO userTO) {
-        for (ItemTO item : idp.getItems()) {
+    private void fill(final String idpKey, final SAML2LoginResponseTO responseTO, final UserTO userTO) {
+        SAML2IdP idp = idpDAO.find(idpKey);
+        if (idp == null) {
+            LOG.warn("Invalid IdP: {}", idpKey);
+            return;
+        }
+
+        idp.getItems().forEach(item -> {
             IntAttrName intAttrName = intAttrNameParser.parse(item.getIntAttrName(), AnyTypeKind.USER);
 
             List<String> values = Collections.emptyList();
@@ -218,7 +245,7 @@ public class SAML2UserManager {
                         LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
                 }
             }
-        }
+        });
     }
 
     @Transactional(propagation = Propagation.REQUIRES_NEW)
@@ -234,7 +261,7 @@ public class SAML2UserManager {
             userTO = action.beforeCreate(userTO, responseTO);
         }
 
-        fill(idp, responseTO, userTO);
+        fill(idp.getKey(), responseTO, userTO);
 
         if (userTO.getRealm() == null) {
             userTO.setRealm(SyncopeConstants.ROOT_REALM);
@@ -258,7 +285,7 @@ public class SAML2UserManager {
         UserTO userTO = binder.getUserTO(userDAO.findKey(username));
         UserTO original = SerializationUtils.clone(userTO);
 
-        fill(idp, responseTO, userTO);
+        fill(idp.getKey(), responseTO, userTO);
 
         UserPatch userPatch = AnyOperations.diff(userTO, original, true);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
index 7ef1cec..b3bda7c 100644
--- a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
+++ b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
 import org.apache.syncope.common.lib.types.SAML2BindingType;
 
 public interface SAML2IdP extends Entity {
@@ -69,6 +68,7 @@ public interface SAML2IdP extends Entity {
 
     List<? extends SAML2IdPItem> getItems();
 
-    Set<String> getActionsClassNames();
+    boolean add(Implementation action);
 
+    List<? extends Implementation> getActions();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
index 2de265b..13b43f1 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
@@ -19,27 +19,27 @@
 package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
 import javax.persistence.Basic;
 import javax.persistence.Cacheable;
 import javax.persistence.CascadeType;
-import javax.persistence.CollectionTable;
 import javax.persistence.Column;
-import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
 import javax.persistence.Lob;
+import javax.persistence.ManyToMany;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.SAML2BindingType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem;
 import org.apache.syncope.core.persistence.api.entity.SAML2UserTemplate;
@@ -94,12 +94,13 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP
     @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "idp")
     private JPASAML2UserTemplate userTemplate;
 
-    @ElementCollection(fetch = FetchType.EAGER)
-    @Column(name = "actionClassName")
-    @CollectionTable(name = TABLE + "_actionsClassNames",
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(name = TABLE + "Action",
             joinColumns =
-            @JoinColumn(name = "saml2IdP_id", referencedColumnName = "id"))
-    private Set<String> actionsClassNames = new HashSet<>();
+            @JoinColumn(name = "idp_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "implementation_id"))
+    private List<JPAImplementation> actions = new ArrayList<>();
 
     @Override
     public String getEntityID() {
@@ -215,7 +216,14 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP
     }
 
     @Override
-    public Set<String> getActionsClassNames() {
-        return actionsClassNames;
+    public boolean add(final Implementation action) {
+        checkType(action, JPAImplementation.class);
+        checkImplementationType(action, ImplementationType.LOGIC_ACTIONS);
+        return this.actions.add((JPAImplementation) action);
+    }
+
+    @Override
+    public List<? extends Implementation> getActions() {
+        return actions;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
index 863d068..6e22a43 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
@@ -21,14 +21,15 @@ package org.apache.syncope.core.persistence.jpa.entity;
 import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.Cacheable;
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem;
 import org.apache.syncope.core.persistence.jpa.entity.resource.AbstractItem;
@@ -45,15 +46,13 @@ public class JPASAML2IdPItem extends AbstractItem implements SAML2IdPItem {
     @ManyToOne
     private JPASAML2IdP idp;
 
-    /**
-     * (Optional) classes for Item transformation.
-     */
-    @ElementCollection(fetch = FetchType.EAGER)
-    @Column(name = "transformerClassName")
-    @CollectionTable(name = TABLE + "_Transformer",
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(name = TABLE + "Transformer",
             joinColumns =
-            @JoinColumn(name = "saml2IdPItemItem_id", referencedColumnName = "id"))
-    private List<String> transformerClassNames = new ArrayList<>();
+            @JoinColumn(name = "item_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "implementation_id"))
+    private List<JPAImplementation> transformers = new ArrayList<>();
 
     @Override
     public SAML2IdP getIdP() {
@@ -67,7 +66,14 @@ public class JPASAML2IdPItem extends AbstractItem implements SAML2IdPItem {
     }
 
     @Override
-    public List<String> getTransformerClassNames() {
-        return transformerClassNames;
+    public boolean add(final Implementation transformer) {
+        checkType(transformer, JPAImplementation.class);
+        checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+        return this.transformers.add((JPAImplementation) transformer);
+    }
+
+    @Override
+    public List<? extends Implementation> getTransformers() {
+        return transformers;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
index f3b91e9..83bf348 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
@@ -20,8 +20,8 @@ package org.apache.syncope.core.persistence.jpa.validation.entity;
 
 import javax.validation.ConstraintValidatorContext;
 import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
-import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem;
 import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 
 public class SAML2IdPValidator extends AbstractValidator<SAML2IdPCheck, SAML2IdP> {
@@ -36,38 +36,41 @@ public class SAML2IdPValidator extends AbstractValidator<SAML2IdPCheck, SAML2IdP
             return false;
         }
 
-        boolean isValid = true;
+        final boolean[] isValid = new boolean[] { true };
 
         long passwords = value.getItems().stream().filter(item -> item.isPassword()).count();
         if (passwords > 0) {
             context.buildConstraintViolationWithTemplate(
                     getTemplate(EntityViolationType.InvalidMapping, "No password mapping is allowed")).
                     addPropertyNode("password.size").addConstraintViolation();
-            isValid = false;
+            isValid[0] = false;
         }
 
-        for (SAML2IdPItem item : value.getItems()) {
-            for (String className : item.getTransformerClassNames()) {
-                Class<?> actionsClass = null;
-                boolean isAssignable = false;
-                try {
-                    actionsClass = Class.forName(className);
-                    isAssignable = ItemTransformer.class.isAssignableFrom(actionsClass);
-                } catch (Exception e) {
-                    LOG.error("Invalid MappingItemTransformer specified: {}", className, e);
-                }
+        value.getItems().forEach(item -> {
+            item.getTransformers().stream().
+                    filter(transformer -> transformer.getEngine() == ImplementationEngine.JAVA).
+                    forEach(transformer -> {
 
-                if (actionsClass == null || !isAssignable) {
-                    context.buildConstraintViolationWithTemplate(
-                            getTemplate(EntityViolationType.InvalidMapping,
-                                    "Invalid mapping item trasformer class name")).
-                            addPropertyNode("mappingItemTransformerClassName").addConstraintViolation();
-                    isValid = false;
-                }
-            }
-        }
+                        Class<?> actionsClass = null;
+                        boolean isAssignable = false;
+                        try {
+                            actionsClass = Class.forName(transformer.getBody());
+                            isAssignable = ItemTransformer.class.isAssignableFrom(actionsClass);
+                        } catch (Exception e) {
+                            LOG.error("Invalid ItemTransformer specified: {}", transformer.getBody(), e);
+                        }
+
+                        if (actionsClass == null || !isAssignable) {
+                            context.buildConstraintViolationWithTemplate(
+                                    getTemplate(EntityViolationType.InvalidMapping,
+                                            "Invalid item trasformer class name")).
+                                    addPropertyNode("itemTransformers").addConstraintViolation();
+                            isValid[0] = false;
+                        }
+                    });
+        });
 
-        return isValid;
+        return isValid[0];
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
index 7d003ab..4413fc3 100644
--- a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
+++ b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
@@ -31,7 +31,9 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.SAML2IdPDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.SAML2EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem;
@@ -60,6 +62,9 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
     private SAML2IdPDAO saml2IdPDAO;
 
     @Autowired
+    private ImplementationDAO implementationDAO;
+
+    @Autowired
     private SAML2EntityFactory entityFactory;
 
     @Autowired
@@ -196,8 +201,18 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
         });
         populateItems(idpTO, idp, allowedSchemas);
 
-        idp.getActionsClassNames().clear();
-        idp.getActionsClassNames().addAll(idpTO.getActionsClassNames());
+        idpTO.getActions().forEach(implementationKey -> {
+            Implementation implementation = implementationDAO.find(implementationKey);
+            if (implementation == null) {
+                LOG.debug("Invalid " + Implementation.class.getSimpleName() + "{}, ignoring...", implementationKey);
+            } else {
+                idp.add(implementation);
+            }
+        });
+        // remove all implementations not contained in the TO
+        idp.getActions().removeAll(idp.getActions().stream().
+                filter(implementation -> !idpTO.getActions().contains(implementation.getKey())).
+                collect(Collectors.toList()));
 
         return saml2IdPDAO.save(idp);
     }
@@ -237,7 +252,9 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
 
         populateItems(idp, idpTO);
 
-        idpTO.getActionsClassNames().addAll(idp.getActionsClassNames());
+        idp.getActions().forEach(action -> {
+            idpTO.getActions().add(action.getKey());
+        });
 
         return idpTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index 6e8e170..e4d94d0 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -18,10 +18,12 @@
  */
 package org.apache.syncope.fit.core.reference;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 import javax.sql.DataSource;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
@@ -34,19 +36,24 @@ import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.StaticReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf;
 import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.logic.TaskLogic;
+import org.apache.syncope.core.migration.MigrationPullActions;
 import org.apache.syncope.core.provisioning.java.job.report.AuditReportlet;
 import org.apache.syncope.core.provisioning.java.job.report.GroupReportlet;
 import org.apache.syncope.core.provisioning.java.job.report.ReconciliationReportlet;
 import org.apache.syncope.core.provisioning.java.job.report.StaticReportlet;
 import org.apache.syncope.core.provisioning.java.job.report.UserReportlet;
-import org.apache.syncope.core.migration.MigrationPullActions;
 import org.apache.syncope.core.persistence.api.DomainsHolder;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
 import org.apache.syncope.core.persistence.api.dao.Reportlet;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.jpa.attrvalue.validation.AlwaysTrueValidator;
 import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BasicValidator;
 import org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator;
@@ -68,15 +75,59 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class ITImplementationLookup implements ImplementationLookup {
 
-    private static final Map<Type, Set<String>> CLASS_NAMES = new HashMap<Type, Set<String>>() {
+    private static final String ES_REINDEX = "org.apache.syncope.core.provisioning.java.job.ElasticsearchReindex";
+
+    private static final Set<Class<?>> JWTSSOPROVIDER_CLASSES = new HashSet<>(
+            Arrays.asList(SyncopeJWTSSOProvider.class, CustomJWTSSOProvider.class));
+
+    private static final Map<Class<? extends ReportletConf>, Class<? extends Reportlet>> REPORTLET_CLASSES =
+            new HashMap<Class<? extends ReportletConf>, Class<? extends Reportlet>>() {
+
+        private static final long serialVersionUID = 3109256773218160485L;
+
+        {
+            put(AuditReportletConf.class, AuditReportlet.class);
+            put(ReconciliationReportletConf.class, ReconciliationReportlet.class);
+            put(GroupReportletConf.class, GroupReportlet.class);
+            put(UserReportletConf.class, UserReportlet.class);
+            put(StaticReportletConf.class, StaticReportlet.class);
+        }
+    };
+
+    private static final Map<Class<? extends AccountRuleConf>, Class<? extends AccountRule>> ACCOUNT_RULE_CLASSES =
+            new HashMap<Class<? extends AccountRuleConf>, Class<? extends AccountRule>>() {
+
+        private static final long serialVersionUID = 3109256773218160485L;
+
+        {
+            put(TestAccountRuleConf.class, TestAccountRule.class);
+            put(DefaultAccountRuleConf.class, DefaultAccountRule.class);
+        }
+    };
+
+    private static final Map<Class<? extends PasswordRuleConf>, Class<? extends PasswordRule>> PASSWORD_RULE_CLASSES =
+            new HashMap<Class<? extends PasswordRuleConf>, Class<? extends PasswordRule>>() {
+
+        private static final long serialVersionUID = -6624291041977583649L;
+
+        {
+            put(TestPasswordRuleConf.class, TestPasswordRule.class);
+            put(DefaultPasswordRuleConf.class, DefaultPasswordRule.class);
+        }
+    };
+
+    private static final Set<Class<?>> AUDITAPPENDER_CLASSES = new HashSet<>(
+            Arrays.asList(TestFileAuditAppender.class, TestFileRewriteAuditAppender.class));
+
+    private static final Map<ImplementationType, Set<String>> CLASS_NAMES =
+            new HashMap<ImplementationType, Set<String>>() {
 
         private static final long serialVersionUID = 3109256773218160485L;
 
         {
-            Set<String> classNames = new HashSet<>();
-            classNames.add(SyncopeJWTSSOProvider.class.getName());
-            classNames.add(CustomJWTSSOProvider.class.getName());
-            put(Type.JWT_SSO_PROVIDER, classNames);
+            Set<String> classNames = ITImplementationLookup.JWTSSOPROVIDER_CLASSES.stream().
+                    map(Class::getName).collect(Collectors.toSet());
+            put(ImplementationType.JWT_SSO_PROVIDER, classNames);
 
             classNames = new HashSet<>();
             classNames.add(ReconciliationReportletConf.class.getName());
@@ -84,39 +135,37 @@ public class ITImplementationLookup implements ImplementationLookup {
             classNames.add(GroupReportletConf.class.getName());
             classNames.add(AuditReportletConf.class.getName());
             classNames.add(StaticReportletConf.class.getName());
-            put(Type.REPORTLET_CONF, classNames);
+            put(ImplementationType.REPORTLET, classNames);
 
-            classNames = new HashSet<>();
-            classNames.add(TestAccountRuleConf.class.getName());
-            classNames.add(DefaultAccountRuleConf.class.getName());
-            put(Type.ACCOUNT_RULE_CONF, classNames);
+            classNames = ITImplementationLookup.ACCOUNT_RULE_CLASSES.values().stream().
+                    map(Class::getName).collect(Collectors.toSet());
+            put(ImplementationType.ACCOUNT_RULE, classNames);
 
-            classNames = new HashSet<>();
-            classNames.add(TestPasswordRuleConf.class.getName());
-            classNames.add(DefaultPasswordRuleConf.class.getName());
-            put(Type.PASSWORD_RULE_CONF, classNames);
+            classNames = ITImplementationLookup.PASSWORD_RULE_CLASSES.values().stream().
+                    map(Class::getName).collect(Collectors.toSet());
+            put(ImplementationType.PASSWORD_RULE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(PrefixItemTransformer.class.getName());
-            put(Type.ITEM_TRANSFORMER, classNames);
+            put(ImplementationType.ITEM_TRANSFORMER, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestSampleJobDelegate.class.getName());
-            put(Type.TASKJOBDELEGATE, classNames);
+            put(ImplementationType.TASKJOB_DELEGATE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestReconciliationFilterBuilder.class.getName());
-            put(Type.RECONCILIATION_FILTER_BUILDER, classNames);
+            put(ImplementationType.RECON_FILTER_BUILDER, classNames);
 
             classNames = new HashSet<>();
             classNames.add(DoubleValueLogicActions.class.getName());
-            put(Type.LOGIC_ACTIONS, classNames);
+            put(ImplementationType.LOGIC_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(LDAPMembershipPropagationActions.class.getName());
             classNames.add(LDAPPasswordPropagationActions.class.getName());
             classNames.add(DBPasswordPropagationActions.class.getName());
-            put(Type.PROPAGATION_ACTIONS, classNames);
+            put(ImplementationType.PROPAGATION_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(LDAPPasswordPullActions.class.getName());
@@ -124,70 +173,39 @@ public class ITImplementationLookup implements ImplementationLookup {
             classNames.add(MigrationPullActions.class.getName());
             classNames.add(LDAPMembershipPullActions.class.getName());
             classNames.add(DBPasswordPullActions.class.getName());
-            put(Type.PULL_ACTIONS, classNames);
+            put(ImplementationType.PULL_ACTIONS, classNames);
 
             classNames = new HashSet<>();
-            put(Type.PUSH_ACTIONS, classNames);
+            put(ImplementationType.PUSH_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestPullRule.class.getName());
-            put(Type.PULL_CORRELATION_RULE, classNames);
+            put(ImplementationType.PULL_CORRELATION_RULE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(BasicValidator.class.getName());
             classNames.add(EmailAddressValidator.class.getName());
             classNames.add(AlwaysTrueValidator.class.getName());
-            put(Type.VALIDATOR, classNames);
+            put(ImplementationType.VALIDATOR, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestNotificationRecipientsProvider.class.getName());
-            put(Type.NOTIFICATION_RECIPIENTS_PROVIDER, classNames);
+            put(ImplementationType.RECIPIENTS_PROVIDER, classNames);
 
-            classNames = new HashSet<>();
-            classNames.add(TestFileRewriteAuditAppender.class.getName());
-            classNames.add(TestFileAuditAppender.class.getName());
-            put(Type.AUDIT_APPENDER, classNames);
+            classNames = ITImplementationLookup.AUDITAPPENDER_CLASSES.stream().
+                    map(Class::getName).collect(Collectors.toSet());
+            put(ImplementationType.AUDIT_APPENDER, classNames);
         }
     };
 
-    private static final Map<Class<? extends ReportletConf>, Class<? extends Reportlet>> REPORTLET_CLASSES =
-            new HashMap<Class<? extends ReportletConf>, Class<? extends Reportlet>>() {
-
-        private static final long serialVersionUID = 3109256773218160485L;
-
-        {
-            put(AuditReportletConf.class, AuditReportlet.class);
-            put(ReconciliationReportletConf.class, ReconciliationReportlet.class);
-            put(GroupReportletConf.class, GroupReportlet.class);
-            put(UserReportletConf.class, UserReportlet.class);
-            put(StaticReportletConf.class, StaticReportlet.class);
-        }
-    };
-
-    private static final Map<Class<? extends AccountRuleConf>, Class<? extends AccountRule>> ACCOUNT_RULE_CLASSES =
-            new HashMap<Class<? extends AccountRuleConf>, Class<? extends AccountRule>>() {
-
-        private static final long serialVersionUID = 3109256773218160485L;
-
-        {
-            put(TestAccountRuleConf.class, TestAccountRule.class);
-            put(DefaultAccountRuleConf.class, DefaultAccountRule.class);
-        }
-    };
-
-    private static final Map<Class<? extends PasswordRuleConf>, Class<? extends PasswordRule>> PASSWORD_RULE_CLASSES =
-            new HashMap<Class<? extends PasswordRuleConf>, Class<? extends PasswordRule>>() {
-
-        private static final long serialVersionUID = -6624291041977583649L;
+    @Autowired
+    private AnySearchDAO anySearchDAO;
 
-        {
-            put(TestPasswordRuleConf.class, TestPasswordRule.class);
-            put(DefaultPasswordRuleConf.class, DefaultPasswordRule.class);
-        }
-    };
+    @Autowired
+    private ImplementationDAO implementationDAO;
 
     @Autowired
-    private AnySearchDAO anySearchDAO;
+    private EntityFactory entityFactory;
 
     @Autowired
     private DomainsHolder domainsHolder;
@@ -206,9 +224,21 @@ public class ITImplementationLookup implements ImplementationLookup {
         if (AopUtils.getTargetClass(anySearchDAO).getName().contains("Elasticsearch")) {
             for (Map.Entry<String, DataSource> entry : domainsHolder.getDomains().entrySet()) {
                 AuthContextUtils.execWithAuthContext(entry.getKey(), () -> {
+                    Implementation reindex = implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).
+                            stream().
+                            filter(impl -> impl.getEngine() == ImplementationEngine.JAVA
+                            && ES_REINDEX.equals(impl.getBody())).
+                            findAny().orElse(null);
+                    if (reindex == null) {
+                        reindex = entityFactory.newEntity(Implementation.class);
+                        reindex.setEngine(ImplementationEngine.JAVA);
+                        reindex.setType(ImplementationType.TASKJOB_DELEGATE);
+                        reindex.setBody(ES_REINDEX);
+                        reindex = implementationDAO.save(reindex);
+                    }
+
                     SchedTaskTO task = new SchedTaskTO();
-                    task.setJobDelegateClassName(
-                            "org.apache.syncope.core.provisioning.java.job.ElasticsearchReindex");
+                    task.setJobDelegate(reindex.getKey());
                     task.setName("Elasticsearch Reindex");
                     task = taskLogic.createSchedTask(task);
 
@@ -221,16 +251,13 @@ public class ITImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final Type type) {
+    public Set<String> getClassNames(final ImplementationType type) {
         return CLASS_NAMES.get(type);
     }
 
     @Override
     public Set<Class<?>> getJWTSSOProviderClasses() {
-        Set<Class<?>> classNames = new HashSet<>();
-        classNames.add(SyncopeJWTSSOProvider.class);
-        classNames.add(CustomJWTSSOProvider.class);
-        return classNames;
+        return JWTSSOPROVIDER_CLASSES;
     }
 
     @Override
@@ -256,9 +283,6 @@ public class ITImplementationLookup implements ImplementationLookup {
 
     @Override
     public Set<Class<?>> getAuditAppenderClasses() {
-        Set<Class<?>> classes = new HashSet<>();
-        classes.add(TestFileRewriteAuditAppender.class);
-        classes.add(TestFileAuditAppender.class);
-        return classes;
+        return AUDITAPPENDER_CLASSES;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
index d3039d0..ddd48fe 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
@@ -30,16 +30,19 @@ public class TestAccountRule implements AccountRule {
 
     private TestAccountRuleConf conf;
 
-    @Transactional(readOnly = true)
     @Override
-    public void enforce(final AccountRuleConf conf, final User user) {
+    public void setConf(final AccountRuleConf conf) {
         if (conf instanceof TestAccountRuleConf) {
             this.conf = TestAccountRuleConf.class.cast(conf);
         } else {
             throw new IllegalArgumentException(
                     AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
         }
+    }
 
+    @Transactional(readOnly = true)
+    @Override
+    public void enforce(final User user) {
         if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
             throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestNotificationRecipientsProvider.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestNotificationRecipientsProvider.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestNotificationRecipientsProvider.java
index 178e399..4d1e3f7 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestNotificationRecipientsProvider.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestNotificationRecipientsProvider.java
@@ -21,10 +21,10 @@ package org.apache.syncope.fit.core.reference;
 import java.util.Collections;
 import java.util.Set;
 import org.apache.syncope.core.persistence.api.entity.Notification;
-import org.apache.syncope.core.provisioning.api.notification.NotificationRecipientsProvider;
 import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.core.provisioning.api.notification.RecipientsProvider;
 
-public class TestNotificationRecipientsProvider implements NotificationRecipientsProvider {
+public class TestNotificationRecipientsProvider implements RecipientsProvider {
 
     @Transactional(readOnly = true)
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
index 2ca008b..69431ef 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
@@ -30,9 +30,13 @@ public class TestPasswordRule implements PasswordRule {
 
     private TestPasswordRuleConf conf;
 
-    @Transactional(readOnly = true)
     @Override
-    public void enforce(final PasswordRuleConf conf, final User user) {
+    public TestPasswordRuleConf getConf() {
+        return conf;
+    }
+
+    @Override
+    public void setConf(final PasswordRuleConf conf) {
         if (conf instanceof TestPasswordRuleConf) {
             this.conf = TestPasswordRuleConf.class.cast(conf);
         } else {
@@ -40,6 +44,11 @@ public class TestPasswordRule implements PasswordRule {
                     PasswordRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
         }
 
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public void enforce(final User user) {
         if (!user.getClearPassword().endsWith(this.conf.getMustEndWith())) {
             throw new PasswordPolicyException("Password not ending with " + this.conf.getMustEndWith());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
index 2c392ec..931b183 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestReconciliationFilterBuilder.java
@@ -18,12 +18,12 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import org.apache.syncope.core.provisioning.api.pushpull.ReconciliationFilterBuilder;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.filter.Filter;
 import org.identityconnectors.framework.common.objects.filter.FilterBuilder;
+import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
 
-public class TestReconciliationFilterBuilder implements ReconciliationFilterBuilder {
+public class TestReconciliationFilterBuilder implements ReconFilterBuilder {
 
     private static final Filter EQUALS = FilterBuilder.equalTo(AttributeBuilder.build("SURNAME", "Rossi"));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 98a80a9..97667c3 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -81,6 +81,7 @@ import org.apache.syncope.common.rest.api.service.PolicyService;
 import org.apache.syncope.common.rest.api.service.ReportService;
 import org.apache.syncope.common.rest.api.service.ResourceService;
 import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.common.rest.api.service.MailTemplateService;
 import org.apache.syncope.common.rest.api.service.RealmService;
 import org.apache.syncope.common.rest.api.service.RelationshipTypeService;
@@ -234,6 +235,8 @@ public abstract class AbstractITCase {
 
     protected static SecurityQuestionService securityQuestionService;
 
+    protected static ImplementationService implementationService;
+
     protected static CamelRouteService camelRouteService;
 
     protected static SAML2SPService saml2SpService;
@@ -304,6 +307,7 @@ public abstract class AbstractITCase {
         notificationService = adminClient.getService(NotificationService.class);
         schemaService = adminClient.getService(SchemaService.class);
         securityQuestionService = adminClient.getService(SecurityQuestionService.class);
+        implementationService = adminClient.getService(ImplementationService.class);
         camelRouteService = adminClient.getService(CamelRouteService.class);
         saml2SpService = adminClient.getService(SAML2SPService.class);
         saml2IdPService = adminClient.getService(SAML2IdPService.class);
@@ -321,7 +325,7 @@ public abstract class AbstractITCase {
         return new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).attrTO(attrTO(schema, value)).build();
     }
 
-    public <T> T getObject(final URI location, final Class<?> serviceClass, final Class<T> resultClass) {
+    public static <T> T getObject(final URI location, final Class<?> serviceClass, final Class<T> resultClass) {
         WebClient webClient = WebClient.fromClient(WebClient.client(adminClient.getService(serviceClass)));
         webClient.accept(clientFactory.getContentType().getMediaType()).to(location.toASCIIString(), false);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
new file mode 100644
index 0000000..fe8968e
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.UUID;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.ImplementationService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.apache.syncope.fit.core.reference.TestPullActions;
+import org.junit.jupiter.api.Test;
+
+public class ImplementationITCase extends AbstractITCase {
+
+    @Test
+    public void create() {
+        ImplementationTO implementationTO = new ImplementationTO();
+        implementationTO.setKey(UUID.randomUUID().toString());
+        implementationTO.setEngine(ImplementationEngine.JAVA);
+        implementationTO.setType(ImplementationType.PUSH_ACTIONS);
+        implementationTO.setBody(TestPullActions.class.getName());
+
+        // fail because type is wrong
+        try {
+            implementationService.create(implementationTO);
+            fail("This should not happen");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidImplementation, e.getType());
+        }
+        implementationTO.setType(ImplementationType.PULL_ACTIONS);
+
+        Response response = implementationService.create(implementationTO);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+
+        ImplementationTO actual =
+                getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+        assertNotNull(actual);
+
+        implementationTO.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+        assertEquals(actual, implementationTO);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
index f7fe298..943fe92 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
@@ -237,15 +237,6 @@ public class LoggerITCase extends AbstractITCase {
         found = false;
         for (EventCategoryTO eventCategoryTO : events) {
             if (EventCategoryType.TASK == eventCategoryTO.getType()
-                    && "TestSampleJobDelegate".equals(eventCategoryTO.getCategory())) {
-                found = true;
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategoryTO eventCategoryTO : events) {
-            if (EventCategoryType.TASK == eventCategoryTO.getType()
                     && "PullJobDelegate".equals(eventCategoryTO.getCategory())) {
                 found = true;
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
index 6790f34..38832be 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -31,13 +31,17 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
+import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.common.rest.api.service.NotificationService;
 import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
 import org.apache.syncope.fit.core.reference.TestNotificationRecipientsProvider;
@@ -219,6 +223,15 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
     @Test
     public void issueSYNCOPE446() throws Exception {
         // 1. Create notification
+        ImplementationTO recipientsProvider = new ImplementationTO();
+        recipientsProvider.setKey(TestNotificationRecipientsProvider.class.getSimpleName());
+        recipientsProvider.setEngine(ImplementationEngine.JAVA);
+        recipientsProvider.setType(ImplementationType.RECIPIENTS_PROVIDER);
+        recipientsProvider.setBody(TestNotificationRecipientsProvider.class.getName());
+        Response response = implementationService.create(recipientsProvider);
+        recipientsProvider = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+        assertNotNull(recipientsProvider);
+
         NotificationTO notification = new NotificationTO();
         notification.setTraceLevel(TraceLevel.ALL);
         notification.getEvents().add("[LOGIC]:[GroupLogic]:[]:[create]:[SUCCESS]");
@@ -232,7 +245,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
         notification.setSelfAsRecipient(false);
         notification.setRecipientAttrName("email");
         notification.getStaticRecipients().add("notificationtest@syncope.apache.org");
-        notification.setRecipientsProviderClassName(TestNotificationRecipientsProvider.class.getName());
+        notification.setRecipientsProvider(recipientsProvider.getKey());
 
         String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
         notification.setSender(sender);
@@ -241,10 +254,10 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
         notification.setTemplate("optin");
         notification.setActive(true);
 
-        Response response = notificationService.create(notification);
+        response = notificationService.create(notification);
         notification = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
         assertNotNull(notification);
-        assertEquals(TestNotificationRecipientsProvider.class.getName(), notification.getRecipientsProviderClassName());
+        assertEquals(recipientsProvider.getKey(), notification.getRecipientsProvider());
 
         // 2. create group
         GroupTO groupTO = new GroupTO();

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
index 40664f0..51b49ff 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 
 import java.util.Arrays;
 import java.util.List;
+import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
@@ -38,6 +39,12 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.policy.PullPolicySpec;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.ImplementationService;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.fit.AbstractITCase;
 import org.apache.syncope.fit.core.reference.TestPullRule;
 import org.junit.jupiter.api.Test;
@@ -45,11 +52,27 @@ import org.junit.jupiter.api.Test;
 public class PolicyITCase extends AbstractITCase {
 
     private PullPolicyTO buildPullPolicyTO() {
-        PullPolicyTO policy = new PullPolicyTO();
+        ImplementationTO corrRule = null;
+        try {
+            corrRule = implementationService.read(TestPullRule.class.getSimpleName());
+        } catch (SyncopeClientException e) {
+            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
+                corrRule = new ImplementationTO();
+                corrRule.setKey(TestPullRule.class.getSimpleName());
+                corrRule.setEngine(ImplementationEngine.JAVA);
+                corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
+                corrRule.setBody(TestPullRule.class.getName());
+                Response response = implementationService.create(corrRule);
+                corrRule = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+                assertNotNull(corrRule);
+            }
+        }
+        assertNotNull(corrRule);
 
         PullPolicySpec spec = new PullPolicySpec();
-        spec.getCorrelationRules().put(AnyTypeKind.USER.name(), TestPullRule.class.getName());
+        spec.getCorrelationRules().put(AnyTypeKind.USER.name(), corrRule.getKey());
 
+        PullPolicyTO policy = new PullPolicyTO();
         policy.setSpecification(spec);
         policy.setDescription("Pull policy");
 
@@ -110,7 +133,7 @@ public class PolicyITCase extends AbstractITCase {
         PullPolicyTO policyTO = createPolicy(policy);
 
         assertNotNull(policyTO);
-        assertEquals(TestPullRule.class.getName(),
+        assertEquals(TestPullRule.class.getSimpleName(),
                 policyTO.getSpecification().getCorrelationRules().get(AnyTypeKind.USER.name()));
     }
 
@@ -126,15 +149,21 @@ public class PolicyITCase extends AbstractITCase {
         assertNotNull(policy);
         assertNotEquals("ce93fcda-dc3a-4369-a7b0-a6108c261c85", policy.getKey());
 
-        ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).setMaxLength(22);
+        ImplementationTO rule = implementationService.read(policy.getRules().get(0));
+        assertNotNull(rule);
+
+        DefaultPasswordRuleConf ruleConf = POJOHelper.deserialize(rule.getBody(), DefaultPasswordRuleConf.class);
+        ruleConf.setMaxLength(22);
+        rule.setBody(POJOHelper.serialize(ruleConf));
 
         // update new password policy
         policyService.update(policy);
         policy = policyService.read(policy.getKey());
-
         assertNotNull(policy);
-        assertEquals(22, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMaxLength());
-        assertEquals(8, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMinLength());
+
+        ruleConf = POJOHelper.deserialize(rule.getBody(), DefaultPasswordRuleConf.class);
+        assertEquals(22, ruleConf.getMaxLength());
+        assertEquals(8, ruleConf.getMinLength());
     }
 
     @Test
@@ -155,8 +184,9 @@ public class PolicyITCase extends AbstractITCase {
     }
 
     @Test
-    public void getCorrelationRules() {
-        assertEquals(1, syncopeService.platform().getPullCorrelationRules().size());
+    public void getPullCorrelationRuleJavaClasses() {
+        assertEquals(1, syncopeService.platform().
+                getJavaImplInfo(ImplementationType.PULL_CORRELATION_RULE).get().getClasses().size());
     }
 
     @Test
@@ -167,7 +197,16 @@ public class PolicyITCase extends AbstractITCase {
         DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
         ruleConf.setMinLength(3);
         ruleConf.setMaxLength(8);
-        policy.getRuleConfs().add(ruleConf);
+
+        ImplementationTO rule = new ImplementationTO();
+        rule.setKey("DefaultAccountRuleConf" + getUUIDString());
+        rule.setEngine(ImplementationEngine.JAVA);
+        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setBody(POJOHelper.serialize(ruleConf));
+        Response response = implementationService.create(rule);
+        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+
+        policy.getRules().add(rule.getKey());
 
         policy = createPolicy(policy);
         assertNotNull(policy);
@@ -182,7 +221,16 @@ public class PolicyITCase extends AbstractITCase {
         DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
         ruleConf.setMinLength(3);
         ruleConf.setMaxLength(8);
-        policy.getRuleConfs().add(ruleConf);
+
+        ImplementationTO rule = new ImplementationTO();
+        rule.setKey("DefaultAccountRuleConf" + getUUIDString());
+        rule.setEngine(ImplementationEngine.JAVA);
+        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setBody(POJOHelper.serialize(ruleConf));
+        Response response = implementationService.create(rule);
+        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+
+        policy.getRules().add(rule.getKey());
 
         policy = createPolicy(policy);
         assertNotNull(policy);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index c1ae0b8..a130bd5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -116,7 +116,7 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
         Optional<ItemTO> mappingItem = provision.getMapping().getItems().stream().
                 filter(item -> "location".equals(item.getIntAttrName())).findFirst();
         assertTrue(mappingItem.isPresent());
-        assertTrue(mappingItem.get().getTransformerClassNames().isEmpty());
+        assertTrue(mappingItem.get().getTransformers().isEmpty());
 
         String suffix = getUUIDString();
         mappingItem.get().setPropagationJEXLTransformer("value + '" + suffix + "'");

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index 391289a..5d67ece 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -62,6 +62,7 @@ import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
+import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -69,6 +70,8 @@ import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
 import org.apache.syncope.common.lib.types.PullMode;
@@ -76,6 +79,7 @@ import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.common.rest.api.service.TaskService;
 import org.apache.syncope.core.provisioning.java.pushpull.DBPasswordPullActions;
 import org.apache.syncope.core.provisioning.java.pushpull.LDAPPasswordPullActions;
@@ -100,14 +104,32 @@ public class PullTaskITCase extends AbstractTaskITCase {
 
     @BeforeAll
     public static void testPullActionsSetup() {
+        ImplementationTO pullActions = null;
+        try {
+            pullActions = implementationService.read(TestPullActions.class.getSimpleName());
+        } catch (SyncopeClientException e) {
+            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
+                pullActions = new ImplementationTO();
+                pullActions.setKey(TestPullActions.class.getSimpleName());
+                pullActions.setEngine(ImplementationEngine.JAVA);
+                pullActions.setType(ImplementationType.PULL_ACTIONS);
+                pullActions.setBody(TestPullActions.class.getName());
+                Response response = implementationService.create(pullActions);
+                pullActions = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+                assertNotNull(pullActions);
+            }
+        }
+        assertNotNull(pullActions);
+
         PullTaskTO pullTask = taskService.read(PULL_TASK_KEY, true);
-        pullTask.getActionsClassNames().add(TestPullActions.class.getName());
+        pullTask.getActions().add(pullActions.getKey());
         taskService.update(pullTask);
     }
 
     @Test
     public void getPullActionsClasses() {
-        Set<String> actions = syncopeService.platform().getPullActions();
+        Set<String> actions = syncopeService.platform().
+                getJavaImplInfo(ImplementationType.PULL_ACTIONS).get().getClasses();
         assertNotNull(actions);
         assertFalse(actions.isEmpty());
     }
@@ -147,7 +169,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
         task = taskService.read(actual.getKey(), true);
         assertNotNull(task);
         assertEquals(actual.getKey(), task.getKey());
-        assertEquals(actual.getJobDelegateClassName(), task.getJobDelegateClassName());
+        assertEquals(actual.getJobDelegate(), task.getJobDelegate());
         assertEquals(userTemplate, task.getTemplates().get(AnyTypeKind.USER.name()));
         assertEquals(groupTemplate, task.getTemplates().get(AnyTypeKind.GROUP.name()));
     }
@@ -406,8 +428,18 @@ public class PullTaskITCase extends AbstractTaskITCase {
         ItemTO mappingItem = provision.getMapping().getItems().stream().
                 filter(object -> "location".equals(object.getIntAttrName())).findFirst().get();
         assertNotNull(mappingItem);
-        mappingItem.getTransformerClassNames().clear();
-        mappingItem.getTransformerClassNames().add(PrefixItemTransformer.class.getName());
+
+        ImplementationTO transformer = new ImplementationTO();
+        transformer.setKey(PrefixItemTransformer.class.getSimpleName());
+        transformer.setEngine(ImplementationEngine.JAVA);
+        transformer.setType(ImplementationType.ITEM_TRANSFORMER);
+        transformer.setBody(PrefixItemTransformer.class.getName());
+        Response response = implementationService.create(transformer);
+        transformer = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+        assertNotNull(transformer);
+
+        mappingItem.getTransformers().clear();
+        mappingItem.getTransformers().add(transformer.getKey());
 
         try {
             resourceService.update(resource);
@@ -488,15 +520,22 @@ public class PullTaskITCase extends AbstractTaskITCase {
                     + "'" + user2OnTestPull + "', 'user2', 'Rossi', 'mail2@apache.org', NULL)");
 
             // 2. create new pull task for test-db, with reconciliation filter (surname 'Rossi') 
+            ImplementationTO reconFilterBuilder = new ImplementationTO();
+            reconFilterBuilder.setKey(TestReconciliationFilterBuilder.class.getSimpleName());
+            reconFilterBuilder.setEngine(ImplementationEngine.JAVA);
+            reconFilterBuilder.setType(ImplementationType.RECON_FILTER_BUILDER);
+            reconFilterBuilder.setBody(TestReconciliationFilterBuilder.class.getName());
+            Response response = implementationService.create(reconFilterBuilder);
+            reconFilterBuilder = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+            assertNotNull(reconFilterBuilder);
+
             task = taskService.read("7c2242f4-14af-4ab5-af31-cdae23783655", true);
             task.setPullMode(PullMode.FILTERED_RECONCILIATION);
-            task.setReconciliationFilterBuilderClassName(TestReconciliationFilterBuilder.class.getName());
-            Response response = taskService.create(task);
+            task.setReconFilterBuilder(reconFilterBuilder.getKey());
+            response = taskService.create(task);
             task = getObject(response.getLocation(), TaskService.class, PullTaskTO.class);
             assertNotNull(task);
-            assertEquals(
-                    TestReconciliationFilterBuilder.class.getName(),
-                    task.getReconciliationFilterBuilderClassName());
+            assertEquals(reconFilterBuilder.getKey(), task.getReconFilterBuilder());
 
             // 3. exec task
             ExecTO execution = execProvisioningTask(taskService, task.getKey(), 50, false);
@@ -714,8 +753,25 @@ public class PullTaskITCase extends AbstractTaskITCase {
         // -----------------------------
         // Add a custom correlation rule
         // -----------------------------
+        ImplementationTO corrRule = null;
+        try {
+            corrRule = implementationService.read(TestPullRule.class.getSimpleName());
+        } catch (SyncopeClientException e) {
+            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
+                corrRule = new ImplementationTO();
+                corrRule.setKey(TestPullRule.class.getSimpleName());
+                corrRule.setEngine(ImplementationEngine.JAVA);
+                corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
+                corrRule.setBody(TestPullRule.class.getName());
+                Response response = implementationService.create(corrRule);
+                corrRule = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+                assertNotNull(corrRule);
+            }
+        }
+        assertNotNull(corrRule);
+
         PullPolicyTO policyTO = policyService.read("9454b0d7-2610-400a-be82-fc23cf553dd6");
-        policyTO.getSpecification().getCorrelationRules().put(AnyTypeKind.USER.name(), TestPullRule.class.getName());
+        policyTO.getSpecification().getCorrelationRules().put(AnyTypeKind.USER.name(), corrRule.getKey());
         policyService.update(policyTO);
         // -----------------------------
 
@@ -856,6 +912,15 @@ public class PullTaskITCase extends AbstractTaskITCase {
         jdbcTemplate.execute("UPDATE test set PASSWORD='" + newPassword + "' where ID='" + user.getUsername() + "'");
 
         // 4. Pull the user from the resource
+        ImplementationTO pullActions = new ImplementationTO();
+        pullActions.setKey(DBPasswordPullActions.class.getSimpleName());
+        pullActions.setEngine(ImplementationEngine.JAVA);
+        pullActions.setType(ImplementationType.PULL_ACTIONS);
+        pullActions.setBody(DBPasswordPullActions.class.getName());
+        Response response = implementationService.create(pullActions);
+        pullActions = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+        assertNotNull(pullActions);
+
         PullTaskTO pullTask = new PullTaskTO();
         pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
         pullTask.setName("DB Pull Task");
@@ -864,7 +929,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
         pullTask.setPerformUpdate(true);
         pullTask.setPullMode(PullMode.FULL_RECONCILIATION);
         pullTask.setResource(RESOURCE_NAME_TESTDB);
-        pullTask.getActionsClassNames().add(DBPasswordPullActions.class.getName());
+        pullTask.getActions().add(pullActions.getKey());
         Response taskResponse = taskService.create(pullTask);
 
         PullTaskTO actual = getObject(taskResponse.getLocation(), TaskService.class, PullTaskTO.class);
@@ -873,7 +938,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
         pullTask = taskService.read(actual.getKey(), true);
         assertNotNull(pullTask);
         assertEquals(actual.getKey(), pullTask.getKey());
-        assertEquals(actual.getJobDelegateClassName(), pullTask.getJobDelegateClassName());
+        assertEquals(actual.getJobDelegate(), pullTask.getJobDelegate());
 
         ExecTO execution = execProvisioningTask(taskService, pullTask.getKey(), 50, false);
         assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
@@ -936,6 +1001,15 @@ public class PullTaskITCase extends AbstractTaskITCase {
             connectorService.update(resourceConnector);
 
             // 6. Pull the user from the resource
+            ImplementationTO pullActions = new ImplementationTO();
+            pullActions.setKey(LDAPPasswordPullActions.class.getSimpleName());
+            pullActions.setEngine(ImplementationEngine.JAVA);
+            pullActions.setType(ImplementationType.PULL_ACTIONS);
+            pullActions.setBody(LDAPPasswordPullActions.class.getName());
+            Response response = implementationService.create(pullActions);
+            pullActions = getObject(response.getLocation(), ImplementationService.class, ImplementationTO.class);
+            assertNotNull(pullActions);
+
             pullTask = new PullTaskTO();
             pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
             pullTask.setName("LDAP Pull Task");
@@ -944,7 +1018,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
             pullTask.setPerformUpdate(true);
             pullTask.setPullMode(PullMode.FULL_RECONCILIATION);
             pullTask.setResource(RESOURCE_NAME_LDAP);
-            pullTask.getActionsClassNames().add(LDAPPasswordPullActions.class.getName());
+            pullTask.getActions().add(pullActions.getKey());
             Response taskResponse = taskService.create(pullTask);
 
             pullTask = getObject(taskResponse.getLocation(), TaskService.class, PullTaskTO.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
index 17d9c05..c46c445 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
@@ -45,6 +45,7 @@ import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -70,7 +71,8 @@ public class PushTaskITCase extends AbstractTaskITCase {
 
     @Test
     public void getPushActionsClasses() {
-        Set<String> actions = syncopeService.platform().getPushActions();
+        Set<String> actions = syncopeService.platform().
+                getJavaImplInfo(ImplementationType.PUSH_ACTIONS).get().getClasses();
         assertNotNull(actions);
     }
 
@@ -110,7 +112,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         task = taskService.read(actual.getKey(), true);
         assertNotNull(task);
         assertEquals(task.getKey(), actual.getKey());
-        assertEquals(task.getJobDelegateClassName(), actual.getJobDelegateClassName());
+        assertEquals(task.getJobDelegate(), actual.getJobDelegate());
         assertEquals(task.getFilters().get(AnyTypeKind.USER.name()),
                 actual.getFilters().get(AnyTypeKind.USER.name()));
         assertEquals(task.getFilters().get(AnyTypeKind.GROUP.name()),

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index 751b9d3..23c202a 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.UUID;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -34,10 +35,15 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
+import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.RealmService;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.fit.AbstractITCase;
 import org.junit.jupiter.api.Test;
 
@@ -122,13 +128,21 @@ public class RealmITCase extends AbstractITCase {
     @Test
     public void deletingAccountPolicy() {
         // 1. create account policy
-        AccountPolicyTO policy = new AccountPolicyTO();
-        policy.setDescription("deletingAccountPolicy");
-
         DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
         ruleConf.setMinLength(3);
         ruleConf.setMaxLength(8);
-        policy.getRuleConfs().add(ruleConf);
+
+        ImplementationTO rule = new ImplementationTO();
+        rule.setKey("DefaultAccountRuleConf" + UUID.randomUUID().toString());
+        rule.setEngine(ImplementationEngine.JAVA);
+        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setBody(POJOHelper.serialize(ruleConf));
+        Response response = implementationService.create(rule);
+        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+
+        AccountPolicyTO policy = new AccountPolicyTO();
+        policy.setDescription("deletingAccountPolicy");
+        policy.getRules().add(rule.getKey());
 
         policy = createPolicy(policy);
         assertNotNull(policy);
@@ -138,7 +152,7 @@ public class RealmITCase extends AbstractITCase {
         realm.setName("withppolicy");
         realm.setAccountPolicy(policy.getKey());
 
-        Response response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
+        response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
         RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
         assertNotNull(actuals);
         assertTrue(actuals.length > 0);


Mime
View raw message