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:49 UTC

[09/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-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
index 780d192..fc8305b 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
@@ -27,15 +27,15 @@ import static org.junit.Assert.assertTrue;
 import java.util.List;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
+import org.apache.syncope.common.lib.policy.SyncPolicySpec;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
-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.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -108,20 +108,21 @@ public class PolicyTest extends AbstractTest {
 
     @Test
     public void update() {
-        PasswordPolicySpec specification = new PasswordPolicySpec();
-        specification.setMaxLength(8);
-        specification.setMinLength(6);
+        DefaultPasswordRuleConf ruleConf = new DefaultPasswordRuleConf();
+        ruleConf.setMaxLength(8);
+        ruleConf.setMinLength(6);
 
         PasswordPolicy policy = policyDAO.find(2L);
         assertNotNull(policy);
-        policy.setSpecification(specification);
+        assertEquals(1, policy.getRuleConfs().size());
+        policy.add(ruleConf);
 
         policy = policyDAO.save(policy);
 
         assertNotNull(policy);
         assertEquals(PolicyType.PASSWORD, policy.getType());
-        assertEquals(policy.getSpecification().getMaxLength(), 8);
-        assertEquals(policy.getSpecification().getMinLength(), 6);
+        assertEquals(((DefaultPasswordRuleConf) policy.getRuleConfs().get(1)).getMaxLength(), 8);
+        assertEquals(((DefaultPasswordRuleConf) policy.getRuleConfs().get(1)).getMinLength(), 6);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RealmTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RealmTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RealmTest.java
index 4eb611a..0fa7c35 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RealmTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RealmTest.java
@@ -33,8 +33,8 @@ import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntit
 import org.apache.syncope.core.persistence.api.dao.MalformedPathException;
 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.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.AbstractTest;
 import org.junit.Test;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
index 7c62ab2..e1d12b1 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
@@ -32,7 +32,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
+import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.misc.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.junit.Test;
@@ -214,7 +214,7 @@ public class UserTest extends AbstractTest {
         String password = "";
         try {
             password = passwordGenerator.generate(user);
-        } catch (InvalidPasswordPolicySpecException ex) {
+        } catch (InvalidPasswordRuleConf ex) {
             fail(ex.getMessage());
         }
         assertNotNull(password);
@@ -233,7 +233,7 @@ public class UserTest extends AbstractTest {
         try {
             password = passwordGenerator.generate(user);
 
-        } catch (InvalidPasswordPolicySpecException ex) {
+        } catch (InvalidPasswordRuleConf ex) {
             fail(ex.getMessage());
         }
         assertNotNull(password);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
index 967b719..1cd5e47 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
@@ -39,7 +39,7 @@ 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.ConnInstance;
 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.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 5977c9a..6f912b6 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -36,7 +36,7 @@ under the License.
   <PlainSchema name="notificationjob.cronExpression" type="String"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="2" owner_id="1" schema_name="notificationjob.cronExpression"/>
-  <CPlainAttrValue id="2" attribute_id="2" stringValue="0/5 * * * * ?"/>
+  <CPlainAttrValue id="2" attribute_id="2" stringValue="0/20 * * * * ?"/>
   
   <PlainSchema name="notification.maxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
@@ -100,24 +100,34 @@ under the License.
                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
   
   <!-- sample policies -->
-  <Policy DTYPE="SyncPolicy" id="1" description="a sync policy" type="SYNC" 
-          specification='{"conflictResolutionAction":"IGNORE"'/>
-  <Policy DTYPE="PasswordPolicy" id="2" description="a password policy" type="PASSWORD" 
-          specification='{"historyLength":1,"maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":true}'/>
-  <Policy DTYPE="SyncPolicy" id="3" description="sync policy 2" type="SYNC" 
-          specification='{"conflictResolutionAction":"ALL","correlationRules":{"USER":"[\"username\",\"firstname\"]"}}'/>
-  <Policy DTYPE="PasswordPolicy" id="4" description="sample password policy" type="PASSWORD" 
-          specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[], "allowNullPassword":true}'/>
-  <Policy DTYPE="AccountPolicy" id="5" description="an account policy" type="ACCOUNT" 
-          specification='{"maxLength":0,"minLength":0,"pattern":null,"allUpperCase":false,"allLowerCase":false,"propagateSuspension":false,"maxAuthenticationAttempts":0,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":[],"suffixesNotPermitted":[]}'/>
-  <Policy DTYPE="AccountPolicy" id="6" description="sample account policy" type="ACCOUNT" 
-          specification='{"maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"propagateSuspension":false,"maxAuthenticationAttempts":3,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
-  <Policy DTYPE="SyncPolicy" id="7" description="sync policy 1" type="SYNC" 
-          specification='{"conflictResolutionAction":"IGNORE"}'/>
-  <Policy DTYPE="PasswordPolicy" id="8" description="sample password policy" type="PASSWORD" 
-          specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":false}'/>
-  <Policy DTYPE="SyncPolicy" id="9" description="sync policy for java rule" type="SYNC" 
-          specification='{"conflictResolutionAction":"IGNORE"}'/>
+  <SyncPolicy id="1" description="a sync policy" type="SYNC" 
+              specification='{"conflictResolutionAction":"IGNORE"'/>
+  <PasswordPolicy id="2" description="a password policy" type="PASSWORD" 
+                  historyLength="1" allowNullPassword="1"/> 
+  <PasswordRuleConfInstance id="2" passwordPolicy_id="2"
+                            serializedInstance='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <SyncPolicy id="3" description="sync policy 2" type="SYNC" 
+              specification='{"conflictResolutionAction":"ALL","correlationRules":{"USER":"[\"username\",\"firstname\"]"}}'/>
+  <PasswordPolicy id="4" description="sample password policy" type="PASSWORD"
+                  historyLength="0"  allowNullPassword="1"/> 
+  <PasswordRuleConfInstance id="4" passwordPolicy_id="4"
+                            serializedInstance='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <AccountPolicy id="5" description="an account policy" type="ACCOUNT"
+                 propagateSuspension="0" maxAuthenticationAttempts="0"/>
+  <AccountRuleConfInstance id="5" accountPolicy_id="5"
+                           serializedInstance='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccountRuleConf","maxLength":0,"minLength":0,"pattern":null,"allUpperCase":false,"allLowerCase":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":[],"suffixesNotPermitted":[]}'/>
+  <AccountPolicy id="6" description="sample account policy" type="ACCOUNT"
+                 propagateSuspension="0" maxAuthenticationAttempts="3"/>
+  <AccountRuleConfInstance id="6" accountPolicy_id="6"
+                           serializedInstance='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccountRuleConf","maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <SyncPolicy id="7" description="sync policy 1" type="SYNC" 
+              specification='{"conflictResolutionAction":"IGNORE"}'/>
+  <PasswordPolicy id="8" description="sample password policy" type="PASSWORD"
+                  historyLength="0" allowNullPassword="0"/> 
+  <PasswordRuleConfInstance id="8" passwordPolicy_id="8"
+                            serializedInstance='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <SyncPolicy id="9" description="sync policy for java rule" type="SYNC" 
+              specification='{"conflictResolutionAction":"IGNORE"}'/>
 
   <RelationshipType name="inclusion" description="Models the act that an object is included in another"/>
   <RelationshipType name="neighborhood"/>
@@ -698,7 +708,7 @@ under the License.
                     creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
 
   <!-- Use resource-testdb for passthrough authentication (SYNCOPE-164) -->
-  <Policy_ExternalResource accountPolicy_id="5" resource_name="resource-testdb"/>
+  <AccountPolicy_ExternalResource accountPolicy_id="5" resource_name="resource-testdb"/>
     
   <SyncopeUser_ExternalResource user_id="1" resource_name="resource-testdb2"/>
   <SyncopeUser_ExternalResource user_id="3" resource_name="ws-target-resource-delete"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-jpa/src/test/resources/persistenceTest.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/persistenceTest.xml b/core/persistence-jpa/src/test/resources/persistenceTest.xml
index da8f321..2874cac 100644
--- a/core/persistence-jpa/src/test/resources/persistenceTest.xml
+++ b/core/persistence-jpa/src/test/resources/persistenceTest.xml
@@ -49,6 +49,8 @@ under the License.
   <context:component-scan base-package="org.apache.syncope.core.misc.policy"/>
   <context:component-scan base-package="org.apache.syncope.core.misc.security"/>
 
+  <bean class="org.apache.syncope.core.misc.security.DefaultPasswordGenerator"/>
+
   <import resource="persistenceContext.xml"/>
 
 </beans>

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PolicyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PolicyDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PolicyDataBinder.java
index f225b28..aa144f0 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PolicyDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PolicyDataBinder.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api.data;
 
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 
 public interface PolicyDataBinder {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
index 7180b6c..f2074f8 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
@@ -20,20 +20,24 @@ package org.apache.syncope.core.provisioning.java.data;
 
 import org.apache.syncope.core.provisioning.api.data.PolicyDataBinder;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
-import org.apache.syncope.common.lib.to.AccountPolicyTO;
-import org.apache.syncope.common.lib.to.PasswordPolicyTO;
-import org.apache.syncope.common.lib.to.SyncPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractAccountRuleConf;
+import org.apache.syncope.common.lib.policy.AbstractPasswordRuleConf;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.common.lib.policy.SyncPolicyTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 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.EntityFactory;
 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.api.entity.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,14 +63,33 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
         T policyTO;
         switch (policy.getType()) {
             case PASSWORD:
-                policyTO = (T) new PasswordPolicyTO();
-                ((PasswordPolicyTO) policyTO).setSpecification(((PasswordPolicy) policy).getSpecification());
+                PasswordPolicy passwordPolicy = PasswordPolicy.class.cast(policy);
+                PasswordPolicyTO passwordPolicyTO = new PasswordPolicyTO();
+                policyTO = (T) passwordPolicyTO;
+
+                passwordPolicyTO.setAllowNullPassword(passwordPolicy.isAllowNullPassword());
+                passwordPolicyTO.setHistoryLength(passwordPolicy.getHistoryLength());
+
+                passwordPolicyTO.getRuleConfs().clear();
+                for (PasswordRuleConf ruleConf : passwordPolicy.getRuleConfs()) {
+                    passwordPolicyTO.getRuleConfs().add((AbstractPasswordRuleConf) ruleConf);
+                }
                 break;
 
             case ACCOUNT:
-                policyTO = (T) new AccountPolicyTO();
-                ((AccountPolicyTO) policyTO).setSpecification(((AccountPolicy) policy).getSpecification());
-                ((AccountPolicyTO) policyTO).getResources().addAll(((AccountPolicy) policy).getResourceNames());
+                AccountPolicy accountPolicy = AccountPolicy.class.cast(policy);
+                AccountPolicyTO accountPolicyTO = new AccountPolicyTO();
+                policyTO = (T) accountPolicyTO;
+
+                accountPolicyTO.setMaxAuthenticationAttempts(accountPolicy.getMaxAuthenticationAttempts());
+                accountPolicyTO.setPropagateSuspension(accountPolicy.isPropagateSuspension());
+
+                accountPolicyTO.getRuleConfs().clear();
+                for (AccountRuleConf ruleConf : accountPolicy.getRuleConfs()) {
+                    accountPolicyTO.getRuleConfs().add((AbstractAccountRuleConf) ruleConf);
+                }
+
+                accountPolicyTO.getResources().addAll(accountPolicy.getResourceNames());
                 break;
 
             case SYNC:
@@ -88,15 +111,6 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
         return policyTO;
     }
 
-    private ExternalResource getResource(final String resourceName) {
-        ExternalResource resource = resourceDAO.find(resourceName);
-        if (resource == null) {
-            LOG.debug("Ignoring invalid resource {} ", resourceName);
-        }
-
-        return resource;
-    }
-
     @SuppressWarnings("unchecked")
     @Override
     public <T extends Policy> T getPolicy(final T policy, final AbstractPolicyTO policyTO) {
@@ -116,7 +130,16 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                 if (result == null) {
                     result = (T) entityFactory.newEntity(PasswordPolicy.class);
                 }
-                ((PasswordPolicy) result).setSpecification(((PasswordPolicyTO) policyTO).getSpecification());
+                PasswordPolicy passwordPolicy = PasswordPolicy.class.cast(result);
+                PasswordPolicyTO passwordPolicyTO = PasswordPolicyTO.class.cast(policyTO);
+
+                passwordPolicy.setAllowNullPassword(passwordPolicyTO.isAllowNullPassword());
+                passwordPolicy.setHistoryLength(passwordPolicyTO.getHistoryLength());
+
+                passwordPolicy.removeAllRuleConfs();
+                for (PasswordRuleConf conf : passwordPolicyTO.getRuleConfs()) {
+                    passwordPolicy.add(conf);
+                }
                 break;
 
             case ACCOUNT:
@@ -127,17 +150,24 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                 if (result == null) {
                     result = (T) entityFactory.newEntity(AccountPolicy.class);
                 }
-                ((AccountPolicy) result).setSpecification(((AccountPolicyTO) policyTO).getSpecification());
+                AccountPolicy accountPolicy = AccountPolicy.class.cast(result);
+                AccountPolicyTO accountPolicyTO = AccountPolicyTO.class.cast(policyTO);
+
+                accountPolicy.setMaxAuthenticationAttempts(accountPolicyTO.getMaxAuthenticationAttempts());
+                accountPolicy.setPropagateSuspension(accountPolicyTO.isPropagateSuspension());
 
-                if (((AccountPolicy) result).getResources() != null
-                        && !((AccountPolicy) result).getResources().isEmpty()) {
-                    ((AccountPolicy) result).getResources().clear();
+                accountPolicy.removeAllRuleConfs();
+                for (AccountRuleConf conf : accountPolicyTO.getRuleConfs()) {
+                    accountPolicy.add(conf);
                 }
-                for (String resourceName : ((AccountPolicyTO) policyTO).getResources()) {
-                    ExternalResource resource = getResource(resourceName);
 
-                    if (resource != null) {
-                        ((AccountPolicy) result).add(resource);
+                accountPolicy.getResources().clear();
+                for (String resourceName : accountPolicyTO.getResources()) {
+                    ExternalResource resource = resourceDAO.find(resourceName);
+                    if (resource == null) {
+                        LOG.debug("Ignoring invalid resource {} ", resourceName);
+                    } else {
+                        accountPolicy.add(resource);
                     }
                 }
                 break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
index a5f12aa..d9a2838 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
@@ -21,9 +21,9 @@ package org.apache.syncope.core.provisioning.java.data;
 import org.apache.syncope.common.lib.to.RealmTO;
 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.EntityFactory;
-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.Realm;
 import org.apache.syncope.core.provisioning.api.data.RealmDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
index 6a40803..252b719 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
@@ -18,10 +18,9 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
-import java.util.HashSet;
-import java.util.Set;
-import org.apache.syncope.core.provisioning.api.data.ReportDataBinder;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.report.AbstractReportletConf;
+import org.apache.syncope.core.provisioning.api.data.ReportDataBinder;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
@@ -43,9 +42,6 @@ import org.springframework.stereotype.Component;
 @Component
 public class ReportDataBinderImpl implements ReportDataBinder {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(ReportDataBinder.class);
 
     private static final String[] IGNORE_REPORT_PROPERTIES = { "key", "reportlets", "executions" };
@@ -62,16 +58,7 @@ public class ReportDataBinderImpl implements ReportDataBinder {
     public void getReport(final Report report, final ReportTO reportTO) {
         BeanUtils.copyProperties(reportTO, report, IGNORE_REPORT_PROPERTIES);
 
-        // 1. remove all reportlet confs
-        Set<ReportletConf> toRemove = new HashSet<>();
-        for (ReportletConf conf : report.getReportletConfs()) {
-            toRemove.add(conf);
-        }
-        for (ReportletConf conf : toRemove) {
-            report.remove(conf);
-        }
-
-        // 2. take all reportlet confs from reportTO
+        report.removeAllReportletConfs();
         for (ReportletConf conf : reportTO.getReportletConfs()) {
             report.add(conf);
         }
@@ -83,11 +70,14 @@ public class ReportDataBinderImpl implements ReportDataBinder {
         reportTO.setKey(report.getKey());
         BeanUtils.copyProperties(report, reportTO, IGNORE_REPORT_PROPERTIES);
 
-        copyReportletConfs(report, reportTO);
+        reportTO.getReportletConfs().clear();
+        for (ReportletConf reportletConf : report.getReportletConfs()) {
+            reportTO.getReportletConfs().add((AbstractReportletConf) reportletConf);
+        }
 
         ReportExec latestExec = reportExecDAO.findLatestStarted(report);
         reportTO.setLatestExecStatus(latestExec == null
-                ? ""
+                ? StringUtils.EMPTY
                 : latestExec.getStatus());
 
         reportTO.setStartDate(latestExec == null
@@ -120,13 +110,6 @@ public class ReportDataBinderImpl implements ReportDataBinder {
         return reportTO;
     }
 
-    private void copyReportletConfs(final Report report, final ReportTO reportTO) {
-        reportTO.getReportletConfs().clear();
-        for (ReportletConf reportletConf : report.getReportletConfs()) {
-            reportTO.getReportletConfs().add((AbstractReportletConf) reportletConf);
-        }
-    }
-
     @Override
     public ReportExecTO getReportExecTO(final ReportExec execution) {
         ReportExecTO executionTO = new ReportExecTO();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index cb8f979..5821106 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -36,14 +36,14 @@ import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
-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.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-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.provisioning.api.ConnectorRegistry;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
index 2e70e80..3b9dc70 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
+import org.apache.syncope.common.lib.policy.SyncPolicySpec;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
index 4878362..642181f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
@@ -25,7 +25,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
+import org.apache.syncope.common.lib.policy.SyncPolicySpec;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
index ecec019..a6c4c5d 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
@@ -21,10 +21,10 @@ package org.apache.syncope.core.rest.cxf.service;
 import java.net.URI;
 import java.util.List;
 import javax.ws.rs.core.Response;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
-import org.apache.syncope.common.lib.to.AccountPolicyTO;
-import org.apache.syncope.common.lib.to.PasswordPolicyTO;
-import org.apache.syncope.common.lib.to.SyncPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
+import org.apache.syncope.common.lib.policy.SyncPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.PolicyService;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
index 9fa3d99..e04053a 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
@@ -31,8 +31,6 @@ import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.JobAction;
 import org.apache.syncope.common.lib.types.JobStatusType;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
-import org.apache.syncope.common.lib.wrap.ReportletConfClass;
-import org.apache.syncope.common.rest.api.CollectionWrapper;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.beans.ListQuery;
 import org.apache.syncope.common.rest.api.service.ReportService;
@@ -74,11 +72,6 @@ public class ReportServiceImpl extends AbstractServiceImpl implements ReportServ
     }
 
     @Override
-    public List<ReportletConfClass> getReportletConfClasses() {
-        return CollectionWrapper.wrap(logic.getReportletConfClasses(), ReportletConfClass.class);
-    }
-
-    @Override
     public ReportTO read(final Long key) {
         return logic.read(key);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
index 8903058..47c468d 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
@@ -18,19 +18,20 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.policy.AbstractAccountRuleConf;
 
-public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
+@XmlRootElement(name = "testAccountRuleConf")
+@XmlType
+public class TestAccountRuleConf extends AbstractAccountRuleConf {
 
     private static final long serialVersionUID = -1803947511928491978L;
 
-    @Override
-    public String getName() {
-        return getClass().getName();
-    }
+    private String mustContainSubstring = "YYY";
 
     public String getMustContainSubstring() {
-        return "YYY";
+        return mustContainSubstring;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
index 2b67f37..ea41274 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
@@ -18,30 +18,30 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import org.apache.syncope.common.lib.policy.AccountRuleConf;
-import org.apache.syncope.core.misc.policy.AccountPolicyException;
-import org.apache.syncope.core.persistence.api.dao.AccountRule;
-import org.apache.syncope.core.persistence.api.dao.AccountRuleConfClass;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.core.misc.policy.PasswordPolicyException;
+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.entity.user.User;
 import org.springframework.transaction.annotation.Transactional;
 
-@AccountRuleConfClass(TestAccountRuleConf.class)
-public class TestAccountRule implements AccountRule {
+@PasswordRuleConfClass(TestPasswordRuleConf.class)
+public class TestPasswordRule implements PasswordRule {
 
-    private TestAccountRuleConf conf;
+    private TestPasswordRuleConf conf;
 
     @Transactional(readOnly = true)
     @Override
-    public void enforce(final AccountRuleConf conf, final User user) {
-        if (conf instanceof TestAccountRuleConf) {
-            this.conf = TestAccountRuleConf.class.cast(conf);
+    public void enforce(final PasswordRuleConf conf, final User user) {
+        if (conf instanceof TestPasswordRuleConf) {
+            this.conf = TestPasswordRuleConf.class.cast(conf);
         } else {
             throw new IllegalArgumentException(
-                    AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
+                    PasswordRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
         }
 
-        if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
-            throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
+        if (!user.getClearPassword().endsWith(this.conf.getMustEndWith())) {
+            throw new PasswordPolicyException("Password not ending with " + this.conf.getMustEndWith());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
index 8903058..c6c6446 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
@@ -18,19 +18,20 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.policy.AbstractPasswordRuleConf;
 
-public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
+@XmlRootElement(name = "testPasswordRuleConf")
+@XmlType
+public class TestPasswordRuleConf extends AbstractPasswordRuleConf {
 
     private static final long serialVersionUID = -1803947511928491978L;
 
-    @Override
-    public String getName() {
-        return getClass().getName();
-    }
+    private String mustEndWith = "XXX";
 
-    public String getMustContainSubstring() {
-        return "YYY";
+    public String getMustEndWith() {
+        return mustEndWith;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/log4j2.xml b/fit/core-reference/src/main/resources/log4j2.xml
index df1de40..7ef0997 100644
--- a/fit/core-reference/src/main/resources/log4j2.xml
+++ b/fit/core-reference/src/main/resources/log4j2.xml
@@ -103,7 +103,7 @@ under the License.
       <appender-ref ref="connid"/>
     </asyncLogger>
     
-    <asyncLogger name="org.apache.syncope" additivity="false" level="ERROR">
+    <asyncLogger name="org.apache.syncope" additivity="false" level="INFO">
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.provisioning" additivity="false" level="INFO">

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
index 871155a..368035e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
@@ -39,7 +39,7 @@ import org.apache.syncope.common.lib.mod.AnyObjectMod;
 import org.apache.syncope.common.lib.mod.AttrMod;
 import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.mod.UserMod;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AttrTO;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PolicyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PolicyITCase.java
index 95701ae..a08b881 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PolicyITCase.java
@@ -20,22 +20,24 @@ package org.apache.syncope.fit.core.reference;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.util.Arrays;
 import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.AccountPolicyTO;
-import org.apache.syncope.common.lib.to.PasswordPolicyTO;
-import org.apache.syncope.common.lib.to.SyncPolicyTO;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
+import org.apache.syncope.common.lib.policy.SyncPolicyTO;
+import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
+import org.apache.syncope.common.lib.policy.SyncPolicySpec;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
@@ -116,24 +118,17 @@ public class PolicyITCase extends AbstractITCase {
 
     @Test
     public void update() {
-        // get global password
         PasswordPolicyTO globalPolicy = policyService.read(2L);
 
-        PasswordPolicyTO policy = new PasswordPolicyTO();
+        PasswordPolicyTO policy = SerializationUtils.clone(globalPolicy);
         policy.setDescription("A simple password policy");
-        policy.setSpecification(globalPolicy.getSpecification());
 
-        // create a new password policy using global password as a template
+        // create a new password policy using the former as a template
         policy = createPolicy(policy);
+        assertNotNull(policy);
+        assertNotEquals(2L, policy.getKey());
 
-        // read new password policy
-        policy = policyService.read(policy.getKey());
-
-        assertNotNull("find to update did not work", policy);
-
-        PasswordPolicySpec policySpec = policy.getSpecification();
-        policySpec.setMaxLength(22);
-        policy.setSpecification(policySpec);
+        ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).setMaxLength(22);
 
         // update new password policy
         policyService.update(policy);
@@ -141,8 +136,8 @@ public class PolicyITCase extends AbstractITCase {
 
         assertNotNull(policy);
         assertEquals(PolicyType.PASSWORD, policy.getType());
-        assertEquals(22, policy.getSpecification().getMaxLength());
-        assertEquals(8, policy.getSpecification().getMinLength());
+        assertEquals(22, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMaxLength());
+        assertEquals(8, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMinLength());
     }
 
     @Test
@@ -172,10 +167,10 @@ public class PolicyITCase extends AbstractITCase {
         AccountPolicyTO policy = new AccountPolicyTO();
         policy.setDescription("SYNCOPE553");
 
-        final AccountPolicySpec accountPolicySpec = new AccountPolicySpec();
-        accountPolicySpec.setMinLength(3);
-        accountPolicySpec.setMaxLength(8);
-        policy.setSpecification(accountPolicySpec);
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
 
         policy = createPolicy(policy);
         assertNotNull(policy);
@@ -187,10 +182,10 @@ public class PolicyITCase extends AbstractITCase {
         policy.setDescription("SYNCOPE682");
         policy.getResources().add(RESOURCE_NAME_LDAP);
 
-        final AccountPolicySpec accountPolicySpec = new AccountPolicySpec();
-        accountPolicySpec.setMinLength(3);
-        accountPolicySpec.setMaxLength(8);
-        policy.setSpecification(accountPolicySpec);
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
 
         policy = createPolicy(policy);
         assertNotNull(policy);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/RealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/RealmITCase.java
index fe2c0a5..c203272 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/RealmITCase.java
@@ -31,9 +31,9 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
+import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.service.RealmService;
 import org.junit.FixMethodOrder;
@@ -136,10 +136,10 @@ public class RealmITCase extends AbstractITCase {
         AccountPolicyTO policy = new AccountPolicyTO();
         policy.setDescription("deletingAccountPolicy");
 
-        final AccountPolicySpec accountPolicySpec = new AccountPolicySpec();
-        accountPolicySpec.setMinLength(3);
-        accountPolicySpec.setMaxLength(8);
-        policy.setSpecification(accountPolicySpec);
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
 
         policy = createPolicy(policy);
         assertNotNull(policy);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ReportITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ReportITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ReportITCase.java
index d02b726..e092a1d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ReportITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ReportITCase.java
@@ -39,7 +39,6 @@ import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
 import org.apache.syncope.common.lib.types.ReportExecStatus;
-import org.apache.syncope.common.lib.wrap.ReportletConfClass;
 import org.apache.syncope.common.rest.api.service.ReportService;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -56,9 +55,9 @@ public class ReportITCase extends AbstractITCase {
 
     @Test
     public void getReportletClasses() {
-        List<ReportletConfClass> reportletClasses = reportService.getReportletConfClasses();
-        assertNotNull(reportletClasses);
-        assertFalse(reportletClasses.isEmpty());
+        List<String> reportlets = syncopeService.info().getReportlets();
+        assertNotNull(reportlets);
+        assertFalse(reportlets.isEmpty());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
index d97eaed..4604731 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
@@ -46,7 +46,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
-import org.apache.syncope.common.lib.to.SyncPolicyTO;
+import org.apache.syncope.common.lib.policy.SyncPolicyTO;
 import org.apache.syncope.common.lib.to.SyncTaskTO;
 import org.apache.syncope.common.lib.to.TaskExecTO;
 import org.apache.syncope.common.lib.to.UserTO;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
index da438d3..5fe876f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
@@ -38,6 +38,7 @@ import java.util.Map;
 import java.util.Set;
 import javax.naming.NamingException;
 import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -50,6 +51,9 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 import org.apache.syncope.common.lib.mod.StatusMod;
 import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
+import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
@@ -63,6 +67,7 @@ import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -1162,6 +1167,66 @@ public class UserITCase extends AbstractITCase {
     }
 
     @Test
+    public void customPolicyRules() {
+        // Using custom policy rules with application/xml requires to overwrite
+        // org.apache.syncope.common.lib.policy.AbstractAccountRuleConf's and / or
+        // org.apache.syncope.common.lib.policy.AbstractPasswordRuleConf's
+        // @XmlSeeAlso - the power of JAXB :-/
+        Assume.assumeTrue(MediaType.APPLICATION_JSON_TYPE.equals(clientFactory.getContentType().getMediaType()));
+
+        AccountPolicyTO accountPolicy = new AccountPolicyTO();
+        accountPolicy.setDescription("Account Policy with custom rules");
+        accountPolicy.getRuleConfs().add(new TestAccountRuleConf());
+        accountPolicy = createPolicy(accountPolicy);
+        assertNotNull(accountPolicy);
+
+        PasswordPolicyTO passwordPolicy = new PasswordPolicyTO();
+        passwordPolicy.setDescription("Password Policy with custom rules");
+        passwordPolicy.getRuleConfs().add(new TestPasswordRuleConf());
+        passwordPolicy = createPolicy(passwordPolicy);
+        assertNotNull(passwordPolicy);
+
+        RealmTO realm = realmService.list("/even/two").get(0);
+        Long oldAccountPolicy = realm.getAccountPolicy();
+        realm.setAccountPolicy(accountPolicy.getKey());
+        Long oldPasswordPolicy = realm.getPasswordPolicy();
+        realm.setPasswordPolicy(passwordPolicy.getKey());
+        realmService.update(realm);
+
+        try {
+            UserTO user = getUniqueSampleTO("custompolicyrules@syncope.apache.org");
+            user.setRealm(realm.getFullPath());
+            try {
+                createUser(user);
+                fail();
+            } catch (SyncopeClientException e) {
+                assertEquals(ClientExceptionType.InvalidUser, e.getType());
+                assertTrue(e.getElements().iterator().next().startsWith("InvalidPassword"));
+            }
+
+            user.setPassword(user.getPassword() + "XXX");
+            try {
+                createUser(user);
+                fail();
+            } catch (SyncopeClientException e) {
+                assertEquals(ClientExceptionType.InvalidUser, e.getType());
+                assertTrue(e.getElements().iterator().next().startsWith("InvalidUsername"));
+            }
+
+            user.setUsername("YYY" + user.getUsername());
+            user = createUser(user);
+            assertNotNull(user);
+        } finally {
+            realm.setAccountPolicy(oldAccountPolicy);
+            realm.setPasswordPolicy(oldPasswordPolicy);
+            realmService.update(realm);
+
+            policyService.delete(passwordPolicy.getKey());
+            policyService.delete(accountPolicy.getKey());
+        }
+    }
+
+    @Test
     public void issueSYNCOPE108() {
         UserTO userTO = getUniqueSampleTO("syncope108@syncope.apache.org");
         userTO.getResources().clear();
@@ -2418,4 +2483,45 @@ public class UserITCase extends AbstractITCase {
         assertNotNull(connObjectTO);
         assertEquals("newPostalAddress", connObjectTO.getPlainAttrMap().get("postalAddress").getValues().get(0));
     }
+
+    @Test
+    public void issueSYNCOPE626() {
+        PasswordPolicyTO passwordPolicy = new PasswordPolicyTO();
+        passwordPolicy.setDescription("Password Policy for SYNCOPE-626");
+
+        DefaultPasswordRuleConf ruleConf = new DefaultPasswordRuleConf();
+        ruleConf.setUsernameAllowed(false);
+        passwordPolicy.getRuleConfs().add(ruleConf);
+
+        passwordPolicy = createPolicy(passwordPolicy);
+        assertNotNull(passwordPolicy);
+
+        RealmTO realm = realmService.list("/even/two").get(0);
+        Long oldPasswordPolicy = realm.getPasswordPolicy();
+        realm.setPasswordPolicy(passwordPolicy.getKey());
+        realmService.update(realm);
+
+        try {
+            UserTO user = getUniqueSampleTO("syncope626@syncope.apache.org");
+            user.setRealm(realm.getFullPath());
+            user.setPassword(user.getUsername());
+            try {
+                createUser(user);
+                fail();
+            } catch (SyncopeClientException e) {
+                assertEquals(ClientExceptionType.InvalidUser, e.getType());
+                assertTrue(e.getElements().iterator().next().startsWith("InvalidPassword"));
+            }
+
+            user.setPassword("password123");
+            user = createUser(user);
+            assertNotNull(user);
+        } finally {
+            realm.setPasswordPolicy(oldPasswordPolicy);
+            realmService.update(realm);
+
+            policyService.delete(passwordPolicy.getKey());
+        }
+
+    }
 }