You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/10/10 06:36:56 UTC

[07/18] syncope git commit: [SYNCOPE-956] Core implementation

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
new file mode 100644
index 0000000..b212021
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
@@ -0,0 +1,77 @@
+/*
+ * 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.common.lib.to;
+
+import javax.ws.rs.PathParam;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+
+@XmlRootElement(name = "implementation")
+@XmlType
+public class ImplementationTO extends AbstractBaseBean implements EntityTO {
+
+    private static final long serialVersionUID = 2703397698393060586L;
+
+    private String key;
+
+    private ImplementationEngine engine;
+
+    private ImplementationType type;
+
+    private String body;
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @PathParam("key")
+    @Override
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public ImplementationEngine getEngine() {
+        return engine;
+    }
+
+    public void setEngine(final ImplementationEngine engine) {
+        this.engine = engine;
+    }
+
+    public ImplementationType getType() {
+        return type;
+    }
+
+    public void setType(final ImplementationType type) {
+        this.type = type;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    public void setBody(final String body) {
+        this.body = body;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
index 603b4d3..0bed627 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
@@ -77,7 +77,7 @@ public class ItemTO extends AbstractBaseBean implements EntityTO {
      */
     private String pullJEXLTransformer;
 
-    private final List<String> transformerClassNames = new ArrayList<>();
+    private final List<String> transformers = new ArrayList<>();
 
     public boolean isConnObjectKey() {
         return connObjectKey;
@@ -153,11 +153,10 @@ public class ItemTO extends AbstractBaseBean implements EntityTO {
         this.pullJEXLTransformer = pullJEXLTransformer;
     }
 
-    @XmlElementWrapper(name = "transformerClassNames")
-    @XmlElement(name = "transformerClassName")
-    @JsonProperty("transformerClassNames")
-    public List<String> getTransformerClassNames() {
-        return transformerClassNames;
+    @XmlElementWrapper(name = "transformers")
+    @XmlElement(name = "transformer")
+    @JsonProperty("transformers")
+    public List<String> getTransformers() {
+        return transformers;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
index 428efde..d09fe07 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
@@ -56,7 +56,7 @@ public class NotificationTO extends AbstractBaseBean implements EntityTO {
 
     private boolean selfAsRecipient;
 
-    private String recipientsProviderClassName;
+    private String recipientsProvider;
 
     private String sender;
 
@@ -122,12 +122,12 @@ public class NotificationTO extends AbstractBaseBean implements EntityTO {
         this.selfAsRecipient = selfAsRecipient;
     }
 
-    public String getRecipientsProviderClassName() {
-        return recipientsProviderClassName;
+    public String getRecipientsProvider() {
+        return recipientsProvider;
     }
 
-    public void setRecipientsProviderClassName(final String recipientsProviderClassName) {
-        this.recipientsProviderClassName = recipientsProviderClassName;
+    public void setRecipientsProvider(final String recipientsProvider) {
+        this.recipientsProvider = recipientsProvider;
     }
 
     public String getSender() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
index 9aaccf2..0b70608 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
@@ -39,7 +39,7 @@ public class PullTaskTO extends AbstractProvisioningTaskTO implements Templatabl
 
     private PullMode pullMode;
 
-    private String reconciliationFilterBuilderClassName;
+    private String reconFilterBuilder;
 
     private String destinationRealm;
 
@@ -55,12 +55,12 @@ public class PullTaskTO extends AbstractProvisioningTaskTO implements Templatabl
         this.pullMode = pullMode;
     }
 
-    public String getReconciliationFilterBuilderClassName() {
-        return reconciliationFilterBuilderClassName;
+    public String getReconFilterBuilder() {
+        return reconFilterBuilder;
     }
 
-    public void setReconciliationFilterBuilderClassName(final String reconciliationFilterBuilderClassName) {
-        this.reconciliationFilterBuilderClassName = reconciliationFilterBuilderClassName;
+    public void setReconFilterBuilder(final String reconFilterBuilder) {
+        this.reconFilterBuilder = reconFilterBuilder;
     }
 
     public String getDestinationRealm() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
index db770e7..7615d8f 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
@@ -20,8 +20,10 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import javax.ws.rs.PathParam;
@@ -51,7 +53,7 @@ public class RealmTO extends AbstractBaseBean implements EntityTO, TemplatableTO
 
     private String passwordPolicy;
 
-    private final Set<String> actionsClassNames = new HashSet<>();
+    private final List<String> actions = new ArrayList<>();
 
     @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
     @JsonIgnore
@@ -110,11 +112,11 @@ public class RealmTO extends AbstractBaseBean implements EntityTO, TemplatableTO
         this.passwordPolicy = passwordPolicy;
     }
 
-    @XmlElementWrapper(name = "actionsClassNames")
-    @XmlElement(name = "actionsClassName")
-    @JsonProperty("actionsClassNames")
-    public Set<String> getActionsClassNames() {
-        return actionsClassNames;
+    @XmlElementWrapper(name = "actions")
+    @XmlElement(name = "action")
+    @JsonProperty("actions")
+    public List<String> getActions() {
+        return actions;
     }
 
     @JsonProperty

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
index 73b16f7..636f3eb 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReportTO.java
@@ -27,7 +27,6 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.report.AbstractReportletConf;
 
 @XmlRootElement(name = "report")
 @XmlType
@@ -39,7 +38,7 @@ public class ReportTO extends AbstractStartEndBean implements EntityTO {
 
     private String name;
 
-    private final List<AbstractReportletConf> reportletConfs = new ArrayList<>();
+    private final List<String> reportlets = new ArrayList<>();
 
     private String cronExpression;
 
@@ -74,11 +73,11 @@ public class ReportTO extends AbstractStartEndBean implements EntityTO {
         this.name = name;
     }
 
-    @XmlElementWrapper(name = "reportletConfs")
-    @XmlElement(name = "reportletConf")
-    @JsonProperty("reportletConfs")
-    public List<AbstractReportletConf> getReportletConfs() {
-        return reportletConfs;
+    @XmlElementWrapper(name = "reportlets")
+    @XmlElement(name = "reportlets")
+    @JsonProperty("reportlets")
+    public List<String> getReportlets() {
+        return reportlets;
     }
 
     public String getCronExpression() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
index 6286e93..ab7e0e6 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
@@ -83,7 +83,7 @@ public class ResourceTO extends AbstractBaseBean implements EntityTO {
 
     private final Set<ConnectorCapability> capabilitiesOverride = EnumSet.noneOf(ConnectorCapability.class);
 
-    private final List<String> propagationActionsClassNames = new ArrayList<>();
+    private final List<String> propagationActions = new ArrayList<>();
 
     @Override
     public String getKey() {
@@ -236,11 +236,10 @@ public class ResourceTO extends AbstractBaseBean implements EntityTO {
         this.provisioningTraceLevel = provisioningTraceLevel;
     }
 
-    @XmlElementWrapper(name = "propagationActionsClassNames")
-    @XmlElement(name = "propagationActionsClassName")
-    @JsonProperty("propagationActionsClassNames")
-    public List<String> getPropagationActionsClassNames() {
-        return propagationActionsClassNames;
+    @XmlElementWrapper(name = "propagationActions")
+    @XmlElement(name = "propagationAction")
+    @JsonProperty("propagationActions")
+    public List<String> getPropagationActions() {
+        return propagationActions;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
index 90748ec..e6c0697 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
@@ -35,7 +35,7 @@ public class SchedTaskTO extends AbstractTaskTO {
 
     private String cronExpression;
 
-    private String jobDelegateClassName;
+    private String jobDelegate;
 
     private String name;
 
@@ -63,12 +63,12 @@ public class SchedTaskTO extends AbstractTaskTO {
         this.cronExpression = cronExpression;
     }
 
-    public String getJobDelegateClassName() {
-        return jobDelegateClassName;
+    public String getJobDelegate() {
+        return jobDelegate;
     }
 
-    public void setJobDelegateClassName(final String jobDelegateClassName) {
-        this.jobDelegateClassName = jobDelegateClassName;
+    public void setJobDelegate(final String jobDelegate) {
+        this.jobDelegate = jobDelegate;
     }
 
     public Date getLastExec() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index 1927737..92238d8 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -31,6 +31,7 @@ public enum ClientExceptionType {
     EntityExists(Response.Status.CONFLICT),
     GenericPersistence(Response.Status.BAD_REQUEST),
     HasChildren(Response.Status.BAD_REQUEST),
+    InvalidImplementation(Response.Status.BAD_REQUEST),
     InvalidSecurityAnswer(Response.Status.BAD_REQUEST),
     InvalidEntity(Response.Status.BAD_REQUEST),
     InvalidLogger(Response.Status.BAD_REQUEST),

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationEngine.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationEngine.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationEngine.java
new file mode 100644
index 0000000..36baddd
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationEngine.java
@@ -0,0 +1,39 @@
+/*
+ * 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.common.lib.types;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum
+public enum ImplementationEngine {
+
+    JAVA("application/java"),
+    GROOVY("application/x-groovy");
+
+    private final String mimeType;
+
+    ImplementationEngine(final String mimeType) {
+        this.mimeType = mimeType;
+    }
+
+    public String getMimeType() {
+        return mimeType;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
new file mode 100644
index 0000000..c528274
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
@@ -0,0 +1,42 @@
+/*
+ * 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.common.lib.types;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum
+public enum ImplementationType {
+
+    JWT_SSO_PROVIDER,
+    REPORTLET,
+    ACCOUNT_RULE,
+    PASSWORD_RULE,
+    ITEM_TRANSFORMER,
+    TASKJOB_DELEGATE,
+    RECON_FILTER_BUILDER,
+    LOGIC_ACTIONS,
+    PROPAGATION_ACTIONS,
+    PULL_ACTIONS,
+    PUSH_ACTIONS,
+    PULL_CORRELATION_RULE,
+    VALIDATOR,
+    RECIPIENTS_PROVIDER,
+    AUDIT_APPENDER;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
index 8a7fe36..4942037 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
@@ -282,6 +282,16 @@ public final class StandardEntitlement {
 
     public static final String ACCESS_TOKEN_DELETE = "TASK_DELETE";
 
+    public static final String IMPLEMENTATION_LIST = "IMPLEMENTATION_LIST";
+
+    public static final String IMPLEMENTATION_READ = "IMPLEMENTATION_READ";
+
+    public static final String IMPLEMENTATION_CREATE = "IMPLEMENTATION_CREATE";
+
+    public static final String IMPLEMENTATION_UPDATE = "IMPLEMENTATION_UPDATE";
+
+    public static final String IMPLEMENTATION_DELETE = "IMPLEMENTATION_DELETE";
+
     private static final Set<String> VALUES;
 
     static {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
----------------------------------------------------------------------
diff --git a/common/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java b/common/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
index 7c50063..bf2ab85 100644
--- a/common/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
+++ b/common/lib/src/test/java/org/apache/syncope/common/lib/JSONTest.java
@@ -30,13 +30,11 @@ import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.patch.StringReplacePatchItem;
 import org.apache.syncope.common.lib.patch.UserPatch;
-import org.apache.syncope.common.lib.report.UserReportletConf;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
-import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.junit.jupiter.api.Test;
@@ -59,22 +57,6 @@ public class JSONTest {
     }
 
     @Test
-    public void reportletConfImplementations() throws IOException {
-        ReportTO report = new ReportTO();
-        report.setName("testReportForCreate");
-        report.getReportletConfs().add(new UserReportletConf("first"));
-        report.getReportletConfs().add(new UserReportletConf("second"));
-
-        ObjectMapper mapper = new ObjectMapper();
-
-        StringWriter writer = new StringWriter();
-        mapper.writeValue(writer, report);
-
-        ReportTO actual = mapper.readValue(writer.toString(), ReportTO.class);
-        assertEquals(report, actual);
-    }
-
-    @Test
     public void patch() throws IOException {
         UserPatch patch = new UserPatch();
         patch.setKey(UUID.randomUUID().toString());

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
new file mode 100644
index 0000000..4dffa0d
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
@@ -0,0 +1,92 @@
+/*
+ * 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.common.rest.api.service;
+
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationType;
+
+/**
+ * REST operations for implementations.
+ */
+@Path("implementations")
+public interface ImplementationService extends JAXRSService {
+
+    /**
+     * Returns a list of all implementations.
+     *
+     * @param type implementation type
+     * @return list of all implementations.
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    List<ImplementationTO> list(@NotNull @MatrixParam("type") ImplementationType type);
+
+    /**
+     * Returns implementation with matching key.
+     *
+     * @param key key of implementation to be read
+     * @return implementation with matching key
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    ImplementationTO read(@NotNull @PathParam("key") String key);
+
+    /**
+     * Creates a new implementation.
+     *
+     * @param implementationTO implementation.
+     * @return Response object featuring Location header of created implementation
+     */
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    Response create(@NotNull ImplementationTO implementationTO);
+
+    /**
+     * Updates an existing implementation.
+     *
+     * @param implementationTO implementation.
+     */
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    void update(@NotNull ImplementationTO implementationTO);
+
+    /**
+     * Deletes the implementation matching the given key.
+     *
+     * @param key key for implementation to be deleted
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") String key);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
index ad43e0e..4e84455 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
@@ -37,7 +37,6 @@ import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
 import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
@@ -48,8 +47,8 @@ import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.provisioning.api.LogicActions;
 import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
+import org.apache.syncope.core.spring.ImplementationManager;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
 
 public abstract class AbstractAnyLogic<TO extends AnyTO, P extends AnyPatch> extends AbstractResourceAssociator<TO> {
 
@@ -74,15 +73,11 @@ public abstract class AbstractAnyLogic<TO extends AnyTO, P extends AnyPatch> ext
     private List<LogicActions> getActions(final Realm realm) {
         List<LogicActions> actions = new ArrayList<>();
 
-        realm.getActionsClassNames().forEach(className -> {
+        realm.getActions().forEach(impl -> {
             try {
-                Class<?> actionsClass = Class.forName(className);
-                LogicActions logicActions = (LogicActions) ApplicationContextProvider.getBeanFactory().
-                        createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-
-                actions.add(logicActions);
+                actions.add(ImplementationManager.build(impl));
             } catch (Exception e) {
-                LOG.warn("Class '{}' not found", className, e);
+                LOG.warn("While building {}", impl, e);
             }
         });
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index ace95de..55e9b3e 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -42,16 +42,20 @@ import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.BulkMembersActionType;
 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.JobType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 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.group.Group;
 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.provisioning.api.GroupProvisioningManager;
@@ -86,6 +90,9 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> {
     protected AnySearchDAO searchDAO;
 
     @Autowired
+    protected ImplementationDAO implementationDAO;
+
+    @Autowired
     protected TaskDAO taskDAO;
 
     @Autowired
@@ -376,10 +383,22 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> {
             throw new NotFoundException("Group " + key);
         }
 
+        Implementation jobDelegate = implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+                filter(impl -> GroupMemberProvisionTaskJobDelegate.class.getName().equals(impl.getBody())).
+                findFirst().orElse(null);
+        if (jobDelegate == null) {
+            jobDelegate = entityFactory.newEntity(Implementation.class);
+            jobDelegate.setKey(GroupMemberProvisionTaskJobDelegate.class.getSimpleName());
+            jobDelegate.setEngine(ImplementationEngine.JAVA);
+            jobDelegate.setType(ImplementationType.TASKJOB_DELEGATE);
+            jobDelegate.setBody(GroupMemberProvisionTaskJobDelegate.class.getName());
+            jobDelegate = implementationDAO.save(jobDelegate);
+        }
+
         SchedTask task = entityFactory.newEntity(SchedTask.class);
         task.setName("Bulk member provision for group " + group.getName());
         task.setActive(true);
-        task.setJobDelegateClassName(GroupMemberProvisionTaskJobDelegate.class.getName());
+        task.setJobDelegate(jobDelegate);
         task = taskDAO.save(task);
 
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
new file mode 100644
index 0000000..5dca6f5
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
@@ -0,0 +1,124 @@
+/*
+ * 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.logic;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ImplementationLogic extends AbstractTransactionalLogic<ImplementationTO> {
+
+    @Autowired
+    private ImplementationDataBinder binder;
+
+    @Autowired
+    private ImplementationDAO implementationDAO;
+
+    @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_LIST + "')")
+    public List<ImplementationTO> list(final ImplementationType type) {
+        return implementationDAO.find(type).stream().
+                map(implementation -> binder.getImplementationTO(implementation)).collect(Collectors.toList());
+    }
+
+    @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_READ + "')")
+    public ImplementationTO read(final String key) {
+        Implementation implementation = implementationDAO.find(key);
+        if (implementation == null) {
+            LOG.error("Could not find implementation '" + key + "'");
+
+            throw new NotFoundException(key);
+        }
+
+        return binder.getImplementationTO(implementation);
+    }
+
+    @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_CREATE + "')")
+    public ImplementationTO create(final ImplementationTO implementationTO) {
+        return binder.getImplementationTO(implementationDAO.save(binder.create(implementationTO)));
+    }
+
+    @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_UPDATE + "')")
+    public ImplementationTO update(final ImplementationTO implementationTO) {
+        Implementation implementation = implementationDAO.find(implementationTO.getKey());
+        if (implementation == null) {
+            LOG.error("Could not find implementation '" + implementationTO.getKey() + "'");
+
+            throw new NotFoundException(implementationTO.getKey());
+        }
+
+        binder.update(implementation, implementationTO);
+        implementation = implementationDAO.save(implementation);
+
+        return binder.getImplementationTO(implementation);
+    }
+
+    @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_DELETE + "')")
+    public void delete(final String key) {
+        Implementation implementation = implementationDAO.find(key);
+        if (implementation == null) {
+            LOG.error("Could not find implementation '" + key + "'");
+
+            throw new NotFoundException(key);
+        }
+
+        implementationDAO.delete(key);
+    }
+
+    @Override
+    protected ImplementationTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof String) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof ImplementationTO) {
+                    key = ((ImplementationTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getImplementationTO(implementationDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/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 a3f3a3a..0867c62 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
@@ -42,7 +42,6 @@ import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AuditElements;
@@ -52,10 +51,8 @@ import org.apache.syncope.core.logic.init.LoggerLoader;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
-import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Logger;
-import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.spring.BeanUtils;
 import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
 import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
@@ -86,9 +83,6 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
     private ExternalResourceDAO resourceDAO;
 
     @Autowired
-    private TaskDAO taskDAO;
-
-    @Autowired
     private EntityFactory entityFactory;
 
     private List<LoggerTO> list(final LoggerType type) {
@@ -385,12 +379,6 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
                 });
             }
 
-            for (SchedTask task : taskDAO.<SchedTask>findAll(TaskType.SCHEDULED)) {
-                EventCategoryTO eventCategoryTO = new EventCategoryTO(EventCategoryType.TASK);
-                eventCategoryTO.setCategory(Class.forName(task.getJobDelegateClassName()).getSimpleName());
-                events.add(eventCategoryTO);
-            }
-
             EventCategoryTO eventCategoryTO = new EventCategoryTO(EventCategoryType.TASK);
             eventCategoryTO.setCategory(PullJobDelegate.class.getSimpleName());
             events.add(eventCategoryTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index 95027d8..427c1e5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -24,6 +24,7 @@ import java.lang.management.RuntimeMXBean;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -34,16 +35,17 @@ import javax.annotation.Resource;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.info.NumbersInfo;
 import org.apache.syncope.common.lib.info.SystemInfo;
 import org.apache.syncope.common.lib.info.PlatformInfo;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.TypeExtensionTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.spring.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
-import org.apache.syncope.core.persistence.api.ImplementationLookup.Type;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
@@ -221,23 +223,14 @@ public class SyncopeLogic extends AbstractLogic<AbstractBaseBean> {
                 PLATFORM_INFO.setPasswordGenerator(AopUtils.getTargetClass(passwordGenerator).getName());
                 PLATFORM_INFO.setAnySearchDAO(AopUtils.getTargetClass(anySearchDAO).getName());
 
-                PLATFORM_INFO.getJwtSSOProviders().addAll(implLookup.getClassNames(Type.JWT_SSO_PROVIDER));
-                PLATFORM_INFO.getReportletConfs().addAll(implLookup.getClassNames(Type.REPORTLET_CONF));
-                PLATFORM_INFO.getAccountRules().addAll(implLookup.getClassNames(Type.ACCOUNT_RULE_CONF));
-                PLATFORM_INFO.getPasswordRules().addAll(implLookup.getClassNames(Type.PASSWORD_RULE_CONF));
-                PLATFORM_INFO.getItemTransformers().addAll(
-                        implLookup.getClassNames(Type.ITEM_TRANSFORMER));
-                PLATFORM_INFO.getTaskJobs().addAll(implLookup.getClassNames(Type.TASKJOBDELEGATE));
-                PLATFORM_INFO.getReconciliationFilterBuilders().
-                        addAll(implLookup.getClassNames(Type.RECONCILIATION_FILTER_BUILDER));
-                PLATFORM_INFO.getLogicActions().addAll(implLookup.getClassNames(Type.LOGIC_ACTIONS));
-                PLATFORM_INFO.getPropagationActions().addAll(implLookup.getClassNames(Type.PROPAGATION_ACTIONS));
-                PLATFORM_INFO.getPullActions().addAll(implLookup.getClassNames(Type.PULL_ACTIONS));
-                PLATFORM_INFO.getPushActions().addAll(implLookup.getClassNames(Type.PUSH_ACTIONS));
-                PLATFORM_INFO.getPullCorrelationRules().addAll(implLookup.getClassNames(Type.PULL_CORRELATION_RULE));
-                PLATFORM_INFO.getValidators().addAll(implLookup.getClassNames(Type.VALIDATOR));
-                PLATFORM_INFO.getNotificationRecipientsProviders().
-                        addAll(implLookup.getClassNames(Type.NOTIFICATION_RECIPIENTS_PROVIDER));
+                Arrays.stream(ImplementationType.values()).
+                        forEach(type -> {
+                            JavaImplInfo javaImplInfo = new JavaImplInfo();
+                            javaImplInfo.setType(type);
+                            javaImplInfo.getClasses().addAll(implLookup.getClassNames(type));
+
+                            PLATFORM_INFO.getJavaImplInfos().add(javaImplInfo);
+                        });
             }
 
             PLATFORM_INFO.setSelfRegAllowed(isSelfRegAllowed());

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index ebe1e5d..8aa628f 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
@@ -40,12 +41,12 @@ import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
 import org.apache.syncope.core.provisioning.api.LogicActions;
 import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
-import org.apache.syncope.core.provisioning.api.notification.NotificationRecipientsProvider;
+import org.apache.syncope.core.provisioning.api.notification.RecipientsProvider;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
 import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
 import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
-import org.apache.syncope.core.provisioning.api.pushpull.ReconciliationFilterBuilder;
+import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
 import org.apache.syncope.core.provisioning.java.data.JEXLItemTransformerImpl;
 import org.apache.syncope.core.provisioning.java.job.GroupMemberProvisionTaskJobDelegate;
 import org.apache.syncope.core.provisioning.java.pushpull.PlainAttrsPullCorrelationRule;
@@ -54,7 +55,6 @@ import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
 import org.apache.syncope.core.spring.security.JWTSSOProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
 import org.springframework.core.type.filter.AssignableTypeFilter;
 import org.springframework.util.ClassUtils;
@@ -68,7 +68,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
 
     private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.core";
 
-    private Map<Type, Set<String>> classNames;
+    private Map<ImplementationType, Set<String>> classNames;
 
     private Set<Class<?>> jwtSSOProviderClasses;
 
@@ -97,8 +97,8 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
     @Override
     @SuppressWarnings("unchecked")
     public void load() {
-        classNames = new EnumMap<>(Type.class);
-        for (Type type : Type.values()) {
+        classNames = new EnumMap<>(ImplementationType.class);
+        for (ImplementationType type : ImplementationType.values()) {
             classNames.put(type, new HashSet<>());
         }
 
@@ -115,24 +115,24 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
         scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRule.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(ItemTransformer.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(SchedTaskJobDelegate.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(ReconciliationFilterBuilder.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(ReconFilterBuilder.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(LogicActions.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PropagationActions.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PullActions.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PushActions.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PullCorrelationRule.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(Validator.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(NotificationRecipientsProvider.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(RecipientsProvider.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(AuditAppender.class));
 
-        for (BeanDefinition bd : scanner.findCandidateComponents(getBasePackage())) {
+        scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
             try {
                 Class<?> clazz = ClassUtils.resolveClassName(
                         bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
                 boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
 
                 if (JWTSSOProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.JWT_SSO_PROVIDER).add(clazz.getName());
+                    classNames.get(ImplementationType.JWT_SSO_PROVIDER).add(clazz.getName());
                     jwtSSOProviderClasses.add(clazz);
                 }
 
@@ -141,7 +141,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found Reportlet {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(Type.REPORTLET_CONF).add(annotation.value().getName());
+                        classNames.get(ImplementationType.REPORTLET).add(clazz.getName());
                         reportletClasses.put(annotation.value(), (Class<? extends Reportlet>) clazz);
                     }
                 }
@@ -151,7 +151,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found account policy rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(Type.ACCOUNT_RULE_CONF).add(annotation.value().getName());
+                        classNames.get(ImplementationType.ACCOUNT_RULE).add(clazz.getName());
                         accountRuleClasses.put(annotation.value(), (Class<? extends AccountRule>) clazz);
                     }
                 }
@@ -161,7 +161,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found password policy rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(Type.PASSWORD_RULE_CONF).add(annotation.value().getName());
+                        classNames.get(ImplementationType.PASSWORD_RULE).add(clazz.getName());
                         passwordRuleClasses.put(annotation.value(), (Class<? extends PasswordRule>) clazz);
                     }
                 }
@@ -169,7 +169,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                 if (ItemTransformer.class.isAssignableFrom(clazz) && !isAbstractClazz
                         && !clazz.equals(JEXLItemTransformerImpl.class)) {
 
-                    classNames.get(Type.ITEM_TRANSFORMER).add(clazz.getName());
+                    classNames.get(ImplementationType.ITEM_TRANSFORMER).add(clazz.getName());
                 }
 
                 if (SchedTaskJobDelegate.class.isAssignableFrom(clazz) && !isAbstractClazz
@@ -177,60 +177,64 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                         && !PushJobDelegate.class.isAssignableFrom(clazz)
                         && !GroupMemberProvisionTaskJobDelegate.class.isAssignableFrom(clazz)) {
 
-                    classNames.get(Type.TASKJOBDELEGATE).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.TASKJOB_DELEGATE).add(bd.getBeanClassName());
                 }
 
-                if (ReconciliationFilterBuilder.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.RECONCILIATION_FILTER_BUILDER).add(bd.getBeanClassName());
+                if (ReconFilterBuilder.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+                    classNames.get(ImplementationType.RECON_FILTER_BUILDER).add(bd.getBeanClassName());
                 }
 
                 if (LogicActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.LOGIC_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.LOGIC_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PropagationActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.PROPAGATION_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.PROPAGATION_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PullActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.PULL_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.PULL_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PushActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.PUSH_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.PUSH_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PullCorrelationRule.class.isAssignableFrom(clazz) && !isAbstractClazz
                         && !PlainAttrsPullCorrelationRule.class.isAssignableFrom(clazz)) {
-                    classNames.get(Type.PULL_CORRELATION_RULE).add(bd.getBeanClassName());
+
+                    classNames.get(ImplementationType.PULL_CORRELATION_RULE).add(bd.getBeanClassName());
                 }
 
                 if (Validator.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.VALIDATOR).add(bd.getBeanClassName());
+                    classNames.get(ImplementationType.VALIDATOR).add(bd.getBeanClassName());
                 }
 
-                if (NotificationRecipientsProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.NOTIFICATION_RECIPIENTS_PROVIDER).add(bd.getBeanClassName());
+                if (RecipientsProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+                    classNames.get(ImplementationType.RECIPIENTS_PROVIDER).add(bd.getBeanClassName());
                 }
 
                 if (AuditAppender.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(Type.AUDIT_APPENDER).add(clazz.getName());
+                    classNames.get(ImplementationType.AUDIT_APPENDER).add(clazz.getName());
                     auditAppenderClasses.add(clazz);
                 }
             } catch (Throwable t) {
                 LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
             }
-        }
+        });
+
         classNames = Collections.unmodifiableMap(classNames);
+        LOG.debug("Implementation classes found: {}", classNames);
+
+        jwtSSOProviderClasses = Collections.unmodifiableSet(jwtSSOProviderClasses);
         reportletClasses = Collections.unmodifiableMap(reportletClasses);
         accountRuleClasses = Collections.unmodifiableMap(accountRuleClasses);
         passwordRuleClasses = Collections.unmodifiableMap(passwordRuleClasses);
-
-        LOG.debug("Implementation classes found: {}", classNames);
+        auditAppenderClasses = Collections.unmodifiableSet(auditAppenderClasses);
     }
 
     @Override
-    public Set<String> getClassNames(final Type type) {
+    public Set<String> getClassNames(final ImplementationType type) {
         return classNames.get(type);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
index a81a2d6..774928d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
@@ -22,33 +22,14 @@ import java.util.Set;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
 import org.apache.syncope.core.persistence.api.dao.Reportlet;
 
 public interface ImplementationLookup extends SyncopeLoader {
 
-    enum Type {
-
-        JWT_SSO_PROVIDER,
-        REPORTLET_CONF,
-        ACCOUNT_RULE_CONF,
-        PASSWORD_RULE_CONF,
-        ITEM_TRANSFORMER,
-        TASKJOBDELEGATE,
-        RECONCILIATION_FILTER_BUILDER,
-        LOGIC_ACTIONS,
-        PROPAGATION_ACTIONS,
-        PULL_ACTIONS,
-        PUSH_ACTIONS,
-        PULL_CORRELATION_RULE,
-        VALIDATOR,
-        NOTIFICATION_RECIPIENTS_PROVIDER,
-        AUDIT_APPENDER;
-
-    }
-
-    Set<String> getClassNames(Type type);
+    Set<String> getClassNames(ImplementationType type);
 
     Set<Class<?>> getJWTSSOProviderClasses();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/Validator.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/Validator.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/Validator.java
index c9fad02..5b49b4c 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/Validator.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/Validator.java
@@ -19,8 +19,11 @@
 package org.apache.syncope.core.persistence.api.attrvalue.validation;
 
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 
 public interface Validator {
 
+    void setSchema(PlainSchema schema);
+
     void validate(String value, PlainAttrValue attrValue);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
index 25145de..9327266 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
@@ -26,5 +26,7 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
  */
 public interface AccountRule {
 
-    void enforce(AccountRuleConf conf, User user);
+    void setConf(AccountRuleConf conf);
+
+    void enforce(User user);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
new file mode 100644
index 0000000..71b7399
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
@@ -0,0 +1,37 @@
+/*
+ * 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.api.dao;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+
+public interface ImplementationDAO extends DAO<Implementation> {
+
+    Implementation find(String key);
+
+    List<Implementation> find(ImplementationType type);
+
+    List<Implementation> findAll();
+
+    Implementation save(Implementation implementation);
+
+    void delete(String key);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
index 4cb1ba9..8ac914a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
@@ -26,5 +26,9 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
  */
 public interface PasswordRule {
 
-    void enforce(PasswordRuleConf conf, User user);
+    PasswordRuleConf getConf();
+
+    void setConf(PasswordRuleConf conf);
+
+    void enforce(User user);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java
index 8180831..5366403 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java
@@ -30,11 +30,17 @@ import org.xml.sax.SAXException;
 public interface Reportlet {
 
     /**
-     * Actual data extraction for reporting.
+     * Optional configuration.
      *
      * @param conf configuration
+     */
+    void setConf(ReportletConf conf);
+
+    /**
+     * Actual data extraction for reporting.
+     *
      * @param handler SAX content handler for streaming result
      * @throws SAXException if there is any problem in SAX handling
      */
-    void extract(ReportletConf conf, ContentHandler handler) throws SAXException;
+    void extract(ContentHandler handler) throws SAXException;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
new file mode 100644
index 0000000..761a06e
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
@@ -0,0 +1,37 @@
+/*
+ * 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.api.entity;
+
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+
+public interface Implementation extends ProvidedKeyEntity {
+
+    ImplementationEngine getEngine();
+
+    void setEngine(ImplementationEngine engine);
+
+    ImplementationType getType();
+
+    void setType(ImplementationType type);
+
+    String getBody();
+
+    void setBody(String body);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
index 48ce512..e4fb71a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
@@ -133,7 +133,12 @@ public class LinkingMappingItem implements MappingItem {
     }
 
     @Override
-    public List<String> getTransformerClassNames() {
+    public boolean add(final Implementation transformer) {
+        return false;
+    }
+
+    @Override
+    public List<? extends Implementation> getTransformers() {
         return Collections.emptyList();
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
index 62d8221..1614a7e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
@@ -40,9 +40,9 @@ public interface Notification extends Entity {
 
     void setRecipientsFIQL(String recipientsFIQL);
 
-    String getRecipientsProviderClassName();
+    Implementation getRecipientsProvider();
 
-    void setRecipientsProviderClassName(String recipientsProviderClassName);
+    void setRecipientsProvider(Implementation recipientsProvider);
 
     boolean add(AnyAbout about);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainSchema.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainSchema.java
index 82ae012..97821e0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainSchema.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainSchema.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
 
 public interface PlainSchema extends Schema {
 
@@ -36,9 +35,7 @@ public interface PlainSchema extends Schema {
 
     String getSecretKey();
 
-    Validator getValidator();
-
-    String getValidatorClass();
+    Implementation getValidator();
 
     void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm);
 
@@ -52,7 +49,7 @@ public interface PlainSchema extends Schema {
 
     void setSecretKey(String secretKey);
 
-    void setValidatorClass(String validatorClass);
+    void setValidator(Implementation validator);
 
     void setType(AttrSchemaType type);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
index e345921..c4ef281 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.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.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -45,7 +44,9 @@ public interface Realm extends Entity {
 
     void setPasswordPolicy(PasswordPolicy passwordPolicy);
 
-    Set<String> getActionsClassNames();
+    boolean add(Implementation action);
+
+    List<? extends Implementation> getActions();
 
     boolean add(AnyTemplateRealm template);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
index 3e51233..a6cc50e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.List;
-import org.apache.syncope.common.lib.report.ReportletConf;
 
 public interface Report extends Entity {
 
@@ -31,11 +30,9 @@ public interface Report extends Entity {
 
     List<? extends ReportExec> getExecs();
 
-    boolean add(ReportletConf reportletConf);
+    boolean add(Implementation reportlet);
 
-    void removeAllReportletConfs();
-
-    List<? extends ReportletConf> getReportletConfs();
+    List<? extends Implementation> getReportlets();
 
     String getCronExpression();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
index bf810b3..3fe3c5e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity.policy;
 
 import java.util.List;
 import java.util.Set;
-import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
@@ -34,15 +34,11 @@ public interface AccountPolicy extends Policy {
 
     void setMaxAuthenticationAttempts(int maxAuthenticationAttempts);
 
-    boolean add(AccountRuleConf accountRuleConf);
+    boolean add(Implementation rule);
 
-    void removeAllRuleConfs();
-
-    List<AccountRuleConf> getRuleConfs();
+    List<? extends Implementation> getRules();
 
     boolean add(ExternalResource resource);
 
-    Set<String> getResourceKeys();
-
     Set<? extends ExternalResource> getResources();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
index a3e565f..e44eba0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
@@ -19,22 +19,20 @@
 package org.apache.syncope.core.persistence.api.entity.policy;
 
 import java.util.List;
-import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 
 public interface PasswordPolicy extends Policy {
 
     boolean isAllowNullPassword();
 
-    void setAllowNullPassword(final boolean allowNullPassword);
+    void setAllowNullPassword(boolean allowNullPassword);
 
     int getHistoryLength();
 
     void setHistoryLength(int historyLength);
 
-    boolean add(PasswordRuleConf passwordRuleConf);
+    boolean add(Implementation rule);
 
-    void removeAllRuleConfs();
-
-    List<PasswordRuleConf> getRuleConfs();
+    List<? extends Implementation> getRules();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
index 4b8ee40..4093bec 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
@@ -27,6 +27,7 @@ import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
@@ -76,7 +77,9 @@ public interface ExternalResource extends ProvidedKeyEntity {
 
     void setProvisioningTraceLevel(TraceLevel provisioningTraceLevel);
 
-    List<String> getPropagationActionsClassNames();
+    boolean add(Implementation propagationAction);
+
+    List<? extends Implementation> getPropagationActions();
 
     Integer getPropagationPriority();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
index e8bf037..b46cab5 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.api.entity.resource;
 import java.util.List;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public interface Item extends Entity {
 
@@ -56,5 +57,7 @@ public interface Item extends Entity {
 
     void setPullJEXLTransformer(String pullJEXLTransformer);
 
-    List<String> getTransformerClassNames();
+    boolean add(Implementation transformer);
+
+    List<? extends Implementation> getTransformers();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
index 296de84..971e8e5 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
@@ -18,9 +18,10 @@
  */
 package org.apache.syncope.core.persistence.api.entity.task;
 
-import java.util.Set;
+import java.util.List;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
 public interface ProvisioningTask extends SchedTask {
@@ -29,7 +30,9 @@ public interface ProvisioningTask extends SchedTask {
 
     void setResource(ExternalResource resource);
 
-    Set<String> getActionsClassNames();
+    boolean add(Implementation action);
+
+    List<? extends Implementation> getActions();
 
     MatchingRule getMatchingRule();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
index 0ce891b..d4234f2 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Optional;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 
 public interface PullTask extends ProvisioningTask {
@@ -30,9 +31,9 @@ public interface PullTask extends ProvisioningTask {
 
     void setPullMode(PullMode pullMode);
 
-    String getReconciliationFilterBuilderClassName();
+    Implementation getReconFilterBuilder();
 
-    void setReconciliationFilterBuilderClassName(String reconciliationFilterBuilderClassName);
+    void setReconFilterBuilder(Implementation reconFilterBuilder);
 
     Realm getDestinatioRealm();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
index c88c23d..abddc8b 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.api.entity.task;
 
 import java.util.Date;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public interface SchedTask extends Task {
 
@@ -30,9 +31,9 @@ public interface SchedTask extends Task {
 
     String getDescription();
 
-    void setJobDelegateClassName(String jobDelegateClassName);
+    void setJobDelegate(Implementation jobDelegate);
 
-    String getJobDelegateClassName();
+    Implementation getJobDelegate();
 
     Date getStartAt();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AbstractValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AbstractValidator.java
index af1c9b8..8c149db 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AbstractValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AbstractValidator.java
@@ -31,9 +31,10 @@ public abstract class AbstractValidator implements Validator, Serializable {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
 
-    protected final PlainSchema schema;
+    protected PlainSchema schema;
 
-    public AbstractValidator(final PlainSchema schema) {
+    @Override
+    public void setSchema(final PlainSchema schema) {
         this.schema = schema;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
index 1d93c5b..65d63ed 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
@@ -20,16 +20,11 @@ package org.apache.syncope.core.persistence.jpa.attrvalue.validation;
 
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 
 public class AlwaysTrueValidator extends AbstractValidator {
 
     private static final long serialVersionUID = 872107345555773183L;
 
-    public AlwaysTrueValidator(final PlainSchema schema) {
-        super(schema);
-    }
-
     @Override
     protected void doValidate(final PlainAttrValue attrValue) {
         Boolean value = attrValue.getValue();

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BasicValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BasicValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BasicValidator.java
index 4d99372..fc64f03 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BasicValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/BasicValidator.java
@@ -22,16 +22,11 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 
 public class BasicValidator extends AbstractValidator {
 
     private static final long serialVersionUID = -2606728447694223607L;
 
-    public BasicValidator(final PlainSchema schema) {
-        super(schema);
-    }
-
     @Override
     protected void doValidate(final PlainAttrValue attrValue) {
         if (AttrSchemaType.Enum == schema.getType()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/d5b57922/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/EmailAddressValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
index b16c0b7..1202373 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
@@ -22,16 +22,11 @@ import java.util.regex.Matcher;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 
 public class EmailAddressValidator extends AbstractValidator {
 
     private static final long serialVersionUID = 792457177290331518L;
 
-    public EmailAddressValidator(final PlainSchema schema) {
-        super(schema);
-    }
-
     @Override
     protected void doValidate(final PlainAttrValue attrValue) {
         Matcher matcher = SyncopeConstants.EMAIL_PATTERN.matcher(attrValue.<CharSequence>getValue());