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 2015/08/20 11:47:50 UTC

[10/12] syncope git commit: [SYNCOPE-685] Now account and password policies can be composed of several 'rules', where each rule can be provided as a separate Java class (similar to Reportlet mechanism); previous account and password policies are now impl

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SyncPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SyncPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SyncPolicy.java
deleted file mode 100644
index 1e389d7..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SyncPolicy.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.api.entity;
-
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
-
-public interface SyncPolicy extends Policy {
-
-    SyncPolicySpec getSpecification();
-
-    void setSpecification(SyncPolicySpec spec);
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/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 f9a8277..066efdf 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
@@ -36,7 +36,7 @@ public interface AccountPolicy extends Policy {
 
     boolean add(AccountRuleConf accountRuleConf);
 
-    boolean remove(AccountRuleConf accountRuleConf);
+    void removeAllRuleConfs();
 
     List<AccountRuleConf> getRuleConfs();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/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 173608e..a3e565f 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
@@ -34,7 +34,7 @@ public interface PasswordPolicy extends Policy {
 
     boolean add(PasswordRuleConf passwordRuleConf);
 
-    boolean remove(PasswordRuleConf passwordRuleConf);
+    void removeAllRuleConfs();
 
     List<PasswordRuleConf> getRuleConfs();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/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 63047a1..a8f32c0 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
@@ -23,12 +23,12 @@ import java.util.Set;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.PropagationMode;
 import org.apache.syncope.common.lib.types.TraceLevel;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.AnnotatedEntity;
 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.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 
 public interface ExternalResource extends AnnotatedEntity<String> {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
index 7ef2ebf..d4eaf63 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
@@ -36,25 +36,22 @@ public class DefaultAccountRule implements AccountRule {
 
     private DefaultAccountRuleConf conf;
 
+    @Transactional(readOnly = true)
     @Override
-    public void setConf(final AccountRuleConf conf) {
+    public void enforce(final AccountRuleConf conf, final User user) {
         if (conf instanceof DefaultAccountRuleConf) {
-            this.conf = (DefaultAccountRuleConf) conf;
+            this.conf = DefaultAccountRuleConf.class.cast(conf);
         } else {
             throw new IllegalArgumentException(
                     AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
         }
-    }
 
-    @Transactional(readOnly = true)
-    @Override
-    public void isCompliant(final User user) {
-        for (String schema : conf.getSchemasNotPermitted()) {
+        for (String schema : this.conf.getSchemasNotPermitted()) {
             PlainAttr<?> attr = user.getPlainAttr(schema);
             if (attr != null) {
                 List<String> values = attr.getValuesAsStrings();
                 if (values != null && !values.isEmpty()) {
-                    conf.getWordsNotPermitted().add(values.get(0));
+                    this.conf.getWordsNotPermitted().add(values.get(0));
                 }
             }
         }
@@ -64,45 +61,45 @@ public class DefaultAccountRule implements AccountRule {
         }
 
         // check min length
-        if (conf.getMinLength() > 0 && conf.getMinLength() > user.getUsername().length()) {
+        if (this.conf.getMinLength() > 0 && this.conf.getMinLength() > user.getUsername().length()) {
             throw new AccountPolicyException("Username too short");
         }
 
         // check max length
-        if (conf.getMaxLength() > 0 && conf.getMaxLength() < user.getUsername().length()) {
+        if (this.conf.getMaxLength() > 0 && this.conf.getMaxLength() < user.getUsername().length()) {
             throw new AccountPolicyException("Username too long");
         }
 
         // check words not permitted
-        for (String word : conf.getWordsNotPermitted()) {
+        for (String word : this.conf.getWordsNotPermitted()) {
             if (user.getUsername().contains(word)) {
                 throw new AccountPolicyException("Used word(s) not permitted");
             }
         }
 
         // check case
-        if (conf.isAllUpperCase() && !user.getUsername().equals(user.getUsername().toUpperCase())) {
+        if (this.conf.isAllUpperCase() && !user.getUsername().equals(user.getUsername().toUpperCase())) {
             throw new AccountPolicyException("No lowercase characters permitted");
         }
-        if (conf.isAllLowerCase() && !user.getUsername().equals(user.getUsername().toLowerCase())) {
+        if (this.conf.isAllLowerCase() && !user.getUsername().equals(user.getUsername().toLowerCase())) {
             throw new AccountPolicyException("No uppercase characters permitted");
         }
 
         // check pattern
-        Pattern pattern = (conf.getPattern() == null) ? DEFAULT_PATTERN : Pattern.compile(conf.getPattern());
+        Pattern pattern = (this.conf.getPattern() == null) ? DEFAULT_PATTERN : Pattern.compile(this.conf.getPattern());
         if (!pattern.matcher(user.getUsername()).matches()) {
             throw new AccountPolicyException("Username does not match pattern");
         }
 
         // check prefix
-        for (String prefix : conf.getPrefixesNotPermitted()) {
+        for (String prefix : this.conf.getPrefixesNotPermitted()) {
             if (user.getUsername().startsWith(prefix)) {
                 throw new AccountPolicyException("Prefix not permitted");
             }
         }
 
         // check suffix
-        for (String suffix : conf.getSuffixesNotPermitted()) {
+        for (String suffix : this.conf.getSuffixesNotPermitted()) {
             if (user.getUsername().endsWith(suffix)) {
                 throw new AccountPolicyException("Suffix not permitted");
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
index 8eaad0e..d3ab592 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
@@ -34,25 +34,22 @@ public class DefaultPasswordRule implements PasswordRule {
 
     private DefaultPasswordRuleConf conf;
 
+    @Transactional(readOnly = true)
     @Override
-    public void setConf(final PasswordRuleConf conf) {
+    public void enforce(final PasswordRuleConf conf, final User user) {
         if (conf instanceof DefaultPasswordRuleConf) {
             this.conf = (DefaultPasswordRuleConf) conf;
         } else {
             throw new IllegalArgumentException(
                     PasswordRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
         }
-    }
 
-    @Transactional(readOnly = true)
-    @Override
-    public void isCompliant(final User user) {
-        for (String schema : conf.getSchemasNotPermitted()) {
+        for (String schema : this.conf.getSchemasNotPermitted()) {
             PlainAttr<?> attr = user.getPlainAttr(schema);
             if (attr != null) {
                 List<String> values = attr.getValuesAsStrings();
                 if (values != null && !values.isEmpty()) {
-                    conf.getWordsNotPermitted().add(values.get(0));
+                    this.conf.getWordsNotPermitted().add(values.get(0));
                 }
             }
         }
@@ -62,113 +59,119 @@ public class DefaultPasswordRule implements PasswordRule {
 
         if (password != null && clearPassword != null) {
             // check length
-            if (conf.getMinLength() > 0 && conf.getMinLength() > clearPassword.length()) {
+            if (this.conf.getMinLength() > 0 && this.conf.getMinLength() > clearPassword.length()) {
                 throw new PasswordPolicyException("Password too short");
             }
 
-            if (conf.getMaxLength() > 0 && conf.getMaxLength() < clearPassword.length()) {
+            if (this.conf.getMaxLength() > 0 && this.conf.getMaxLength() < clearPassword.length()) {
                 throw new PasswordPolicyException("Password too long");
             }
 
             // check words not permitted
-            for (String word : conf.getWordsNotPermitted()) {
+            for (String word : this.conf.getWordsNotPermitted()) {
                 if (clearPassword.contains(word)) {
                     throw new PasswordPolicyException("Used word(s) not permitted");
                 }
             }
 
             // check digits occurrence
-            if (conf.isDigitRequired() && !checkDigit(clearPassword)) {
+            if (this.conf.isDigitRequired() && !checkDigit(clearPassword)) {
                 throw new PasswordPolicyException("Password must contain digit(s)");
             }
 
             // check lowercase alphabetic characters occurrence
-            if (conf.isLowercaseRequired() && !checkLowercase(clearPassword)) {
+            if (this.conf.isLowercaseRequired() && !checkLowercase(clearPassword)) {
                 throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
             }
 
             // check uppercase alphabetic characters occurrence
-            if (conf.isUppercaseRequired() && !checkUppercase(clearPassword)) {
+            if (this.conf.isUppercaseRequired() && !checkUppercase(clearPassword)) {
                 throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
             }
 
             // check prefix
-            for (String prefix : conf.getPrefixesNotPermitted()) {
+            for (String prefix : this.conf.getPrefixesNotPermitted()) {
                 if (clearPassword.startsWith(prefix)) {
                     throw new PasswordPolicyException("Prefix not permitted");
                 }
             }
 
             // check suffix
-            for (String suffix : conf.getSuffixesNotPermitted()) {
+            for (String suffix : this.conf.getSuffixesNotPermitted()) {
                 if (clearPassword.endsWith(suffix)) {
                     throw new PasswordPolicyException("Suffix not permitted");
                 }
             }
 
             // check digit first occurrence
-            if (conf.isMustStartWithDigit() && !checkFirstDigit(clearPassword)) {
+            if (this.conf.isMustStartWithDigit() && !checkFirstDigit(clearPassword)) {
                 throw new PasswordPolicyException("Password must start with a digit");
             }
 
-            if (conf.isMustntStartWithDigit() && checkFirstDigit(clearPassword)) {
+            if (this.conf.isMustntStartWithDigit() && checkFirstDigit(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't start with a digit");
             }
 
             // check digit last occurrence
-            if (conf.isMustEndWithDigit() && !checkLastDigit(clearPassword)) {
+            if (this.conf.isMustEndWithDigit() && !checkLastDigit(clearPassword)) {
                 throw new PasswordPolicyException("Password must end with a digit");
             }
 
-            if (conf.isMustntEndWithDigit() && checkLastDigit(clearPassword)) {
+            if (this.conf.isMustntEndWithDigit() && checkLastDigit(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't end with a digit");
             }
 
             // check alphanumeric characters occurence
-            if (conf.isAlphanumericRequired() && !checkAlphanumeric(clearPassword)) {
+            if (this.conf.isAlphanumericRequired() && !checkAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
             }
 
             // check non alphanumeric characters occurence
-            if (conf.isNonAlphanumericRequired() && !checkNonAlphanumeric(clearPassword)) {
+            if (this.conf.isNonAlphanumericRequired() && !checkNonAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
             }
 
             // check alphanumeric character first occurrence
-            if (conf.isMustStartWithAlpha() && !checkFirstAlphanumeric(clearPassword)) {
+            if (this.conf.isMustStartWithAlpha() && !checkFirstAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must start with an alphanumeric character");
             }
 
-            if (conf.isMustntStartWithAlpha() && checkFirstAlphanumeric(clearPassword)) {
+            if (this.conf.isMustntStartWithAlpha() && checkFirstAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't start with an alphanumeric character");
             }
 
             // check alphanumeric character last occurrence
-            if (conf.isMustEndWithAlpha() && !checkLastAlphanumeric(clearPassword)) {
+            if (this.conf.isMustEndWithAlpha() && !checkLastAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must end with an alphanumeric character");
             }
 
-            if (conf.isMustntEndWithAlpha() && checkLastAlphanumeric(clearPassword)) {
+            if (this.conf.isMustntEndWithAlpha() && checkLastAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't end with an alphanumeric character");
             }
 
             // check non alphanumeric character first occurrence
-            if (conf.isMustStartWithNonAlpha() && !checkFirstNonAlphanumeric(clearPassword)) {
+            if (this.conf.isMustStartWithNonAlpha() && !checkFirstNonAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
             }
 
-            if (conf.isMustntStartWithNonAlpha() && checkFirstNonAlphanumeric(clearPassword)) {
+            if (this.conf.isMustntStartWithNonAlpha() && checkFirstNonAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't start with a non-alphanumeric character");
             }
 
             // check non alphanumeric character last occurrence
-            if (conf.isMustEndWithNonAlpha() && !checkLastNonAlphanumeric(clearPassword)) {
+            if (this.conf.isMustEndWithNonAlpha() && !checkLastNonAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
             }
 
-            if (conf.isMustntEndWithNonAlpha() && checkLastNonAlphanumeric(clearPassword)) {
+            if (this.conf.isMustntEndWithNonAlpha() && checkLastNonAlphanumeric(clearPassword)) {
                 throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
             }
+
+            if (!this.conf.isUsernameAllowed()
+                    && user.getUsername() != null && user.getUsername().equals(clearPassword)) {
+
+                throw new PasswordPolicyException("Password mustn't be equal to username");
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
index 4a8a759..3905d92 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
@@ -32,7 +32,7 @@ import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.Policy;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
index ab0a8c5..4b89f8c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
@@ -24,13 +24,13 @@ import javax.persistence.TypedQuery;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.apache.syncope.core.persistence.jpa.entity.JPAPolicy;
-import org.apache.syncope.core.persistence.jpa.entity.JPAAccountPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.AbstractPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
@@ -44,7 +44,7 @@ public class JPAPolicyDAO extends AbstractDAO<Policy, Long> implements PolicyDAO
     @SuppressWarnings("unchecked")
     public <T extends Policy> T find(final Long key) {
         final Query query = entityManager().createQuery(
-                "SELECT e FROM " + JPAPolicy.class.getSimpleName() + " e WHERE e.id=:id");
+                "SELECT e FROM " + AbstractPolicy.class.getSimpleName() + " e WHERE e.id=:id");
         query.setParameter("id", key);
 
         List<T> result = query.getResultList();
@@ -57,7 +57,7 @@ public class JPAPolicyDAO extends AbstractDAO<Policy, Long> implements PolicyDAO
     @SuppressWarnings("unchecked")
     public <T extends Policy> List<T> find(final PolicyType type) {
         final Query query = entityManager().createQuery(
-                "SELECT e FROM " + JPAPolicy.class.getSimpleName() + " e WHERE e.type=:type");
+                "SELECT e FROM " + AbstractPolicy.class.getSimpleName() + " e WHERE e.type=:type");
         query.setParameter("type", type);
 
         return (List<T>) query.getResultList();
@@ -76,7 +76,7 @@ public class JPAPolicyDAO extends AbstractDAO<Policy, Long> implements PolicyDAO
     @Override
     public List<Policy> findAll() {
         TypedQuery<Policy> query = entityManager().createQuery(
-                "SELECT e FROM " + JPAPolicy.class.getSimpleName() + " e", Policy.class);
+                "SELECT e FROM " + AbstractPolicy.class.getSimpleName() + " e", Policy.class);
         return query.getResultList();
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
index 36ce550..eee37f1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
@@ -32,7 +32,7 @@ import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.dao.MalformedPathException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index a70f65e..b4b5342 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -33,7 +33,7 @@ import org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTask;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPAPushTask;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPASchedTask;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPASyncTask;
-import org.apache.syncope.core.persistence.jpa.entity.task.JPATask;
+import org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -75,7 +75,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO {
     @SuppressWarnings("unchecked")
     @Override
     public <T extends Task> T find(final Long key) {
-        return (T) entityManager().find(JPATask.class, key);
+        return (T) entityManager().find(AbstractTask.class, key);
     }
 
     private <T extends Task> StringBuilder buildfindAllQuery(final TaskType type) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 7dd3fe7..130c01e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -18,10 +18,13 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.Resource;
 import javax.persistence.NoResultException;
@@ -29,17 +32,16 @@ import javax.persistence.TypedQuery;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
+import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.Entitlement;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.core.misc.policy.AccountPolicyEnforcer;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.core.misc.policy.AccountPolicyException;
-import org.apache.syncope.core.misc.policy.PasswordPolicyEnforcer;
-import org.apache.syncope.core.misc.policy.PolicyEvaluator;
+import org.apache.syncope.core.misc.policy.PasswordPolicyException;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -49,13 +51,17 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
 import org.apache.syncope.core.misc.security.UnauthorizedException;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.core.persistence.api.dao.AccountRule;
+import org.apache.syncope.core.persistence.api.dao.AccountRuleConfClass;
+import org.apache.syncope.core.persistence.api.dao.PasswordRule;
+import org.apache.syncope.core.persistence.api.dao.PasswordRuleConfClass;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.Policy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -64,13 +70,55 @@ import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AssignableTypeFilter;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ClassUtils;
 
 @Repository
 public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
 
+    private static final Map<Class<? extends AccountRuleConf>, Class<AccountRule>> ACCOUNT_RULES_CLASSES =
+            new HashMap<>();
+
+    private static final Map<Class<? extends PasswordRuleConf>, Class<PasswordRule>> PASSWORD_RULES_CLASSES =
+            new HashMap<>();
+
+    static {
+        initRules();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void initRules() {
+        ClassPathScanningCandidateComponentProvider scanner =
+                new ClassPathScanningCandidateComponentProvider(false);
+        scanner.addIncludeFilter(new AssignableTypeFilter(AccountRule.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRule.class));
+
+        for (BeanDefinition bd : scanner.findCandidateComponents(StringUtils.EMPTY)) {
+            Class<?> clazz = ClassUtils.resolveClassName(
+                    bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
+            boolean isAbstract = Modifier.isAbstract(clazz.getModifiers());
+
+            if (AccountRule.class.isAssignableFrom(clazz) && !isAbstract) {
+                AccountRuleConfClass annotation = clazz.getAnnotation(AccountRuleConfClass.class);
+                if (annotation != null) {
+                    ACCOUNT_RULES_CLASSES.put(annotation.value(), (Class<AccountRule>) clazz);
+                }
+            }
+            if (PasswordRule.class.isAssignableFrom(clazz) && !isAbstract) {
+                PasswordRuleConfClass annotation = clazz.getAnnotation(PasswordRuleConfClass.class);
+                if (annotation != null) {
+                    PASSWORD_RULES_CLASSES.put(annotation.value(), (Class<PasswordRule>) clazz);
+                }
+            }
+        }
+    }
+
     @Autowired
     private RealmDAO realmDAO;
 
@@ -86,15 +134,6 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
     @Resource(name = "anonymousUser")
     private String anonymousUser;
 
-    @Autowired
-    private PolicyEvaluator evaluator;
-
-    @Autowired
-    private PasswordPolicyEnforcer ppEnforcer;
-
-    @Autowired
-    private AccountPolicyEnforcer apEnforcer;
-
     @Override
     protected AnyUtils init() {
         return new JPAAnyUtilsFactory().getInstance(AnyTypeKind.USER);
@@ -235,14 +274,39 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
 
         try {
             int maxPPSpecHistory = 0;
-            for (Policy policy : getPasswordPolicies(user)) {
-                // evaluate policy
-                PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user);
-                // enforce policy
-                ppEnforcer.enforce(ppSpec, user);
-
-                if (ppSpec.getHistoryLength() > maxPPSpecHistory) {
-                    maxPPSpecHistory = ppSpec.getHistoryLength();
+            for (PasswordPolicy policy : getPasswordPolicies(user)) {
+                if (user.getPassword() == null && !policy.isAllowNullPassword()) {
+                    throw new PasswordPolicyException("Password mandatory");
+                }
+
+                for (PasswordRuleConf ruleConf : policy.getRuleConfs()) {
+                    Class<PasswordRule> ruleClass = PASSWORD_RULES_CLASSES.get(ruleConf.getClass());
+                    if (ruleClass == null) {
+                        LOG.warn("Could not find matching password rule for {}", ruleConf.getClass());
+                    } else {
+                        // fetch (or create) rule
+                        PasswordRule rule;
+                        if (ApplicationContextProvider.getBeanFactory().containsSingleton(ruleClass.getName())) {
+                            rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().
+                                    getSingleton(ruleClass.getName());
+                        } else {
+                            rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        }
+
+                        // enforce rule
+                        rule.enforce(ruleConf, user);
+                    }
+                }
+
+                if (user.verifyPasswordHistory(user.getClearPassword(), policy.getHistoryLength())) {
+                    throw new PasswordPolicyException("Password value was used in the past: not allowed");
+                }
+
+                if (policy.getHistoryLength() > maxPPSpecHistory) {
+                    maxPPSpecHistory = policy.getHistoryLength();
                 }
             }
 
@@ -276,14 +340,32 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
                 throw new AccountPolicyException("Not allowed: " + user.getUsername());
             }
 
-            // invalid username
-            for (Policy policy : getAccountPolicies(user)) {
-                // evaluate policy
-                AccountPolicySpec apSpec = evaluator.evaluate(policy, user);
+            for (AccountPolicy policy : getAccountPolicies(user)) {
+                for (AccountRuleConf ruleConf : policy.getRuleConfs()) {
+                    Class<AccountRule> ruleClass = ACCOUNT_RULES_CLASSES.get(ruleConf.getClass());
+                    if (ruleClass == null) {
+                        LOG.warn("Could not find matching password rule for {}", ruleConf.getClass());
+                    } else {
+                        // fetch (or create) rule
+                        AccountRule rule;
+                        if (ApplicationContextProvider.getBeanFactory().containsSingleton(ruleClass.getName())) {
+                            rule = (AccountRule) ApplicationContextProvider.getBeanFactory().
+                                    getSingleton(ruleClass.getName());
+                        } else {
+                            rule = (AccountRule) ApplicationContextProvider.getBeanFactory().
+                                    createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                            ApplicationContextProvider.getBeanFactory().
+                                    registerSingleton(ruleClass.getName(), rule);
+                        }
+
+                        // enforce rule
+                        rule.enforce(ruleConf, user);
+                    }
+                }
 
-                // enforce policy
-                suspend |= apEnforcer.enforce(apSpec, user);
-                propagateSuspension |= apSpec.isPropagateSuspension();
+                suspend |= user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0
+                        && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended();
+                propagateSuspension |= policy.isPropagateSuspension();
             }
         } catch (Exception e) {
             LOG.error("Invalid username for {}", user, e);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccountPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccountPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccountPolicy.java
deleted file mode 100644
index 844b49a..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccountPolicy.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.persistence.DiscriminatorValue;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
-
-@Entity
-@DiscriminatorValue("AccountPolicy")
-public class JPAAccountPolicy extends JPAPolicy implements AccountPolicy {
-
-    private static final long serialVersionUID = -2767606675667839060L;
-
-    /**
-     * Resources for alternative user authentication: if empty, only internal storage will be used.
-     */
-    @ManyToMany(fetch = FetchType.EAGER)
-    @JoinTable(joinColumns =
-            @JoinColumn(name = "accountPolicy_id"),
-            inverseJoinColumns =
-            @JoinColumn(name = "resource_name"))
-    private Set<JPAExternalResource> resources = new HashSet<>();
-
-    public JPAAccountPolicy() {
-        super();
-        this.type = PolicyType.ACCOUNT;
-    }
-
-    @Override
-    public AccountPolicySpec getSpecification() {
-        return POJOHelper.deserialize(specification, AccountPolicySpec.class);
-    }
-
-    @Override
-    public void setSpecification(final AccountPolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
-    }
-
-    @Override
-    public boolean add(final ExternalResource resource) {
-        checkType(resource, JPAExternalResource.class);
-        return resources.add((JPAExternalResource) resource);
-    }
-
-    @Override
-    public boolean remove(final ExternalResource resource) {
-        checkType(resource, JPAExternalResource.class);
-        return resources.remove((JPAExternalResource) resource);
-    }
-
-    @Override
-    public Set<? extends ExternalResource> getResources() {
-        return resources;
-    }
-
-    @Override
-    public Set<String> getResourceNames() {
-        return CollectionUtils.collect(getResources(), new Transformer<ExternalResource, String>() {
-
-            @Override
-            public String transform(final ExternalResource input) {
-                return input.getKey();
-            }
-        }, new HashSet<String>());
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 41d3f74..586f6cd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -18,9 +18,13 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPASyncPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPushPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
@@ -34,16 +38,15 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.persistence.api.entity.Notification;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-import org.apache.syncope.core.persistence.api.entity.PushPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
-import org.apache.syncope.core.persistence.api.entity.ReportletConfInstance;
 import org.apache.syncope.core.persistence.api.entity.Role;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
@@ -222,8 +225,6 @@ public class JPAEntityFactory implements EntityFactory {
             result = (T) new JPAReport();
         } else if (reference.equals(ReportExec.class)) {
             result = (T) new JPAReportExec();
-        } else if (reference.equals(ReportletConfInstance.class)) {
-            result = (T) new JPAReportletConfInstance();
         } else if (reference.equals(NotificationTask.class)) {
             result = (T) new JPANotificationTask();
         } else if (reference.equals(PropagationTask.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPasswordPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPasswordPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPasswordPolicy.java
deleted file mode 100644
index 8a755f4..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPasswordPolicy.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import javax.persistence.DiscriminatorValue;
-import javax.persistence.Entity;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
-
-@Entity
-@DiscriminatorValue("PasswordPolicy")
-public class JPAPasswordPolicy extends JPAPolicy implements PasswordPolicy {
-
-    private static final long serialVersionUID = 9138550910385232849L;
-
-    public JPAPasswordPolicy() {
-        super();
-        this.type = PolicyType.PASSWORD;
-    }
-
-    @Override
-    public PasswordPolicySpec getSpecification() {
-        return POJOHelper.deserialize(specification, PasswordPolicySpec.class);
-    }
-
-    @Override
-    public void setSpecification(final PasswordPolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPolicy.java
deleted file mode 100644
index 1dc5de6..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPolicy.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import javax.persistence.DiscriminatorColumn;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.Id;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
-import javax.persistence.Lob;
-import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.core.persistence.api.entity.Policy;
-
-@Entity
-@Table(name = JPAPolicy.TABLE)
-@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-@DiscriminatorColumn(name = "DTYPE")
-public abstract class JPAPolicy extends AbstractEntity<Long> implements Policy {
-
-    private static final long serialVersionUID = -5844833125843247458L;
-
-    public static final String TABLE = "Policy";
-
-    @Id
-    private Long id;
-
-    @NotNull
-    private String description;
-
-    @NotNull
-    @Enumerated(EnumType.STRING)
-    protected PolicyType type;
-
-    @Lob
-    protected String specification;
-
-    @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public void setDescription(final String description) {
-        this.description = description;
-    }
-
-    @Override
-    public PolicyType getType() {
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPushPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPushPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPushPolicy.java
deleted file mode 100644
index c3440b2..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPushPolicy.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import javax.persistence.Entity;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.common.lib.types.PushPolicySpec;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.entity.PushPolicy;
-
-@Entity
-public class JPAPushPolicy extends JPAPolicy implements PushPolicy {
-
-    private static final long serialVersionUID = -5875589156893921113L;
-
-    public JPAPushPolicy() {
-        super();
-        this.type = PolicyType.PUSH;
-    }
-
-    @Override
-    public PushPolicySpec getSpecification() {
-        return POJOHelper.deserialize(specification, PushPolicySpec.class);
-    }
-
-    @Override
-    public void setSpecification(final PushPolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
index a813535..d458178 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
 import javax.persistence.Cacheable;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -28,8 +30,8 @@ import javax.persistence.UniqueConstraint;
 import javax.validation.constraints.Size;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
+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.Realm;
 import org.apache.syncope.core.persistence.jpa.validation.entity.RealmCheck;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
index 15c33ea..eeaf86d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
@@ -28,12 +28,10 @@ import javax.persistence.Id;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
-import org.apache.syncope.core.persistence.api.entity.ReportletConfInstance;
 import org.apache.syncope.core.persistence.jpa.validation.entity.ReportCheck;
 
 @Entity
@@ -52,19 +50,12 @@ public class JPAReport extends AbstractEntity<Long> implements Report {
     private String name;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "report")
-    private List<JPAReportletConfInstance> reportletConfs;
+    private List<JPAReportletConfInstance> reportletConfs = new ArrayList<>();
 
     private String cronExpression;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "report")
-    private List<JPAReportExec> executions;
-
-    public JPAReport() {
-        super();
-
-        reportletConfs = new ArrayList<>();
-        executions = new ArrayList<>();
-    }
+    private List<JPAReportExec> executions = new ArrayList<>();
 
     @Override
     public Long getKey() {
@@ -112,22 +103,16 @@ public class JPAReport extends AbstractEntity<Long> implements Report {
     }
 
     @Override
-    public boolean remove(final ReportletConf reportletConf) {
-        return CollectionUtils.filter(reportletConfs, new Predicate<JPAReportletConfInstance>() {
-
-            @Override
-            public boolean evaluate(final JPAReportletConfInstance object) {
-                return reportletConf.equals(object.getInstance());
-            }
-        });
+    public void removeAllReportletConfs() {
+        reportletConfs.clear();
     }
 
     @Override
     public List<ReportletConf> getReportletConfs() {
-        return CollectionUtils.collect(reportletConfs, new Transformer<ReportletConfInstance, ReportletConf>() {
+        return CollectionUtils.collect(reportletConfs, new Transformer<JPAReportletConfInstance, ReportletConf>() {
 
             @Override
-            public ReportletConf transform(final ReportletConfInstance input) {
+            public ReportletConf transform(final JPAReportletConfInstance input) {
                 return input.getInstance();
             }
         }, new ArrayList<ReportletConf>());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReportletConfInstance.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReportletConfInstance.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReportletConfInstance.java
index c7edcdc..df08af8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReportletConfInstance.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReportletConfInstance.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import org.apache.syncope.core.persistence.api.entity.ReportletConfInstance;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Lob;
@@ -30,7 +29,7 @@ import org.apache.syncope.core.misc.serialization.POJOHelper;
 
 @Entity
 @Table(name = JPAReportletConfInstance.TABLE)
-public class JPAReportletConfInstance extends AbstractEntity<Long> implements ReportletConfInstance {
+public class JPAReportletConfInstance extends AbstractEntity<Long> {
 
     private static final long serialVersionUID = -2436055132955674610L;
 
@@ -50,25 +49,21 @@ public class JPAReportletConfInstance extends AbstractEntity<Long> implements Re
         return id;
     }
 
-    @Override
     public Report getReport() {
         return report;
     }
 
-    @Override
     public void setReport(final Report report) {
         checkType(report, JPAReport.class);
         this.report = (JPAReport) report;
     }
 
-    @Override
     public ReportletConf getInstance() {
         return serializedInstance == null
                 ? null
                 : POJOHelper.deserialize(serializedInstance, ReportletConf.class);
     }
 
-    @Override
     public void setInstance(final ReportletConf instance) {
         this.serializedInstance = instance == null
                 ? null

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASyncPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASyncPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASyncPolicy.java
deleted file mode 100644
index e244223..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASyncPolicy.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import javax.persistence.DiscriminatorValue;
-import javax.persistence.Entity;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
-
-@Entity
-@DiscriminatorValue("SyncPolicy")
-public class JPASyncPolicy extends JPAPolicy implements SyncPolicy {
-
-    private static final long serialVersionUID = -6090413855809521279L;
-
-    public JPASyncPolicy() {
-        super();
-        this.type = PolicyType.SYNC;
-    }
-
-    @Override
-    public SyncPolicySpec getSpecification() {
-        return POJOHelper.deserialize(specification, SyncPolicySpec.class);
-    }
-
-    @Override
-    public void setSpecification(final SyncPolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
index 87aa04f..e9b38c3 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
@@ -34,7 +34,6 @@ import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.types.PolicyType;
@@ -58,7 +57,7 @@ public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
     private int maxAuthenticationAttempts;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "accountPolicy")
-    private List<JPAAccountRuleConfInstance> ruleConfs;
+    private List<JPAAccountRuleConfInstance> ruleConfs = new ArrayList<>();
 
     /**
      * Resources for alternative user authentication: if empty, only internal storage will be used.
@@ -109,14 +108,8 @@ public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
     }
 
     @Override
-    public boolean remove(final AccountRuleConf accountRuleConf) {
-        return CollectionUtils.filter(ruleConfs, new Predicate<JPAAccountRuleConfInstance>() {
-
-            @Override
-            public boolean evaluate(final JPAAccountRuleConfInstance object) {
-                return accountRuleConf.equals(object.getInstance());
-            }
-        });
+    public void removeAllRuleConfs() {
+        ruleConfs.clear();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
index 1491c25..b6013fd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
@@ -29,7 +29,6 @@ import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.types.PolicyType;
@@ -51,7 +50,7 @@ public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy
     private int historyLength;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "passwordPolicy")
-    private List<JPAPasswordRuleConfInstance> ruleConfs;
+    private List<JPAPasswordRuleConfInstance> ruleConfs = new ArrayList<>();
 
     public JPAPasswordPolicy() {
         super();
@@ -92,14 +91,8 @@ public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy
     }
 
     @Override
-    public boolean remove(final PasswordRuleConf passwordRuleConf) {
-        return CollectionUtils.filter(ruleConfs, new Predicate<JPAPasswordRuleConfInstance>() {
-
-            @Override
-            public boolean evaluate(final JPAPasswordRuleConfInstance object) {
-                return passwordRuleConf.equals(object.getInstance());
-            }
-        });
+    public void removeAllRuleConfs() {
+        ruleConfs.clear();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
index b4f7f67..650ef6a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
@@ -46,20 +46,20 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.PropagationMode;
 import org.apache.syncope.common.lib.types.TraceLevel;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
 import org.apache.syncope.core.persistence.jpa.validation.entity.ExternalResourceCheck;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractAnnotatedEntity;
-import org.apache.syncope.core.persistence.jpa.entity.JPAAccountPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.JPAConnInstance;
-import org.apache.syncope.core.persistence.jpa.entity.JPAPasswordPolicy;
-import org.apache.syncope.core.persistence.jpa.entity.JPASyncPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPASyncPolicy;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 
 /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
index 36c52a3..938502d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
@@ -47,9 +47,6 @@ public abstract class AbstractTask extends AbstractEntity<Long> implements Task
 
     public static final String TABLE = "Task";
 
-    /**
-     * Id.
-     */
     @Id
     private Long id;
 
@@ -58,13 +55,7 @@ public abstract class AbstractTask extends AbstractEntity<Long> implements Task
     protected TaskType type;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "task")
-    private List<JPATaskExec> executions;
-
-    public AbstractTask() {
-        super();
-
-        executions = new ArrayList<>();
-    }
+    private List<JPATaskExec> executions = new ArrayList<>();
 
     @Override
     public Long getKey() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPANotificationTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPANotificationTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPANotificationTask.java
index be72e1e..f483a19 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPANotificationTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPANotificationTask.java
@@ -41,7 +41,7 @@ import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 
 @Entity
 @DiscriminatorValue("NotificationTask")
-public class JPANotificationTask extends JPATask implements NotificationTask {
+public class JPANotificationTask extends AbstractTask implements NotificationTask {
 
     private static final long serialVersionUID = 95731573485279180L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
index cffc4bf..e4d969d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
@@ -45,7 +45,7 @@ import org.identityconnectors.framework.common.objects.Attribute;
 @Entity
 @DiscriminatorValue("PropagationTask")
 @PropagationTaskCheck
-public class JPAPropagationTask extends JPATask implements PropagationTask {
+public class JPAPropagationTask extends AbstractTask implements PropagationTask {
 
     private static final long serialVersionUID = 7086054884614511210L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
index 4f650ba..d3c0c11 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
@@ -28,7 +28,7 @@ import org.apache.syncope.core.persistence.jpa.validation.entity.SchedTaskCheck;
 @Entity
 @DiscriminatorValue("SchedTask")
 @SchedTaskCheck
-public class JPASchedTask extends JPATask implements SchedTask {
+public class JPASchedTask extends AbstractTask implements SchedTask {
 
     private static final long serialVersionUID = 7596236684832602180L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATask.java
deleted file mode 100644
index f3c6069..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATask.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity.task;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.persistence.CascadeType;
-import javax.persistence.DiscriminatorColumn;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.Id;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.syncope.core.persistence.api.entity.task.Task;
-import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
-
-@Entity
-@Table(name = JPATask.TABLE)
-@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-@DiscriminatorColumn(name = "DTYPE")
-public abstract class JPATask extends AbstractEntity<Long> implements Task {
-
-    private static final long serialVersionUID = 5837401178128177511L;
-
-    public static final String TABLE = "Task";
-
-    /**
-     * Id.
-     */
-    @Id
-    private Long id;
-
-    @NotNull
-    @Enumerated(EnumType.STRING)
-    protected TaskType type;
-
-    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "task")
-    private List<JPATaskExec> executions;
-
-    public JPATask() {
-        super();
-
-        executions = new ArrayList<>();
-    }
-
-    @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
-    public TaskType getType() {
-        return type;
-    }
-
-    @Override
-    public boolean addExec(final TaskExec exec) {
-        checkType(exec, JPATaskExec.class);
-        return exec != null && !executions.contains((JPATaskExec) exec) && executions.add((JPATaskExec) exec);
-    }
-
-    @Override
-    public boolean removeExec(final TaskExec exec) {
-        checkType(exec, JPATaskExec.class);
-        return exec != null && executions.remove((JPATaskExec) exec);
-    }
-
-    @Override
-    public List<? extends TaskExec> getExecs() {
-        return executions;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATaskExec.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATaskExec.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATaskExec.java
index 7a37dc8..6ea4fb5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATaskExec.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPATaskExec.java
@@ -29,7 +29,7 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractExec;
 /**
  * An execution (with result) of a Task.
  *
- * @see JPATask
+ * @see AbstractTask
  */
 @Entity
 @Table(name = JPATaskExec.TABLE)
@@ -39,9 +39,6 @@ public class JPATaskExec extends AbstractExec implements TaskExec {
 
     public static final String TABLE = "TaskExec";
 
-    /**
-     * Id.
-     */
     @Id
     private Long id;
 
@@ -49,7 +46,7 @@ public class JPATaskExec extends AbstractExec implements TaskExec {
      * The referred task.
      */
     @ManyToOne(optional = false)
-    private JPATask task;
+    private AbstractTask task;
 
     @Override
     public Long getKey() {
@@ -63,8 +60,8 @@ public class JPATaskExec extends AbstractExec implements TaskExec {
 
     @Override
     public void setTask(final Task task) {
-        checkType(task, JPATask.class);
-        this.task = (JPATask) task;
+        checkType(task, AbstractTask.class);
+        this.task = (AbstractTask) task;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
index a75e4b6..7e08ced 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
@@ -380,7 +380,7 @@ under the License.
     </attributes>
   </entity>
 
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPATask">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Task" strategy="TABLE"/>
@@ -397,7 +397,7 @@ under the License.
     </attributes>
   </entity>
     
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAPolicy">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.AbstractPolicy">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Policy" strategy="TABLE"/>
@@ -405,7 +405,23 @@ under the License.
       </id>
     </attributes>
   </entity>
-
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AccountRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_AccountRuleConfInstance" pk-column-value="SEQ_AccountRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_PasswordRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_PasswordRuleConfInstance" pk-column-value="SEQ_PasswordRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAReport">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
index a75e4b6..7e08ced 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
@@ -380,7 +380,7 @@ under the License.
     </attributes>
   </entity>
 
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPATask">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Task" strategy="TABLE"/>
@@ -397,7 +397,7 @@ under the License.
     </attributes>
   </entity>
     
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAPolicy">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.AbstractPolicy">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Policy" strategy="TABLE"/>
@@ -405,7 +405,23 @@ under the License.
       </id>
     </attributes>
   </entity>
-
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AccountRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_AccountRuleConfInstance" pk-column-value="SEQ_AccountRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_PasswordRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_PasswordRuleConfInstance" pk-column-value="SEQ_PasswordRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAReport">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
index 6f83543..7be0d48 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
@@ -428,7 +428,7 @@ under the License.
     </attributes>
   </entity>
 
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPATask">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Task" strategy="TABLE"/>
@@ -445,7 +445,7 @@ under the License.
     </attributes>
   </entity>
     
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAPolicy">
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.AbstractPolicy">
     <attributes>
       <id name="id">
         <generated-value generator="SEQ_Policy" strategy="TABLE"/>
@@ -453,7 +453,23 @@ under the License.
       </id>
     </attributes>
   </entity>
-
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AccountRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_AccountRuleConfInstance" pk-column-value="SEQ_AccountRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordRuleConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_PasswordRuleConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_PasswordRuleConfInstance" pk-column-value="SEQ_PasswordRuleConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+    
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAReport">
     <attributes>
       <id name="id">