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

[01/12] syncope git commit: Cleanup unused stuff

Repository: syncope
Updated Branches:
  refs/heads/master 4cdb34b3c -> b8cadde8e


Cleanup unused stuff


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

Branch: refs/heads/master
Commit: fc91e516ed0ba34f8252830f69830460d58eae6b
Parents: 8fe3c7c
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Aug 17 17:28:55 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Aug 17 17:28:55 2015 +0200

----------------------------------------------------------------------
 .../lib/annotation/FormAttributeField.java      | 36 --------------------
 .../lib/report/AbstractAnyReportletConf.java    |  6 ----
 .../core/misc/policy/AccountPolicyEnforcer.java |  9 ++---
 .../misc/policy/PasswordPolicyEnforcer.java     | 17 ++++-----
 .../misc/policy/PolicyEnforceException.java     | 32 -----------------
 .../core/misc/policy/PolicyEvaluator.java       | 13 +++----
 .../core/persistence/jpa/dao/JPAUserDAO.java    |  4 +--
 7 files changed, 15 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java b/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
deleted file mode 100644
index 5d2603f..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
+++ /dev/null
@@ -1,36 +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.common.lib.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.apache.syncope.common.lib.types.IntMappingType;
-
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface FormAttributeField {
-
-    boolean userSearch() default false;
-
-    boolean groupSearch() default false;
-
-    IntMappingType schema() default IntMappingType.UserPlainSchema;
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractAnyReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractAnyReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractAnyReportletConf.java
index e6949b6..29f6363 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractAnyReportletConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractAnyReportletConf.java
@@ -24,24 +24,18 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.annotation.FormAttributeField;
-import org.apache.syncope.common.lib.types.IntMappingType;
 
 @XmlType
 public abstract class AbstractAnyReportletConf extends AbstractReportletConf {
 
     private static final long serialVersionUID = -5388597116592877789L;
 
-    @FormAttributeField(userSearch = true)
     protected String matchingCond;
 
-    @FormAttributeField(schema = IntMappingType.UserPlainSchema)
     protected final List<String> plainAttrs = new ArrayList<>();
 
-    @FormAttributeField(schema = IntMappingType.UserDerivedSchema)
     protected final List<String> derAttrs = new ArrayList<>();
 
-    @FormAttributeField(schema = IntMappingType.UserVirtualSchema)
     protected final List<String> virAttrs = new ArrayList<>();
 
     public AbstractAnyReportletConf() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
index 23740d6..8b7a547 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.misc.policy;
 
 import java.util.regex.Pattern;
 import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.springframework.stereotype.Component;
 
@@ -29,13 +28,9 @@ public class AccountPolicyEnforcer {
 
     private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+");
 
-    public boolean enforce(final AccountPolicySpec policy, final PolicyType type, final User user) {
+    public boolean enforce(final AccountPolicySpec policy, final User user) {
         if (user.getUsername() == null) {
-            throw new PolicyEnforceException("Invalid account");
-        }
-
-        if (policy == null) {
-            throw new PolicyEnforceException("Invalid policy");
+            throw new AccountPolicyException("Invalid account");
         }
 
         // check min length

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
index 1458bf3..c2af367 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
@@ -19,24 +19,21 @@
 package org.apache.syncope.core.misc.policy;
 
 import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.springframework.stereotype.Component;
 
 @Component
 public class PasswordPolicyEnforcer {
 
-    public boolean enforce(final PasswordPolicySpec policy, final PolicyType type, final User user) {
-        final String clearPassword = user.getClearPassword();
-        final String password = user.getPassword();
-
-        if (policy == null) {
-            throw new PolicyEnforceException("Invalid policy");
-        }
+    public boolean enforce(final PasswordPolicySpec policy, final User user) {
+        String clearPassword = user.getClearPassword();
+        String password = user.getPassword();
 
         if (password == null && !policy.isAllowNullPassword()) {
-            throw new PolicyEnforceException("Password mandatory");
-        } else if (password != null && clearPassword != null) {
+            throw new PasswordPolicyException("Password mandatory");
+        }
+        
+        if (password != null && clearPassword != null) {
             // check length
             if (policy.getMinLength() > 0 && policy.getMinLength() > clearPassword.length()) {
                 throw new PasswordPolicyException("Password too short");

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforceException.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforceException.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforceException.java
deleted file mode 100644
index e7211b8..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEnforceException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.misc.policy;
-
-public class PolicyEnforceException extends PolicyException {
-
-    private static final long serialVersionUID = 3247084727383061069L;
-
-    public PolicyEnforceException() {
-        super();
-    }
-
-    public PolicyEnforceException(final String message) {
-        super(message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
index fd6abd2..425568d 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
@@ -38,11 +38,7 @@ public class PolicyEvaluator {
 
     @SuppressWarnings("unchecked")
     public <T extends PolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) {
-        if (policy == null) {
-            return null;
-        }
-
-        T result = null;
+        T result;
         switch (policy.getType()) {
             case PASSWORD:
                 PasswordPolicySpec ppSpec = policy.getSpecification(PasswordPolicySpec.class);
@@ -75,13 +71,13 @@ public class PolicyEvaluator {
                 break;
 
             case ACCOUNT:
-                final AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class);
-                final AccountPolicySpec accountPolicy = new AccountPolicySpec();
+                AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class);
+                AccountPolicySpec accountPolicy = new AccountPolicySpec();
 
                 BeanUtils.copyProperties(spec, accountPolicy, new String[] { "schemasNotPermitted" });
 
                 for (String schema : spec.getSchemasNotPermitted()) {
-                    PlainAttr attr = any.getPlainAttr(schema);
+                    PlainAttr<?> attr = any.getPlainAttr(schema);
                     if (attr != null) {
                         List<String> values = attr.getValuesAsStrings();
                         if (values != null && !values.isEmpty()) {
@@ -93,7 +89,6 @@ public class PolicyEvaluator {
                 result = (T) accountPolicy;
                 break;
 
-            case SYNC:
             default:
                 result = null;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fc91e516/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 4e9afe1..7dd3fe7 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
@@ -239,7 +239,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
                 // evaluate policy
                 PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user);
                 // enforce policy
-                ppEnforcer.enforce(ppSpec, policy.getType(), user);
+                ppEnforcer.enforce(ppSpec, user);
 
                 if (ppSpec.getHistoryLength() > maxPPSpecHistory) {
                     maxPPSpecHistory = ppSpec.getHistoryLength();
@@ -282,7 +282,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
                 AccountPolicySpec apSpec = evaluator.evaluate(policy, user);
 
                 // enforce policy
-                suspend |= apEnforcer.enforce(apSpec, policy.getType(), user);
+                suspend |= apEnforcer.enforce(apSpec, user);
                 propagateSuspension |= apSpec.isPropagateSuspension();
             }
         } catch (Exception e) {


[05/12] syncope git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope

Posted by il...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope


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

Branch: refs/heads/master
Commit: 850269800611173a97c178bf90657312580a45e7
Parents: 56568a4 9abd35a
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Aug 19 09:19:21 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Aug 19 09:19:21 2015 +0200

----------------------------------------------------------------------
 .../client/console/panels/ListViewPanel.java    |  68 ++++--
 .../console/panels/NotificationPanel.java       |  19 +-
 .../console/panels/ResourceDetailsPanel.java    |   2 +-
 .../console/panels/ResourceMappingPanel.java    |  48 ----
 .../client/console/panels/ResourceModal.java    |  25 ++-
 .../client/console/rest/AnyTypeRestClient.java  |  46 ++++
 .../client/console/topology/Topology.java       |  79 ++-----
 .../console/topology/WebSocketBehavior.java     | 209 +++++++++++++++++
 .../markup/html/form/AjaxCheckBoxPanel.java     |   7 +-
 .../html/form/AjaxDropDownChoicePanel.java      |   7 +-
 .../markup/html/form/AjaxTextFieldPanel.java    |   7 +-
 .../wicket/markup/html/form/FieldPanel.java     |   8 +-
 .../client/console/wizards/AjaxWizard.java      |  79 +++++--
 .../console/wizards/AjaxWizardBuilder.java      |  96 ++++++++
 .../console/wizards/AjaxWizardButtonBar.java    |  28 ++-
 .../client/console/wizards/ProvisionWizard.java | 123 ----------
 .../provision/ProvisionWizardBuilder.java       | 222 +++++++++++++++++++
 .../console/panels/ResourceMappingPanel.html    |  20 --
 .../wizards/ProvisionWizard$AccountLink.html    |  23 --
 .../wizards/ProvisionWizard$Mapping.html        |  23 --
 .../wizards/ProvisionWizard$ObjectType.html     |  30 ---
 .../console/wizards/ProvisionWizard.properties  |  24 --
 .../wizards/ProvisionWizard_it.properties       |  24 --
 .../wizards/ProvisionWizard_pt_BR.properties    |  24 --
 .../ProvisionWizardBuilder$ConnObjectLink.html  |  31 +++
 ...isionWizardBuilder$ConnObjectLink.properties |  20 ++
 ...onWizardBuilder$ConnObjectLink_it.properties |  20 ++
 ...izardBuilder$ConnObjectLink_pt_BR.properties |  20 ++
 .../ProvisionWizardBuilder$Mapping.html         |  23 ++
 .../ProvisionWizardBuilder$Mapping.properties   |  20 ++
 ...ProvisionWizardBuilder$Mapping_it.properties |  20 ++
 ...visionWizardBuilder$Mapping_pt_BR.properties |  20 ++
 .../ProvisionWizardBuilder$ObjectType.html      |  31 +++
 ...ProvisionWizardBuilder$ObjectType.properties |  24 ++
 ...visionWizardBuilder$ObjectType_it.properties |  23 ++
 ...ionWizardBuilder$ObjectType_pt_BR.properties |  23 ++
 36 files changed, 1042 insertions(+), 474 deletions(-)
----------------------------------------------------------------------



[12/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

Posted by il...@apache.org.
[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 implemented as default rules - also contain SYNCOPE-626


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

Branch: refs/heads/master
Commit: b8cadde8ec53da6834792b356cfe40a454193644
Parents: 77f697b
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Aug 20 11:47:26 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 20 11:47:26 2015 +0200

----------------------------------------------------------------------
 .../client/cli/commands/PolicyCommand.java      |   2 +-
 .../client/cli/commands/ReportCommand.java      |  14 -
 .../console/panels/ResourceSecurityPanel.java   |   2 +-
 .../client/console/rest/PolicyRestClient.java   |   2 +-
 .../client/console/rest/ReportRestClient.java   |  18 --
 .../client/lib/SyncopeClientFactoryBean.java    |   2 +-
 .../lib/policy/AbstractAccountRuleConf.java     |  12 +-
 .../lib/policy/AbstractPasswordRuleConf.java    |  12 +-
 .../common/lib/policy/AccountPolicyTO.java      |   4 +-
 .../lib/policy/DefaultAccountRuleConf.java      |  55 +++-
 .../lib/policy/DefaultPasswordRuleConf.java     |  67 +++-
 .../common/lib/policy/PasswordPolicyTO.java     |   4 +-
 .../common/lib/report/StaticReportletConf.java  |   2 +-
 .../syncope/common/lib/to/AbstractPolicyTO.java |  97 ------
 .../syncope/common/lib/to/AccountPolicyTO.java  |  59 ----
 .../syncope/common/lib/to/PasswordPolicyTO.java |  46 ---
 .../syncope/common/lib/to/SyncPolicyTO.java     |  46 ---
 .../apache/syncope/common/lib/to/SyncopeTO.java |  28 ++
 .../common/lib/types/AbstractPolicySpec.java    | 100 ------
 .../common/lib/types/AccountPolicySpec.java     | 121 --------
 .../common/lib/types/PasswordPolicySpec.java    | 300 ------------------
 .../syncope/common/lib/types/PolicyType.java    |  43 ---
 .../common/lib/types/PushPolicySpec.java        |  28 --
 .../common/lib/types/SyncPolicySpec.java        |  62 ----
 .../common/rest/api/service/PolicyService.java  |   2 +-
 .../common/rest/api/service/ReportService.java  |  11 -
 .../apache/syncope/core/logic/PolicyLogic.java  |  14 +-
 .../apache/syncope/core/logic/ReportLogic.java  |  75 -----
 .../apache/syncope/core/logic/SyncopeLogic.java |   7 +
 .../init/ImplementationClassNamesLoader.java    |  13 +
 .../core/logic/report/AbstractReportlet.java    |  21 +-
 .../core/logic/report/GroupReportlet.java       |  13 +-
 .../core/logic/report/ReportJobDelegate.java    |  63 +++-
 .../syncope/core/logic/report/Reportlet.java    |  14 +-
 .../core/logic/report/StaticReportlet.java      |  38 ++-
 .../core/logic/report/UserReportlet.java        |  13 +-
 .../syncope/core/misc/ConnObjectUtils.java      |  24 +-
 .../apache/syncope/core/misc/MappingUtils.java  |   6 +-
 .../core/misc/policy/AccountPolicyEnforcer.java |  85 -----
 .../InvalidPasswordPolicySpecException.java     |  37 ---
 .../misc/policy/PasswordPolicyEnforcer.java     | 193 ------------
 .../core/misc/policy/PolicyEvaluator.java       | 100 ------
 .../misc/security/DefaultPasswordGenerator.java |  96 +++---
 .../core/misc/security/PasswordGenerator.java   | 310 +------------------
 .../misc/src/main/resources/security.properties |   1 +
 .../misc/src/main/resources/securityContext.xml |   1 +
 .../misc/security/PasswordGeneratorTest.java    | 146 ++++-----
 .../core/persistence/api/dao/AccountRule.java   |   9 +-
 .../core/persistence/api/dao/PasswordRule.java  |   9 +-
 .../core/persistence/api/dao/PolicyDAO.java     |   2 +-
 .../persistence/api/entity/AccountPolicy.java   |  38 ---
 .../persistence/api/entity/PasswordPolicy.java  |  29 --
 .../core/persistence/api/entity/PushPolicy.java |  28 --
 .../core/persistence/api/entity/Realm.java      |   3 +
 .../core/persistence/api/entity/Report.java     |   2 +-
 .../api/entity/ReportletConfInstance.java       |  33 --
 .../core/persistence/api/entity/SyncPolicy.java |  29 --
 .../api/entity/policy/AccountPolicy.java        |   2 +-
 .../api/entity/policy/PasswordPolicy.java       |   2 +-
 .../api/entity/resource/ExternalResource.java   |   6 +-
 .../persistence/jpa/dao/DefaultAccountRule.java |  29 +-
 .../jpa/dao/DefaultPasswordRule.java            |  61 ++--
 .../jpa/dao/JPAExternalResourceDAO.java         |   2 +-
 .../core/persistence/jpa/dao/JPAPolicyDAO.java  |  14 +-
 .../core/persistence/jpa/dao/JPARealmDAO.java   |   2 +-
 .../core/persistence/jpa/dao/JPATaskDAO.java    |   4 +-
 .../core/persistence/jpa/dao/JPAUserDAO.java    | 146 +++++++--
 .../jpa/entity/JPAAccountPolicy.java            |  96 ------
 .../jpa/entity/JPAEntityFactory.java            |  15 +-
 .../jpa/entity/JPAPasswordPolicy.java           |  48 ---
 .../core/persistence/jpa/entity/JPAPolicy.java  |  76 -----
 .../persistence/jpa/entity/JPAPushPolicy.java   |  47 ---
 .../core/persistence/jpa/entity/JPARealm.java   |   6 +-
 .../core/persistence/jpa/entity/JPAReport.java  |  27 +-
 .../jpa/entity/JPAReportletConfInstance.java    |   7 +-
 .../persistence/jpa/entity/JPASyncPolicy.java   |  48 ---
 .../jpa/entity/policy/JPAAccountPolicy.java     |  13 +-
 .../jpa/entity/policy/JPAPasswordPolicy.java    |  13 +-
 .../entity/resource/JPAExternalResource.java    |  12 +-
 .../jpa/entity/task/AbstractTask.java           |  11 +-
 .../jpa/entity/task/JPANotificationTask.java    |   2 +-
 .../jpa/entity/task/JPAPropagationTask.java     |   2 +-
 .../jpa/entity/task/JPASchedTask.java           |   2 +-
 .../persistence/jpa/entity/task/JPATask.java    |  96 ------
 .../jpa/entity/task/JPATaskExec.java            |  11 +-
 .../resources/META-INF/spring-orm-oracle.xml    |  22 +-
 .../resources/META-INF/spring-orm-sqlserver.xml |  22 +-
 .../src/main/resources/META-INF/spring-orm.xml  |  22 +-
 .../core/persistence/jpa/inner/PolicyTest.java  |  21 +-
 .../core/persistence/jpa/inner/RealmTest.java   |   4 +-
 .../core/persistence/jpa/inner/UserTest.java    |   6 +-
 .../persistence/jpa/outer/ResourceTest.java     |   2 +-
 .../test/resources/domains/MasterContent.xml    |  50 +--
 .../src/test/resources/persistenceTest.xml      |   2 +
 .../provisioning/api/data/PolicyDataBinder.java |   2 +-
 .../java/data/PolicyDataBinderImpl.java         |  90 ++++--
 .../java/data/RealmDataBinderImpl.java          |   4 +-
 .../java/data/ReportDataBinderImpl.java         |  33 +-
 .../java/data/ResourceDataBinderImpl.java       |   6 +-
 .../provisioning/java/sync/SyncJobDelegate.java |   2 +-
 .../core/provisioning/java/sync/SyncUtils.java  |   2 +-
 .../rest/cxf/service/PolicyServiceImpl.java     |   8 +-
 .../rest/cxf/service/ReportServiceImpl.java     |   7 -
 .../fit/core/reference/TestAccountRuleConf.java |  17 +-
 .../fit/core/reference/TestPasswordRule.java    |  26 +-
 .../core/reference/TestPasswordRuleConf.java    |  19 +-
 .../src/main/resources/log4j2.xml               |   2 +-
 .../fit/core/reference/AbstractITCase.java      |   2 +-
 .../fit/core/reference/PolicyITCase.java        |  51 ++-
 .../syncope/fit/core/reference/RealmITCase.java |  12 +-
 .../fit/core/reference/ReportITCase.java        |   7 +-
 .../fit/core/reference/SyncTaskITCase.java      |   2 +-
 .../syncope/fit/core/reference/UserITCase.java  | 106 +++++++
 113 files changed, 1036 insertions(+), 2904 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/cli/src/main/java/org/apache/syncope/client/cli/commands/PolicyCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/PolicyCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/PolicyCommand.java
index 6ea0d33..ae34f53 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/PolicyCommand.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/PolicyCommand.java
@@ -23,7 +23,7 @@ import com.beust.jcommander.Parameters;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.cli.SyncopeServices;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.rest.api.service.PolicyService;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
index 2c4dba0..2ea9423 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
@@ -33,7 +33,6 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 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.wrap.ReportletConfClass;
 import org.apache.syncope.common.rest.api.service.ReportService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -84,9 +83,6 @@ public class ReportCommand extends AbstractCommand {
     @Parameter(names = { "-eer", "--export-execution-result" })
     private Long exportId = -1L;
 
-    @Parameter(names = { "-rc", "--reportlet-class" })
-    private boolean reportletClass = false;
-
     @Override
     public void execute() {
         final ReportService reportService = SyncopeServices.get(ReportService.class);
@@ -176,16 +172,6 @@ public class ReportCommand extends AbstractCommand {
                 LOG.error("Error calling configuration service", ex);
                 System.out.println(" - Error calling configuration service " + ex.getMessage());
             }
-        } else if (reportletClass) {
-            try {
-                LOG.debug("- reportlet configuration class list command");
-                System.out.println("Reportlet conf classes");
-                for (final ReportletConfClass reportletConfClass : reportService.getReportletConfClasses()) {
-                    System.out.println("  *** " + reportletConfClass.getElement());
-                }
-            } catch (final SyncopeClientException ex) {
-                System.out.println(" - Error: " + ex.getMessage());
-            }
         } else {
             System.out.println(helpMessage);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceSecurityPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceSecurityPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceSecurityPanel.java
index 15d2fe8..a0a1ddc 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceSecurityPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceSecurityPanel.java
@@ -23,7 +23,7 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.markup.html.WebMarkupContainer;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
index e58f734..7f5964b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.console.rest;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.rest.api.service.PolicyService;
 import org.springframework.stereotype.Component;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index 05af975..89617df 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@ -18,14 +18,11 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import java.util.ArrayList;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
-import org.apache.syncope.common.lib.wrap.ReportletConfClass;
 import org.apache.syncope.common.rest.api.service.ReportService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.springframework.stereotype.Component;
@@ -35,21 +32,6 @@ public class ReportRestClient extends BaseRestClient implements ExecutionRestCli
 
     private static final long serialVersionUID = 1644689667998953604L;
 
-    public List<String> getReportletConfClasses() {
-        List<String> result = new ArrayList<>();
-
-        try {
-            List<ReportletConfClass> reportletConfClasses = getService(ReportService.class).getReportletConfClasses();
-            for (ReportletConfClass clazz : reportletConfClasses) {
-                result.add(clazz.getElement());
-            }
-        } catch (SyncopeClientException e) {
-            LOG.error("While getting available reportlet classes", e);
-        }
-
-        return result;
-    }
-
     public ReportTO read(final Long reportId) {
         return getService(ReportService.class).read(reportId);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
index a3a271c..968260f 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -31,7 +31,7 @@ import org.apache.cxf.feature.Feature;
 import org.apache.cxf.feature.LoggingFeature;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
 import org.apache.cxf.staxutils.DocumentDepthProperties;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 
 /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
index 8fe5e24..8820779 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.report;
+package org.apache.syncope.common.lib.policy;
 
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
@@ -24,19 +24,19 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlType
-@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, GroupReportletConf.class })
-public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
+@XmlSeeAlso({ DefaultAccountRuleConf.class })
+public abstract class AbstractAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
 
-    private static final long serialVersionUID = -6130008602014516608L;
+    private static final long serialVersionUID = -4080475005967851092L;
 
     private String name;
 
-    public AbstractReportletConf() {
+    public AbstractAccountRuleConf() {
         this(StringUtils.EMPTY);
         setName(getClass().getName());
     }
 
-    public AbstractReportletConf(final String name) {
+    public AbstractAccountRuleConf(final String name) {
         super();
         this.name = name;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
index 8fe5e24..6d35abd 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.report;
+package org.apache.syncope.common.lib.policy;
 
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
@@ -24,19 +24,19 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlType
-@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, GroupReportletConf.class })
-public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
+@XmlSeeAlso({ DefaultPasswordRuleConf.class })
+public abstract class AbstractPasswordRuleConf extends AbstractBaseBean implements PasswordRuleConf {
 
-    private static final long serialVersionUID = -6130008602014516608L;
+    private static final long serialVersionUID = -5814018872387142339L;
 
     private String name;
 
-    public AbstractReportletConf() {
+    public AbstractPasswordRuleConf() {
         this(StringUtils.EMPTY);
         setName(getClass().getName());
     }
 
-    public AbstractReportletConf(final String name) {
+    public AbstractPasswordRuleConf(final String name) {
         super();
         this.name = name;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
index 67d9fe0..b1e1049 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
@@ -37,7 +37,7 @@ public class AccountPolicyTO extends AbstractPolicyTO {
 
     private int maxAuthenticationAttempts;
 
-    private final List<AccountRuleConf> ruleConfs = new ArrayList<>();
+    private final List<AbstractAccountRuleConf> ruleConfs = new ArrayList<>();
 
     private final List<String> resources = new ArrayList<>();
 
@@ -64,7 +64,7 @@ public class AccountPolicyTO extends AbstractPolicyTO {
     @XmlElementWrapper(name = "ruleConfs")
     @XmlElement(name = "ruleConf")
     @JsonProperty("ruleConfs")
-    public List<AccountRuleConf> getRuleConfs() {
+    public List<AbstractAccountRuleConf> getRuleConfs() {
         return ruleConfs;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
index 929f05b..804fcc5 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
@@ -18,12 +18,17 @@
  */
 package org.apache.syncope.common.lib.policy;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
 @XmlRootElement(name = "defaultAccountRuleConf")
 @XmlType
-public class DefaultAccountRuleConf extends AbstractRuleConf implements AccountRuleConf {
+public class DefaultAccountRuleConf extends AbstractAccountRuleConf implements AccountRuleConf {
 
     private static final long serialVersionUID = 3259256974414758406L;
 
@@ -52,6 +57,26 @@ public class DefaultAccountRuleConf extends AbstractRuleConf implements AccountR
      */
     private boolean allLowerCase;
 
+    /**
+     * Substrings not permitted.
+     */
+    private final List<String> wordsNotPermitted = new ArrayList<>();
+
+    /**
+     * User attribute values not permitted.
+     */
+    private final List<String> schemasNotPermitted = new ArrayList<>();
+
+    /**
+     * Substrings not permitted as prefix.
+     */
+    private final List<String> prefixesNotPermitted = new ArrayList<>();
+
+    /**
+     * Substrings not permitted as suffix.
+     */
+    private final List<String> suffixesNotPermitted = new ArrayList<>();
+
     public boolean isAllLowerCase() {
         return allLowerCase;
     }
@@ -91,4 +116,32 @@ public class DefaultAccountRuleConf extends AbstractRuleConf implements AccountR
     public void setPattern(final String pattern) {
         this.pattern = pattern;
     }
+
+    @XmlElementWrapper(name = "wordsNotPermitted")
+    @XmlElement(name = "word")
+    @JsonProperty("wordsNotPermitted")
+    public List<String> getWordsNotPermitted() {
+        return wordsNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "prefixesNotPermitted")
+    @XmlElement(name = "prefix")
+    @JsonProperty("prefixesNotPermitted")
+    public List<String> getPrefixesNotPermitted() {
+        return prefixesNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "schemasNotPermitted")
+    @XmlElement(name = "schema")
+    @JsonProperty("schemasNotPermitted")
+    public List<String> getSchemasNotPermitted() {
+        return schemasNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "suffixesNotPermitted")
+    @XmlElement(name = "suffix")
+    @JsonProperty("suffixesNotPermitted")
+    public List<String> getSuffixesNotPermitted() {
+        return suffixesNotPermitted;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
index 629e820..8792897 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
@@ -18,12 +18,17 @@
  */
 package org.apache.syncope.common.lib.policy;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
 @XmlRootElement(name = "defaultPasswordRuleConf")
 @XmlType
-public class DefaultPasswordRuleConf extends AbstractRuleConf implements PasswordRuleConf {
+public class DefaultPasswordRuleConf extends AbstractPasswordRuleConf {
 
     private static final long serialVersionUID = -7988778083915548547L;
 
@@ -122,6 +127,31 @@ public class DefaultPasswordRuleConf extends AbstractRuleConf implements Passwor
      */
     private boolean mustntEndWithAlpha;
 
+    /**
+     * Specify if using username as password is allowed.
+     */
+    private boolean usernameAllowed;
+
+    /**
+     * Substrings not permitted.
+     */
+    private final List<String> wordsNotPermitted = new ArrayList<>();
+
+    /**
+     * User attribute values not permitted.
+     */
+    private final List<String> schemasNotPermitted = new ArrayList<>();
+
+    /**
+     * Substrings not permitted as prefix.
+     */
+    private final List<String> prefixesNotPermitted = new ArrayList<>();
+
+    /**
+     * Substrings not permitted as suffix.
+     */
+    private final List<String> suffixesNotPermitted = new ArrayList<>();
+
     public boolean isDigitRequired() {
         return digitRequired;
     }
@@ -274,4 +304,39 @@ public class DefaultPasswordRuleConf extends AbstractRuleConf implements Passwor
         this.mustntStartWithAlpha = mustntStartWithAlpha;
     }
 
+    public boolean isUsernameAllowed() {
+        return usernameAllowed;
+    }
+
+    public void setUsernameAllowed(final boolean usernameAllowed) {
+        this.usernameAllowed = usernameAllowed;
+    }
+
+    @XmlElementWrapper(name = "wordsNotPermitted")
+    @XmlElement(name = "word")
+    @JsonProperty("wordsNotPermitted")
+    public List<String> getWordsNotPermitted() {
+        return wordsNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "prefixesNotPermitted")
+    @XmlElement(name = "prefix")
+    @JsonProperty("prefixesNotPermitted")
+    public List<String> getPrefixesNotPermitted() {
+        return prefixesNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "schemasNotPermitted")
+    @XmlElement(name = "schema")
+    @JsonProperty("schemasNotPermitted")
+    public List<String> getSchemasNotPermitted() {
+        return schemasNotPermitted;
+    }
+
+    @XmlElementWrapper(name = "suffixesNotPermitted")
+    @XmlElement(name = "suffix")
+    @JsonProperty("suffixesNotPermitted")
+    public List<String> getSuffixesNotPermitted() {
+        return suffixesNotPermitted;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
index cf91df2..49c73a3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
@@ -37,7 +37,7 @@ public class PasswordPolicyTO extends AbstractPolicyTO {
 
     private int historyLength;
 
-    private final List<PasswordRuleConf> ruleConfs = new ArrayList<>();
+    private final List<AbstractPasswordRuleConf> ruleConfs = new ArrayList<>();
 
     public PasswordPolicyTO() {
         super(PolicyType.PASSWORD);
@@ -62,7 +62,7 @@ public class PasswordPolicyTO extends AbstractPolicyTO {
     @XmlElementWrapper(name = "ruleConfs")
     @XmlElement(name = "ruleConf")
     @JsonProperty("ruleConfs")
-    public List<PasswordRuleConf> getRuleConfs() {
+    public List<AbstractPasswordRuleConf> getRuleConfs() {
         return ruleConfs;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
index 6d867b2..2514c16 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
@@ -44,7 +44,7 @@ public class StaticReportletConf extends AbstractReportletConf {
 
     private TraceLevel traceLevel;
 
-    private final List<String> listField = new ArrayList<String>();
+    private final List<String> listField = new ArrayList<>();
 
     public StaticReportletConf() {
         super();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractPolicyTO.java
deleted file mode 100644
index 2c5fcb4..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractPolicyTO.java
+++ /dev/null
@@ -1,97 +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.common.lib.to;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import java.util.ArrayList;
-import java.util.List;
-import javax.ws.rs.PathParam;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.types.PolicyType;
-
-@XmlRootElement(name = "abstractPolicy")
-@XmlType
-@XmlSeeAlso({ AccountPolicyTO.class, PasswordPolicyTO.class, SyncPolicyTO.class })
-@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
-public abstract class AbstractPolicyTO extends AbstractBaseBean {
-
-    private static final long serialVersionUID = -2903888572649721035L;
-
-    private long key;
-
-    private String description;
-
-    private final PolicyType type;
-
-    private final List<String> usedByResources = new ArrayList<>();
-
-    private final List<String> usedByRealms = new ArrayList<>();
-
-    private AbstractPolicyTO() {
-        super();
-        throw new UnsupportedOperationException("No-arg constructor is just to keep JAXB from complaining");
-    }
-
-    protected AbstractPolicyTO(final PolicyType type) {
-        super();
-        this.type = type;
-    }
-
-    public long getKey() {
-        return key;
-    }
-
-    @PathParam("key")
-    public void setKey(final long key) {
-        this.key = key;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(final String description) {
-        this.description = description;
-    }
-
-    public PolicyType getType() {
-        return type;
-    }
-
-    @XmlElementWrapper(name = "usedByResources")
-    @XmlElement(name = "resource")
-    @JsonProperty("usedByResources")
-    public List<String> getUsedByResources() {
-        return usedByResources;
-    }
-
-    @XmlElementWrapper(name = "usedByRealms")
-    @XmlElement(name = "group")
-    @JsonProperty("usedByRealms")
-    public List<String> getUsedByRealms() {
-        return usedByRealms;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/to/AccountPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AccountPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AccountPolicyTO.java
deleted file mode 100644
index a701899..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AccountPolicyTO.java
+++ /dev/null
@@ -1,59 +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.common.lib.to;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-
-@XmlRootElement(name = "accountPolicy")
-@XmlType
-public class AccountPolicyTO extends AbstractPolicyTO {
-
-    private static final long serialVersionUID = -1557150042828800134L;
-
-    private AccountPolicySpec specification;
-
-    private final List<String> resources = new ArrayList<>();
-
-    public AccountPolicyTO() {
-        super(PolicyType.ACCOUNT);
-    }
-
-    public AccountPolicySpec getSpecification() {
-        return specification;
-    }
-
-    public void setSpecification(final AccountPolicySpec specification) {
-        this.specification = specification;
-    }
-
-    @XmlElementWrapper(name = "resources")
-    @XmlElement(name = "resource")
-    @JsonProperty("resources")
-    public List<String> getResources() {
-        return resources;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordPolicyTO.java
deleted file mode 100644
index a0a21ea..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordPolicyTO.java
+++ /dev/null
@@ -1,46 +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.common.lib.to;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.PolicyType;
-
-@XmlRootElement(name = "passwordPolicy")
-@XmlType
-public class PasswordPolicyTO extends AbstractPolicyTO {
-
-    private static final long serialVersionUID = -5606086441294799690L;
-
-    private PasswordPolicySpec specification;
-
-    public PasswordPolicyTO() {
-        super(PolicyType.PASSWORD);
-    }
-
-    public PasswordPolicySpec getSpecification() {
-        return specification;
-    }
-
-    public void setSpecification(final PasswordPolicySpec specification) {
-        this.specification = specification;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncPolicyTO.java
deleted file mode 100644
index 309a4eb..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncPolicyTO.java
+++ /dev/null
@@ -1,46 +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.common.lib.to;
-
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
-
-@XmlRootElement(name = "syncPolicy")
-@XmlType
-public class SyncPolicyTO extends AbstractPolicyTO {
-
-    private static final long serialVersionUID = 993024634238024242L;
-
-    private SyncPolicySpec specification;
-
-    public SyncPolicyTO() {
-        super(PolicyType.SYNC);
-    }
-
-    public SyncPolicySpec getSpecification() {
-        return specification;
-    }
-
-    public void setSpecification(final SyncPolicySpec specification) {
-        this.specification = specification;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncopeTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncopeTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncopeTO.java
index 243a79f..fe57d52 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncopeTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncopeTO.java
@@ -59,8 +59,14 @@ public class SyncopeTO extends AbstractBaseBean {
 
     private String virAttrCache;
 
+    private String passwordGenerator;
+
     private final List<String> reportlets = new ArrayList<>();
 
+    private final List<String> accountRules = new ArrayList<>();
+
+    private final List<String> passwordRules = new ArrayList<>();
+
     private final List<String> taskJobs = new ArrayList<>();
 
     private final List<String> propagationActions = new ArrayList<>();
@@ -132,6 +138,14 @@ public class SyncopeTO extends AbstractBaseBean {
         return virAttrCache;
     }
 
+    public String getPasswordGenerator() {
+        return passwordGenerator;
+    }
+
+    public void setPasswordGenerator(final String passwordGenerator) {
+        this.passwordGenerator = passwordGenerator;
+    }
+
     @XmlElementWrapper(name = "reportlets")
     @XmlElement(name = "reportlet")
     @JsonProperty("reportlets")
@@ -139,6 +153,20 @@ public class SyncopeTO extends AbstractBaseBean {
         return reportlets;
     }
 
+    @XmlElementWrapper(name = "accountRules")
+    @XmlElement(name = "accountRule")
+    @JsonProperty("accountRules")
+    public List<String> getAccountRules() {
+        return accountRules;
+    }
+
+    @XmlElementWrapper(name = "passwordRules")
+    @XmlElement(name = "passwordRule")
+    @JsonProperty("passwordRules")
+    public List<String> getPasswordRules() {
+        return passwordRules;
+    }
+
     @XmlElementWrapper(name = "taskJobs")
     @XmlElement(name = "taskJob")
     @JsonProperty("taskJobs")

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
deleted file mode 100644
index e951419..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
+++ /dev/null
@@ -1,100 +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.common.lib.types;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-@XmlType
-public abstract class AbstractPolicySpec {
-
-    private static final long serialVersionUID = -6210646284287392063L;
-
-    /**
-     * Substrings not permitted.
-     */
-    private final List<String> wordsNotPermitted = new ArrayList<>();
-
-    /**
-     * User attribute values not permitted.
-     */
-    protected final List<String> schemasNotPermitted = new ArrayList<>();
-
-    /**
-     * Substrings not permitted as prefix.
-     */
-    protected final List<String> prefixesNotPermitted = new ArrayList<>();
-
-    /**
-     * Substrings not permitted as suffix.
-     */
-    protected final List<String> suffixesNotPermitted = new ArrayList<>();
-
-    @XmlElementWrapper(name = "wordsNotPermitted")
-    @XmlElement(name = "word")
-    @JsonProperty("wordsNotPermitted")
-    public List<String> getWordsNotPermitted() {
-        return wordsNotPermitted;
-    }
-
-    @XmlElementWrapper(name = "prefixesNotPermitted")
-    @XmlElement(name = "prefix")
-    @JsonProperty("prefixesNotPermitted")
-    public List<String> getPrefixesNotPermitted() {
-        return prefixesNotPermitted;
-    }
-
-    @XmlElementWrapper(name = "schemasNotPermitted")
-    @XmlElement(name = "schema")
-    @JsonProperty("schemasNotPermitted")
-    public List<String> getSchemasNotPermitted() {
-        return schemasNotPermitted;
-    }
-
-    @XmlElementWrapper(name = "suffixesNotPermitted")
-    @XmlElement(name = "suffix")
-    @JsonProperty("suffixesNotPermitted")
-    public List<String> getSuffixesNotPermitted() {
-        return suffixesNotPermitted;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        return EqualsBuilder.reflectionEquals(this, obj);
-    }
-
-    @Override
-    public int hashCode() {
-        return HashCodeBuilder.reflectionHashCode(this);
-    }
-
-    @Override
-    public String toString() {
-        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/AccountPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AccountPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AccountPolicySpec.java
deleted file mode 100644
index 47a60e8..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AccountPolicySpec.java
+++ /dev/null
@@ -1,121 +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.common.lib.types;
-
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType
-public class AccountPolicySpec extends AbstractPolicySpec {
-
-    private static final long serialVersionUID = 3259256974414758406L;
-
-    /**
-     * Minimum length.
-     */
-    private int maxLength;
-
-    /**
-     * Maximum length.
-     */
-    private int minLength;
-
-    /**
-     * Pattern (regular expression) that must match.
-     */
-    private String pattern;
-
-    /**
-     * Specify if one or more lowercase characters are permitted.
-     */
-    private boolean allUpperCase;
-
-    /**
-     * Specify if one or more uppercase characters are permitted.
-     */
-    private boolean allLowerCase;
-
-    /**
-     * Specify if, when reached the maximum allowed number of subsequent login failures, user shall be suspended.
-     */
-    private boolean propagateSuspension;
-
-    /**
-     * Maximum number of (failing) authentication attempts.
-     * 0 disabled; &gt;0 enabled.
-     * If the number of subsequent failed logins will be greater then this value
-     * the account will be suspended (lock-out).
-     */
-    private int maxAuthenticationAttempts;
-
-    public boolean isAllLowerCase() {
-        return allLowerCase;
-    }
-
-    public void setAllLowerCase(final boolean allLowerCase) {
-        this.allLowerCase = allLowerCase;
-    }
-
-    public boolean isAllUpperCase() {
-        return allUpperCase;
-    }
-
-    public void setAllUpperCase(final boolean allUpperCase) {
-        this.allUpperCase = allUpperCase;
-    }
-
-    public int getMaxLength() {
-        return maxLength;
-    }
-
-    public void setMaxLength(final int maxLength) {
-        this.maxLength = maxLength;
-    }
-
-    public int getMinLength() {
-        return minLength;
-    }
-
-    public void setMinLength(final int minLength) {
-        this.minLength = minLength;
-    }
-
-    public String getPattern() {
-        return pattern;
-    }
-
-    public void setPattern(final String pattern) {
-        this.pattern = pattern;
-    }
-
-    public boolean isPropagateSuspension() {
-        return propagateSuspension;
-    }
-
-    public void setPropagateSuspension(final boolean propagateSuspension) {
-        this.propagateSuspension = propagateSuspension;
-    }
-
-    public int getMaxAuthenticationAttempts() {
-        return maxAuthenticationAttempts;
-    }
-
-    public void setMaxAuthenticationAttempts(final int maxAuthenticationAttempts) {
-        this.maxAuthenticationAttempts = maxAuthenticationAttempts;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordPolicySpec.java
deleted file mode 100644
index 175a1ef..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordPolicySpec.java
+++ /dev/null
@@ -1,300 +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.common.lib.types;
-
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType
-public class PasswordPolicySpec extends AbstractPolicySpec {
-
-    private static final long serialVersionUID = -7988778083915548547L;
-
-    /**
-     * History length.
-     */
-    private int historyLength;
-
-    /**
-     * Minimum length.
-     */
-    private int maxLength;
-
-    /**
-     * Maximum length.
-     */
-    private int minLength;
-
-    /**
-     * Specify if one or more non alphanumeric characters are required.
-     */
-    private boolean nonAlphanumericRequired;
-
-    /**
-     * Specify if one or more alphanumeric characters are required.
-     */
-    private boolean alphanumericRequired;
-
-    /**
-     * Specify if one or more digits are required.
-     */
-    private boolean digitRequired;
-
-    /**
-     * Specify if one or more lowercase alphabetic characters are required.
-     */
-    private boolean lowercaseRequired;
-
-    /**
-     * Specify if one or more uppercase alphabetic characters are required.
-     */
-    private boolean uppercaseRequired;
-
-    /**
-     * Specify if must start with a digit.
-     */
-    private boolean mustStartWithDigit;
-
-    /**
-     * Specify if mustn't start with a digit.
-     */
-    private boolean mustntStartWithDigit;
-
-    /**
-     * Specify if must end with a digit.
-     */
-    private boolean mustEndWithDigit;
-
-    /**
-     * Specify if mustn't end with a digit.
-     */
-    private boolean mustntEndWithDigit;
-
-    /**
-     * Specify if must start with a non alphanumeric character.
-     */
-    private boolean mustStartWithNonAlpha;
-
-    /**
-     * Specify if must start with a alphanumeric character.
-     */
-    private boolean mustStartWithAlpha;
-
-    /**
-     * Specify if mustn't start with a non alphanumeric character.
-     */
-    private boolean mustntStartWithNonAlpha;
-
-    /**
-     * Specify if mustn't start with a alphanumeric character.
-     */
-    private boolean mustntStartWithAlpha;
-
-    /**
-     * Specify if must end with a non alphanumeric character.
-     */
-    private boolean mustEndWithNonAlpha;
-
-    /**
-     * Specify if must end with a alphanumeric character.
-     */
-    private boolean mustEndWithAlpha;
-
-    /**
-     * Specify if mustn't end with a non alphanumeric character.
-     */
-    private boolean mustntEndWithNonAlpha;
-
-    /**
-     * Specify if mustn't end with a alphanumeric character.
-     */
-    private boolean mustntEndWithAlpha;
-
-    /**
-     * Specify if password shall not be stored internally.
-     */
-    private boolean allowNullPassword;
-
-    public boolean isDigitRequired() {
-        return digitRequired;
-    }
-
-    public void setDigitRequired(final boolean digitRequired) {
-        this.digitRequired = digitRequired;
-    }
-
-    public boolean isLowercaseRequired() {
-        return lowercaseRequired;
-    }
-
-    public void setLowercaseRequired(final boolean lowercaseRequired) {
-        this.lowercaseRequired = lowercaseRequired;
-    }
-
-    public int getMaxLength() {
-        return maxLength;
-    }
-
-    public void setMaxLength(final int maxLength) {
-        this.maxLength = maxLength;
-    }
-
-    public int getMinLength() {
-        return minLength;
-    }
-
-    public void setMinLength(final int minLength) {
-        this.minLength = minLength;
-    }
-
-    public boolean isMustEndWithDigit() {
-        return mustEndWithDigit;
-    }
-
-    public void setMustEndWithDigit(final boolean mustEndWithDigit) {
-        this.mustEndWithDigit = mustEndWithDigit;
-    }
-
-    public boolean isMustEndWithNonAlpha() {
-        return mustEndWithNonAlpha;
-    }
-
-    public void setMustEndWithNonAlpha(final boolean mustEndWithNonAlpha) {
-        this.mustEndWithNonAlpha = mustEndWithNonAlpha;
-    }
-
-    public boolean isMustStartWithDigit() {
-        return mustStartWithDigit;
-    }
-
-    public void setMustStartWithDigit(final boolean mustStartWithDigit) {
-        this.mustStartWithDigit = mustStartWithDigit;
-    }
-
-    public boolean isMustStartWithNonAlpha() {
-        return mustStartWithNonAlpha;
-    }
-
-    public void setMustStartWithNonAlpha(final boolean mustStartWithNonAlpha) {
-        this.mustStartWithNonAlpha = mustStartWithNonAlpha;
-    }
-
-    public boolean isMustntEndWithDigit() {
-        return mustntEndWithDigit;
-    }
-
-    public void setMustntEndWithDigit(final boolean mustntEndWithDigit) {
-        this.mustntEndWithDigit = mustntEndWithDigit;
-    }
-
-    public boolean isMustntEndWithNonAlpha() {
-        return mustntEndWithNonAlpha;
-    }
-
-    public void setMustntEndWithNonAlpha(final boolean mustntEndWithNonAlpha) {
-        this.mustntEndWithNonAlpha = mustntEndWithNonAlpha;
-    }
-
-    public boolean isMustntStartWithDigit() {
-        return mustntStartWithDigit;
-    }
-
-    public void setMustntStartWithDigit(final boolean mustntStartWithDigit) {
-        this.mustntStartWithDigit = mustntStartWithDigit;
-    }
-
-    public boolean isMustntStartWithNonAlpha() {
-        return mustntStartWithNonAlpha;
-    }
-
-    public void setMustntStartWithNonAlpha(final boolean mustntStartWithNonAlpha) {
-        this.mustntStartWithNonAlpha = mustntStartWithNonAlpha;
-    }
-
-    public boolean isNonAlphanumericRequired() {
-        return nonAlphanumericRequired;
-    }
-
-    public void setNonAlphanumericRequired(final boolean nonAlphanumericRequired) {
-        this.nonAlphanumericRequired = nonAlphanumericRequired;
-    }
-
-    public boolean isUppercaseRequired() {
-        return uppercaseRequired;
-    }
-
-    public void setUppercaseRequired(final boolean uppercaseRequired) {
-        this.uppercaseRequired = uppercaseRequired;
-    }
-
-    public boolean isAlphanumericRequired() {
-        return alphanumericRequired;
-    }
-
-    public void setAlphanumericRequired(final boolean alphanumericRequired) {
-        this.alphanumericRequired = alphanumericRequired;
-    }
-
-    public boolean isMustEndWithAlpha() {
-        return mustEndWithAlpha;
-    }
-
-    public void setMustEndWithAlpha(final boolean mustEndWithAlpha) {
-        this.mustEndWithAlpha = mustEndWithAlpha;
-    }
-
-    public boolean isMustStartWithAlpha() {
-        return mustStartWithAlpha;
-    }
-
-    public void setMustStartWithAlpha(final boolean mustStartWithAlpha) {
-        this.mustStartWithAlpha = mustStartWithAlpha;
-    }
-
-    public boolean isMustntEndWithAlpha() {
-        return mustntEndWithAlpha;
-    }
-
-    public void setMustntEndWithAlpha(final boolean mustntEndWithAlpha) {
-        this.mustntEndWithAlpha = mustntEndWithAlpha;
-    }
-
-    public boolean isMustntStartWithAlpha() {
-        return mustntStartWithAlpha;
-    }
-
-    public void setMustntStartWithAlpha(final boolean mustntStartWithAlpha) {
-        this.mustntStartWithAlpha = mustntStartWithAlpha;
-    }
-
-    public int getHistoryLength() {
-        return historyLength;
-    }
-
-    public void setHistoryLength(final int historyLength) {
-        this.historyLength = historyLength;
-    }
-
-    public boolean isAllowNullPassword() {
-        return allowNullPassword;
-    }
-
-    public void setAllowNullPassword(final boolean allowNullPassword) {
-        this.allowNullPassword = allowNullPassword;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
deleted file mode 100644
index 7f1c11e..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ /dev/null
@@ -1,43 +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.common.lib.types;
-
-import javax.xml.bind.annotation.XmlEnum;
-
-@XmlEnum
-public enum PolicyType {
-
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during synchronization.
-     */
-    SYNC,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
deleted file mode 100644
index 0bbea85..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
+++ /dev/null
@@ -1,28 +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.common.lib.types;
-
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType
-public class PushPolicySpec {
-
-    private static final long serialVersionUID = 3641030189482617497L;
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
deleted file mode 100644
index 7bdaea0..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
+++ /dev/null
@@ -1,62 +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.common.lib.types;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.HashMap;
-import java.util.Map;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
-
-@XmlType
-public class SyncPolicySpec {
-
-    private static final long serialVersionUID = -3144027171719498127L;
-
-    private ConflictResolutionAction conflictResolutionAction;
-
-    /**
-     * Associates anyTypeKey to either:
-     * <ol>
-     * <li>Java class name, implementing {@code SyncCorrelationRule}</li>
-     * <li>JSON array containing plain schema names - this will be used to feed
-     * {@code PlainAttrsSyncCorrelationRule}</li>
-     * </ol>
-     */
-    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
-    @JsonIgnore
-    private final Map<String, String> correlationRules = new HashMap<>();
-
-    public ConflictResolutionAction getConflictResolutionAction() {
-        return conflictResolutionAction == null
-                ? ConflictResolutionAction.IGNORE
-                : conflictResolutionAction;
-    }
-
-    public void setConflictResolutionAction(final ConflictResolutionAction conflictResolutionAction) {
-        this.conflictResolutionAction = conflictResolutionAction;
-    }
-
-    @JsonProperty
-    public Map<String, String> getCorrelationRules() {
-        return correlationRules;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PolicyService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PolicyService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PolicyService.java
index 980da9f..55b8747 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PolicyService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PolicyService.java
@@ -34,7 +34,7 @@ import javax.ws.rs.core.Response;
 import org.apache.cxf.jaxrs.model.wadl.Description;
 import org.apache.cxf.jaxrs.model.wadl.Descriptions;
 import org.apache.cxf.jaxrs.model.wadl.DocTarget;
-import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 
 /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
index 17c091d..44863ba 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
@@ -42,7 +42,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.beans.ListQuery;
 
 /**
@@ -52,16 +51,6 @@ import org.apache.syncope.common.rest.api.beans.ListQuery;
 public interface ReportService extends JAXRSService {
 
     /**
-     * Returns a list of available classes for reportlet configuration.
-     *
-     * @return list of available classes for reportlet configuration
-     */
-    @GET
-    @Path("reportletConfClasses")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    List<ReportletConfClass> getReportletConfClasses();
-
-    /**
      * Returns report with matching key.
      *
      * @param key key of report to be read

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
index 80409aa..e37dc28 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
@@ -24,18 +24,18 @@ import java.util.List;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.ArrayUtils;
-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.Entitlement;
 import org.apache.syncope.common.lib.types.PolicyType;
 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.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.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.provisioning.api.data.PolicyDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
index d8611ad..3780d30 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
@@ -24,10 +24,8 @@ import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.zip.ZipInputStream;
 import org.apache.cocoon.optional.pipeline.components.sax.fop.FopSerializer;
 import org.apache.cocoon.pipeline.NonCachingPipeline;
@@ -37,13 +35,10 @@ import org.apache.cocoon.sax.component.XMLGenerator;
 import org.apache.cocoon.sax.component.XMLSerializer;
 import org.apache.cocoon.sax.component.XSLTTransformer;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.IteratorUtils;
-import org.apache.commons.collections4.PredicateUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -58,10 +53,7 @@ import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportExec;
 import org.apache.syncope.core.provisioning.api.data.ReportDataBinder;
 import org.apache.syncope.core.provisioning.api.job.JobNamer;
-import org.apache.syncope.core.logic.init.ImplementationClassNamesLoader;
 import org.apache.syncope.core.provisioning.api.job.JobInstanceLoader;
-import org.apache.syncope.core.logic.report.Reportlet;
-import org.apache.syncope.core.logic.report.ReportletConfClass;
 import org.apache.syncope.core.logic.report.TextSerializer;
 import org.apache.syncope.common.lib.to.AbstractExecTO;
 import org.apache.syncope.common.lib.types.Entitlement;
@@ -74,7 +66,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.ClassUtils;
 
 @Component
 public class ReportLogic extends AbstractJobLogic<ReportTO> {
@@ -94,9 +85,6 @@ public class ReportLogic extends AbstractJobLogic<ReportTO> {
     @Autowired
     private EntityFactory entityFactory;
 
-    @Autowired
-    private ImplementationClassNamesLoader classNamesLoader;
-
     @PreAuthorize("hasRole('" + Entitlement.REPORT_CREATE + "')")
     public ReportTO create(final ReportTO reportTO) {
         Report report = entityFactory.newEntity(Report.class);
@@ -156,69 +144,6 @@ public class ReportLogic extends AbstractJobLogic<ReportTO> {
                 }, new ArrayList<ReportTO>());
     }
 
-    private Class<? extends ReportletConf> getReportletConfClass(final Class<Reportlet> reportletClass) {
-        Class<? extends ReportletConf> result = null;
-
-        ReportletConfClass annotation = reportletClass.getAnnotation(ReportletConfClass.class);
-        if (annotation != null) {
-            result = annotation.value();
-        }
-
-        return result;
-    }
-
-    @SuppressWarnings({ "rawtypes" })
-    private Set<Class<Reportlet>> getAllReportletClasses() {
-        return CollectionUtils.collect(IteratorUtils.filteredIterator(
-                classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.REPORTLET).iterator(),
-                PredicateUtils.notNullPredicate()),
-                new Transformer<String, Class<Reportlet>>() {
-
-                    @SuppressWarnings("unchecked")
-                    @Override
-                    public Class<Reportlet> transform(final String className) {
-                        Class<Reportlet> result = null;
-                        try {
-                            Class reportletClass = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
-                            result = reportletClass;
-                        } catch (ClassNotFoundException e) {
-                            LOG.warn("Could not load class {}", className);
-                        } catch (LinkageError e) {
-                            LOG.warn("Could not link class {}", className);
-                        }
-
-                        return result;
-                    }
-                }, new HashSet<Class<Reportlet>>());
-    }
-
-    @PreAuthorize("hasRole('" + Entitlement.REPORT_LIST + "')")
-    @SuppressWarnings({ "rawtypes" })
-    public Set<String> getReportletConfClasses() {
-        return CollectionUtils.collect(IteratorUtils.filteredIterator(getAllReportletClasses().iterator(),
-                PredicateUtils.notNullPredicate()),
-                new Transformer<Class<Reportlet>, String>() {
-
-                    @Override
-                    public String transform(final Class<Reportlet> reportletClass) {
-                        Class<? extends ReportletConf> reportletConfClass = getReportletConfClass(reportletClass);
-                        return reportletConfClass == null ? null : reportletConfClass.getName();
-                    }
-                }, new HashSet<String>());
-    }
-
-    public Class<Reportlet> findReportletClassHavingConfClass(final Class<? extends ReportletConf> reportletConfClass) {
-        Class<Reportlet> result = null;
-        for (Class<Reportlet> reportletClass : getAllReportletClasses()) {
-            Class<? extends ReportletConf> found = getReportletConfClass(reportletClass);
-            if (found != null && found.equals(reportletConfClass)) {
-                result = reportletClass;
-            }
-        }
-
-        return result;
-    }
-
     @PreAuthorize("hasRole('" + Entitlement.REPORT_READ + "')")
     public ReportTO read(final Long reportKey) {
         Report report = reportDAO.find(reportKey);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index d6432e2..eb0c1ad 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import javax.annotation.Resource;
 import org.apache.syncope.common.lib.to.SyncopeTO;
 import org.apache.syncope.core.logic.init.ImplementationClassNamesLoader;
+import org.apache.syncope.core.misc.security.PasswordGenerator;
 import org.apache.syncope.core.misc.spring.ResourceWithFallbackLoader;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
@@ -83,6 +84,9 @@ public class SyncopeLogic extends AbstractLogic<SyncopeTO> {
     private VirAttrCache virAttrCache;
 
     @Autowired
+    private PasswordGenerator passwordGenerator;
+
+    @Autowired
     private ImplementationClassNamesLoader classNamesLoader;
 
     @Resource(name = "velocityResourceLoader")
@@ -129,8 +133,11 @@ public class SyncopeLogic extends AbstractLogic<SyncopeTO> {
         syncopeTO.setUserProvisioningManager(uProvisioningManager.getClass().getName());
         syncopeTO.setGroupProvisioningManager(gProvisioningManager.getClass().getName());
         syncopeTO.setVirAttrCache(virAttrCache.getClass().getName());
+        syncopeTO.setPasswordGenerator(passwordGenerator.getClass().getName());
 
         syncopeTO.getReportlets().addAll(classNamesLoader.getClassNames(Type.REPORTLET));
+        syncopeTO.getAccountRules().addAll(classNamesLoader.getClassNames(Type.ACCOUNT_RULE));
+        syncopeTO.getPasswordRules().addAll(classNamesLoader.getClassNames(Type.PASSWORD_RULE));
         syncopeTO.getTaskJobs().addAll(classNamesLoader.getClassNames(Type.TASKJOBDELEGATE));
         syncopeTO.getPropagationActions().addAll(classNamesLoader.getClassNames(Type.PROPAGATION_ACTIONS));
         syncopeTO.getSyncActions().addAll(classNamesLoader.getClassNames(Type.SYNC_ACTIONS));

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java
index 1b53e5c..7bc842e 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java
@@ -32,6 +32,8 @@ import org.apache.syncope.core.provisioning.api.sync.SyncCorrelationRule;
 import org.apache.syncope.core.logic.report.Reportlet;
 import org.apache.syncope.core.persistence.api.SyncopeLoader;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
+import org.apache.syncope.core.persistence.api.dao.AccountRule;
+import org.apache.syncope.core.persistence.api.dao.PasswordRule;
 import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
 import org.apache.syncope.core.provisioning.java.sync.PushJobDelegate;
 import org.apache.syncope.core.provisioning.java.sync.SyncJobDelegate;
@@ -52,6 +54,8 @@ public class ImplementationClassNamesLoader implements SyncopeLoader {
     public enum Type {
 
         REPORTLET,
+        ACCOUNT_RULE,
+        PASSWORD_RULE,
         TASKJOBDELEGATE,
         PROPAGATION_ACTIONS,
         SYNC_ACTIONS,
@@ -80,6 +84,8 @@ public class ImplementationClassNamesLoader implements SyncopeLoader {
 
         ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
         scanner.addIncludeFilter(new AssignableTypeFilter(Reportlet.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(AccountRule.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRule.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(SchedTaskJobDelegate.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(SyncActions.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PushActions.class));
@@ -99,6 +105,13 @@ public class ImplementationClassNamesLoader implements SyncopeLoader {
                     classNames.get(Type.REPORTLET).add(clazz.getName());
                 }
 
+                if (AccountRule.class.isAssignableFrom(clazz) && !isAbsractClazz) {
+                    classNames.get(Type.ACCOUNT_RULE).add(clazz.getName());
+                }
+                if (PasswordRule.class.isAssignableFrom(clazz) && !isAbsractClazz) {
+                    classNames.get(Type.PASSWORD_RULE).add(clazz.getName());
+                }
+
                 if (SchedTaskJobDelegate.class.isAssignableFrom(clazz) && !isAbsractClazz
                         && !SyncJobDelegate.class.isAssignableFrom(clazz)
                         && !PushJobDelegate.class.isAssignableFrom(clazz)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java
index 8c1e272..482ad0e 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.logic.report;
 
-import org.apache.syncope.common.lib.report.AbstractReportletConf;
+import org.apache.syncope.common.lib.report.ReportletConf;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,26 +26,15 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
 
-public abstract class AbstractReportlet<T extends AbstractReportletConf> implements Reportlet<T> {
+public abstract class AbstractReportlet implements Reportlet {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractReportlet.class);
 
-    protected T conf;
-
-    public T getConf() {
-        return conf;
-    }
-
-    @Override
-    public void setConf(final T conf) {
-        this.conf = conf;
-    }
-
-    protected abstract void doExtract(ContentHandler handler) throws SAXException;
+    protected abstract void doExtract(ReportletConf conf, ContentHandler handler) throws SAXException;
 
     @Override
     @Transactional(readOnly = true)
-    public void extract(final ContentHandler handler) throws SAXException {
+    public void extract(final ReportletConf conf, final ContentHandler handler) throws SAXException {
         if (conf == null) {
             throw new ReportException(new IllegalArgumentException("No configuration provided"));
         }
@@ -55,7 +44,7 @@ public abstract class AbstractReportlet<T extends AbstractReportletConf> impleme
         atts.addAttribute("", "", ReportXMLConst.ATTR_CLASS, ReportXMLConst.XSD_STRING, getClass().getName());
         handler.startElement("", "", ReportXMLConst.ELEMENT_REPORTLET, atts);
 
-        doExtract(handler);
+        doExtract(conf, handler);
 
         handler.endElement("", "", ReportXMLConst.ELEMENT_REPORTLET);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
index 5b89421..c5e6642 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/GroupReportlet.java
@@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.GroupReportletConf;
 import org.apache.syncope.common.lib.report.GroupReportletConf.Feature;
+import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
@@ -43,7 +44,7 @@ import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
 
 @ReportletConfClass(GroupReportletConf.class)
-public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
+public class GroupReportlet extends AbstractReportlet {
 
     private static final int PAGE_SIZE = 10;
 
@@ -56,6 +57,8 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     @Autowired
     private GroupDataBinder groupDataBinder;
 
+    private GroupReportletConf conf;
+
     private List<Group> getPagedGroups(final int page) {
         List<Group> result;
 
@@ -296,7 +299,13 @@ public class GroupReportlet extends AbstractReportlet<GroupReportletConf> {
     }
 
     @Override
-    protected void doExtract(final ContentHandler handler) throws SAXException {
+    protected void doExtract(final ReportletConf conf, final ContentHandler handler) throws SAXException {
+        if (conf instanceof GroupReportletConf) {
+            this.conf = GroupReportletConf.class.cast(conf);
+        } else {
+            throw new ReportException(new IllegalArgumentException("Invalid configuration provided"));
+        }
+
         doExtractConf(handler);
         for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
             doExtract(handler, getPagedGroups(i));


[11/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

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
index f7a8def..d790568 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
@@ -20,7 +20,10 @@ package org.apache.syncope.core.logic.report;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.zip.Deflater;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -30,10 +33,10 @@ import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.types.ReportExecStatus;
-import org.apache.syncope.core.logic.ReportLogic;
 import org.apache.syncope.core.misc.ExceptionUtils2;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
@@ -45,9 +48,13 @@ import org.quartz.JobExecutionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 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.Component;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ClassUtils;
 import org.xml.sax.helpers.AttributesImpl;
 
 @Component
@@ -55,6 +62,32 @@ public class ReportJobDelegate {
 
     private static final Logger LOG = LoggerFactory.getLogger(ReportJobDelegate.class);
 
+    private static final Map<Class<? extends ReportletConf>, Class<Reportlet>> REPORTLET_CLASSES = new HashMap<>();
+
+    static {
+        initReportletClasses();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void initReportletClasses() {
+        ClassPathScanningCandidateComponentProvider scanner =
+                new ClassPathScanningCandidateComponentProvider(false);
+        scanner.addIncludeFilter(new AssignableTypeFilter(Reportlet.class));
+
+        for (BeanDefinition bd : scanner.findCandidateComponents(StringUtils.EMPTY)) {
+            Class<?> clazz = ClassUtils.resolveClassName(
+                    bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
+            boolean isAbstract = Modifier.isAbstract(clazz.getModifiers());
+
+            if (Reportlet.class.isAssignableFrom(clazz) && !isAbstract) {
+                ReportletConfClass annotation = clazz.getAnnotation(ReportletConfClass.class);
+                if (annotation != null) {
+                    REPORTLET_CLASSES.put(annotation.value(), (Class<Reportlet>) clazz);
+                }
+            }
+        }
+    }
+
     /**
      * Report DAO.
      */
@@ -70,9 +103,6 @@ public class ReportJobDelegate {
     @Autowired
     private EntityFactory entityFactory;
 
-    @Autowired
-    private ReportLogic dataBinder;
-
     @Transactional
     public void execute(final Long reportKey) throws JobExecutionException {
         Report report = reportDAO.find(reportKey);
@@ -126,18 +156,25 @@ public class ReportJobDelegate {
 
             // iterate over reportlet instances defined for this report
             for (ReportletConf reportletConf : report.getReportletConfs()) {
-                Class<Reportlet> reportletClass =
-                        dataBinder.findReportletClassHavingConfClass(reportletConf.getClass());
-                if (reportletClass != null) {
-                    @SuppressWarnings("unchecked")
-                    Reportlet<ReportletConf> autowired =
-                            (Reportlet<ReportletConf>) ApplicationContextProvider.getBeanFactory().
-                            createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
-                    autowired.setConf(reportletConf);
+                Class<Reportlet> reportletClass = REPORTLET_CLASSES.get(reportletConf.getClass());
+                if (reportletClass == null) {
+                    LOG.warn("Could not find matching reportlet for {}", reportletConf.getClass());
+                } else {
+                    // fetch (or create) reportlet
+                    Reportlet reportlet;
+                    if (ApplicationContextProvider.getBeanFactory().containsSingleton(reportletClass.getName())) {
+                        reportlet = (Reportlet) ApplicationContextProvider.getBeanFactory().
+                                getSingleton(reportletClass.getName());
+                    } else {
+                        reportlet = (Reportlet) ApplicationContextProvider.getBeanFactory().
+                                createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                        ApplicationContextProvider.getBeanFactory().
+                                registerSingleton(reportletClass.getName(), reportlet);
+                    }
 
                     // invoke reportlet
                     try {
-                        autowired.extract(handler);
+                        reportlet.extract(reportletConf, handler);
                     } catch (Exception e) {
                         execution.setStatus(ReportExecStatus.FAILURE);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/Reportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/Reportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/Reportlet.java
index 65fab56..66d00c4 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/Reportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/Reportlet.java
@@ -25,22 +25,16 @@ import org.xml.sax.SAXException;
 /**
  * Interface for all elements that can be embedded in a report.
  *
- * @see org.apache.syncope.core.persistence.beans.Report
+ * @see org.apache.syncope.core.persistence.api.entity.Report
  */
-public interface Reportlet<T extends ReportletConf> {
-
-    /**
-     * Set this reportlet configuration.
-     *
-     * @param conf configuration
-     */
-    void setConf(T conf);
+public interface Reportlet {
 
     /**
      * Actual data extraction for reporting.
      *
+     * @param conf configuration
      * @param handler SAX content handler for streaming result
      * @throws SAXException if there is any problem in SAX handling
      */
-    void extract(ContentHandler handler) throws SAXException;
+    void extract(ReportletConf conf, ContentHandler handler) throws SAXException;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
index 3e768e7..963d484 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.logic.report;
 
+import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.StaticReportletConf;
 import org.apache.syncope.core.misc.DataFormat;
 import org.springframework.util.StringUtils;
@@ -26,10 +27,11 @@ import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
 
 @ReportletConfClass(StaticReportletConf.class)
-public class StaticReportlet extends AbstractReportlet<StaticReportletConf> {
+public class StaticReportlet extends AbstractReportlet {
 
-    private void doExtractConf(final ContentHandler handler) throws SAXException {
+    private StaticReportletConf conf;
 
+    private void doExtractConf(final ContentHandler handler) throws SAXException {
         AttributesImpl atts = new AttributesImpl();
         handler.startElement("", "", "configurations", null);
         handler.startElement("", "", "staticAttributes", atts);
@@ -67,46 +69,52 @@ public class StaticReportlet extends AbstractReportlet<StaticReportletConf> {
     }
 
     @Override
-    public void doExtract(final ContentHandler handler) throws SAXException {
+    protected void doExtract(final ReportletConf conf, final ContentHandler handler) throws SAXException {
+        if (conf instanceof StaticReportletConf) {
+            this.conf = StaticReportletConf.class.cast(conf);
+        } else {
+            throw new ReportException(new IllegalArgumentException("Invalid configuration provided"));
+        }
+
         doExtractConf(handler);
 
-        if (StringUtils.hasText(conf.getStringField())) {
+        if (StringUtils.hasText(this.conf.getStringField())) {
             handler.startElement("", "", "string", null);
-            handler.characters(conf.getStringField().toCharArray(), 0, conf.getStringField().length());
+            handler.characters(this.conf.getStringField().toCharArray(), 0, this.conf.getStringField().length());
             handler.endElement("", "", "string");
         }
 
-        if (conf.getLongField() != null) {
+        if (this.conf.getLongField() != null) {
             handler.startElement("", "", "long", null);
-            String printed = String.valueOf(conf.getLongField());
+            String printed = String.valueOf(this.conf.getLongField());
             handler.characters(printed.toCharArray(), 0, printed.length());
             handler.endElement("", "", "long");
         }
 
-        if (conf.getDoubleField() != null) {
+        if (this.conf.getDoubleField() != null) {
             handler.startElement("", "", "double", null);
-            String printed = String.valueOf(conf.getDoubleField());
+            String printed = String.valueOf(this.conf.getDoubleField());
             handler.characters(printed.toCharArray(), 0, printed.length());
             handler.endElement("", "", "double");
         }
 
-        if (conf.getDateField() != null) {
+        if (this.conf.getDateField() != null) {
             handler.startElement("", "", "date", null);
-            String printed = DataFormat.format(conf.getDateField());
+            String printed = DataFormat.format(this.conf.getDateField());
             handler.characters(printed.toCharArray(), 0, printed.length());
             handler.endElement("", "", "date");
         }
 
-        if (conf.getTraceLevel() != null) {
+        if (this.conf.getTraceLevel() != null) {
             handler.startElement("", "", "enum", null);
-            String printed = conf.getTraceLevel().name();
+            String printed = this.conf.getTraceLevel().name();
             handler.characters(printed.toCharArray(), 0, printed.length());
             handler.endElement("", "", "enum");
         }
 
-        if (conf.getListField() != null && !conf.getListField().isEmpty()) {
+        if (this.conf.getListField() != null && !this.conf.getListField().isEmpty()) {
             handler.startElement("", "", "list", null);
-            for (String item : conf.getListField()) {
+            for (String item : this.conf.getListField()) {
                 if (StringUtils.hasText(item)) {
                     handler.startElement("", "", "string", null);
                     handler.characters(item.toCharArray(), 0, item.length());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index b626dd1..44ae0e0 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
 import org.apache.syncope.common.lib.to.AnyTO;
@@ -49,7 +50,7 @@ import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
 
 @ReportletConfClass(UserReportletConf.class)
-public class UserReportlet extends AbstractReportlet<UserReportletConf> {
+public class UserReportlet extends AbstractReportlet {
 
     private static final int PAGE_SIZE = 10;
 
@@ -68,6 +69,8 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     @Autowired
     private AnyObjectDataBinder anyObjectDataBinder;
 
+    private UserReportletConf conf;
+
     private List<User> getPagedUsers(final int page) {
         List<User> result;
 
@@ -370,7 +373,13 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     }
 
     @Override
-    protected void doExtract(final ContentHandler handler) throws SAXException {
+    protected void doExtract(final ReportletConf conf, final ContentHandler handler) throws SAXException {
+        if (conf instanceof UserReportletConf) {
+            this.conf = UserReportletConf.class.cast(conf);
+        } else {
+            throw new ReportException(new IllegalArgumentException("Invalid configuration provided"));
+        }
+
         doExtractConf(handler);
         for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
             doExtract(handler, getPagedUsers(i));

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
index de1bcfb..5ab5f44 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.core.misc;
 
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
-import org.apache.syncope.core.misc.security.PasswordGenerator;
+import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.misc.security.SecureRandomUtils;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -30,6 +29,7 @@ import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
@@ -41,7 +41,6 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
@@ -57,6 +56,7 @@ import org.apache.syncope.core.persistence.api.entity.task.SyncTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.misc.security.Encryptor;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
+import org.apache.syncope.core.misc.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -117,32 +117,28 @@ public class ConnObjectUtils {
         if (anyTO instanceof UserTO && StringUtils.isBlank(((UserTO) anyTO).getPassword())) {
             final UserTO userTO = (UserTO) anyTO;
 
-            List<PasswordPolicySpec> ppSpecs = new ArrayList<>();
+            List<PasswordRuleConf> ruleConfs = new ArrayList<>();
 
             Realm realm = realmDAO.find(userTO.getRealm());
             if (realm != null) {
                 for (Realm ancestor : realmDAO.findAncestors(realm)) {
-                    if (ancestor.getPasswordPolicy() != null
-                            && ancestor.getPasswordPolicy().getSpecification() != null) {
-
-                        ppSpecs.add(ancestor.getPasswordPolicy().getSpecification());
+                    if (ancestor.getPasswordPolicy() != null) {
+                        ruleConfs.addAll(ancestor.getPasswordPolicy().getRuleConfs());
                     }
                 }
             }
 
             for (String resName : userTO.getResources()) {
                 ExternalResource resource = resourceDAO.find(resName);
-                if (resource != null && resource.getPasswordPolicy() != null
-                        && resource.getPasswordPolicy().getSpecification() != null) {
-
-                    ppSpecs.add(resource.getPasswordPolicy().getSpecification());
+                if (resource != null && resource.getPasswordPolicy() != null) {
+                    ruleConfs.addAll(resource.getPasswordPolicy().getRuleConfs());
                 }
             }
 
             String password;
             try {
-                password = pwdGen.generate(ppSpecs);
-            } catch (InvalidPasswordPolicySpecException e) {
+                password = pwdGen.generate(ruleConfs);
+            } catch (InvalidPasswordRuleConf e) {
                 LOG.error("Could not generate policy-compliant random password for {}", userTO, e);
 
                 password = SecureRandomUtils.generateRandomPassword(16);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
index 95a16b1..5cb419d 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
@@ -18,8 +18,7 @@
  */
 package org.apache.syncope.core.misc;
 
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
-import org.apache.syncope.core.misc.security.PasswordGenerator;
+import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -58,6 +57,7 @@ import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
 import org.apache.syncope.core.misc.security.Encryptor;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
+import org.apache.syncope.core.misc.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
@@ -329,7 +329,7 @@ public final class MappingUtils {
                     } else if (provision.getResource().isRandomPwdIfNotProvided()) {
                         try {
                             passwordAttrValue = passwordGenerator.generate(user);
-                        } catch (InvalidPasswordPolicySpecException e) {
+                        } catch (InvalidPasswordRuleConf e) {
                             LOG.error("Could not generate policy-compliant random password for {}", user, e);
                         }
                     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
deleted file mode 100644
index 8b7a547..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.misc.policy;
-
-import java.util.regex.Pattern;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.springframework.stereotype.Component;
-
-@Component
-public class AccountPolicyEnforcer {
-
-    private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+");
-
-    public boolean enforce(final AccountPolicySpec policy, final User user) {
-        if (user.getUsername() == null) {
-            throw new AccountPolicyException("Invalid account");
-        }
-
-        // check min length
-        if (policy.getMinLength() > 0 && policy.getMinLength() > user.getUsername().length()) {
-            throw new AccountPolicyException("Username too short");
-        }
-
-        // check max length
-        if (policy.getMaxLength() > 0 && policy.getMaxLength() < user.getUsername().length()) {
-            throw new AccountPolicyException("Username too long");
-        }
-
-        // check words not permitted
-        for (String word : policy.getWordsNotPermitted()) {
-            if (user.getUsername().contains(word)) {
-                throw new AccountPolicyException("Used word(s) not permitted");
-            }
-        }
-
-        // check case
-        if (policy.isAllUpperCase() && !user.getUsername().equals(user.getUsername().toUpperCase())) {
-            throw new AccountPolicyException("No lowercase characters permitted");
-        }
-        if (policy.isAllLowerCase() && !user.getUsername().equals(user.getUsername().toLowerCase())) {
-            throw new AccountPolicyException("No uppercase characters permitted");
-        }
-
-        // check pattern
-        Pattern pattern = (policy.getPattern() == null) ? DEFAULT_PATTERN : Pattern.compile(policy.getPattern());
-        if (!pattern.matcher(user.getUsername()).matches()) {
-            throw new AccountPolicyException("Username does not match pattern");
-        }
-
-        // check prefix
-        for (String prefix : policy.getPrefixesNotPermitted()) {
-            if (user.getUsername().startsWith(prefix)) {
-                throw new AccountPolicyException("Prefix not permitted");
-            }
-        }
-
-        // check suffix
-        for (String suffix : policy.getSuffixesNotPermitted()) {
-            if (user.getUsername().endsWith(suffix)) {
-                throw new AccountPolicyException("Suffix not permitted");
-            }
-        }
-
-        // check for subsequent failed logins
-        return (user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0
-                && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended());
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordPolicySpecException.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordPolicySpecException.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordPolicySpecException.java
deleted file mode 100644
index 7d50951..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordPolicySpecException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.misc.policy;
-
-/**
- * Raise when the merge of two or more PasswordPolicySpec leds to incompatible condition.
- *
- * @see org.apache.syncope.common.lib.types.PasswordPolicySpec
- */
-public class InvalidPasswordPolicySpecException extends Exception {
-
-    private static final long serialVersionUID = 4810651743226663580L;
-
-    public InvalidPasswordPolicySpecException(final String msg) {
-        super(msg);
-    }
-
-    public InvalidPasswordPolicySpecException(final String msg, final Exception e) {
-        super(msg, e);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
deleted file mode 100644
index c2af367..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.misc.policy;
-
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.springframework.stereotype.Component;
-
-@Component
-public class PasswordPolicyEnforcer {
-
-    public boolean enforce(final PasswordPolicySpec policy, final User user) {
-        String clearPassword = user.getClearPassword();
-        String password = user.getPassword();
-
-        if (password == null && !policy.isAllowNullPassword()) {
-            throw new PasswordPolicyException("Password mandatory");
-        }
-        
-        if (password != null && clearPassword != null) {
-            // check length
-            if (policy.getMinLength() > 0 && policy.getMinLength() > clearPassword.length()) {
-                throw new PasswordPolicyException("Password too short");
-            }
-
-            if (policy.getMaxLength() > 0 && policy.getMaxLength() < clearPassword.length()) {
-                throw new PasswordPolicyException("Password too long");
-            }
-
-            // check words not permitted
-            for (String word : policy.getWordsNotPermitted()) {
-                if (clearPassword.contains(word)) {
-                    throw new PasswordPolicyException("Used word(s) not permitted");
-                }
-            }
-
-            // check digits occurrence
-            if (policy.isDigitRequired() && !checkForDigit(clearPassword)) {
-                throw new PasswordPolicyException("Password must contain digit(s)");
-            }
-
-            // check lowercase alphabetic characters occurrence
-            if (policy.isLowercaseRequired() && !checkForLowercase(clearPassword)) {
-                throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
-            }
-
-            // check uppercase alphabetic characters occurrence
-            if (policy.isUppercaseRequired() && !checkForUppercase(clearPassword)) {
-                throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
-            }
-
-            // check prefix
-            for (String prefix : policy.getPrefixesNotPermitted()) {
-                if (clearPassword.startsWith(prefix)) {
-                    throw new PasswordPolicyException("Prefix not permitted");
-                }
-            }
-
-            // check suffix
-            for (String suffix : policy.getSuffixesNotPermitted()) {
-                if (clearPassword.endsWith(suffix)) {
-                    throw new PasswordPolicyException("Suffix not permitted");
-                }
-            }
-
-            // check digit first occurrence
-            if (policy.isMustStartWithDigit() && !checkForFirstDigit(clearPassword)) {
-                throw new PasswordPolicyException("Password must start with a digit");
-            }
-
-            if (policy.isMustntStartWithDigit() && checkForFirstDigit(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't start with a digit");
-            }
-
-            // check digit last occurrence
-            if (policy.isMustEndWithDigit() && !checkForLastDigit(clearPassword)) {
-                throw new PasswordPolicyException("Password must end with a digit");
-            }
-
-            if (policy.isMustntEndWithDigit() && checkForLastDigit(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't end with a digit");
-            }
-
-            // check alphanumeric characters occurence
-            if (policy.isAlphanumericRequired() && !checkForAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
-            }
-
-            // check non alphanumeric characters occurence
-            if (policy.isNonAlphanumericRequired() && !checkForNonAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
-            }
-
-            // check alphanumeric character first occurrence
-            if (policy.isMustStartWithAlpha() && !checkForFirstAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must start with an alphanumeric character");
-            }
-
-            if (policy.isMustntStartWithAlpha() && checkForFirstAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't start with an alphanumeric character");
-            }
-
-            // check alphanumeric character last occurrence
-            if (policy.isMustEndWithAlpha() && !checkForLastAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must end with an alphanumeric character");
-            }
-
-            if (policy.isMustntEndWithAlpha() && checkForLastAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't end with an alphanumeric character");
-            }
-
-            // check non alphanumeric character first occurrence
-            if (policy.isMustStartWithNonAlpha() && !checkForFirstNonAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
-            }
-
-            if (policy.isMustntStartWithNonAlpha() && checkForFirstNonAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't start with a non-alphanumeric character");
-            }
-
-            // check non alphanumeric character last occurrence
-            if (policy.isMustEndWithNonAlpha() && !checkForLastNonAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
-            }
-
-            if (policy.isMustntEndWithNonAlpha() && checkForLastNonAlphanumeric(clearPassword)) {
-                throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
-            }
-        }
-
-        return false;
-    }
-
-    private boolean checkForDigit(final String str) {
-        return PolicyPattern.DIGIT.matcher(str).matches();
-    }
-
-    private boolean checkForLowercase(final String str) {
-        return PolicyPattern.ALPHA_LOWERCASE.matcher(str).matches();
-    }
-
-    private boolean checkForUppercase(final String str) {
-        return PolicyPattern.ALPHA_UPPERCASE.matcher(str).matches();
-    }
-
-    private boolean checkForFirstDigit(final String str) {
-        return PolicyPattern.FIRST_DIGIT.matcher(str).matches();
-    }
-
-    private boolean checkForLastDigit(final String str) {
-        return PolicyPattern.LAST_DIGIT.matcher(str).matches();
-    }
-
-    private boolean checkForAlphanumeric(final String str) {
-        return PolicyPattern.ALPHANUMERIC.matcher(str).matches();
-    }
-
-    private boolean checkForFirstAlphanumeric(final String str) {
-        return PolicyPattern.FIRST_ALPHANUMERIC.matcher(str).matches();
-    }
-
-    private boolean checkForLastAlphanumeric(final String str) {
-        return PolicyPattern.LAST_ALPHANUMERIC.matcher(str).matches();
-    }
-
-    private boolean checkForNonAlphanumeric(final String str) {
-        return PolicyPattern.NON_ALPHANUMERIC.matcher(str).matches();
-    }
-
-    private boolean checkForFirstNonAlphanumeric(final String str) {
-        return PolicyPattern.FIRST_NON_ALPHANUMERIC.matcher(str).matches();
-    }
-
-    private boolean checkForLastNonAlphanumeric(final String str) {
-        return PolicyPattern.LAST_NON_ALPHANUMERIC.matcher(str).matches();
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
deleted file mode 100644
index 48cc981..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.misc.policy;
-
-import java.util.List;
-import org.apache.syncope.common.lib.types.AbstractPolicySpec;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
-import org.apache.syncope.core.persistence.api.entity.Policy;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Component;
-
-@Component
-public class PolicyEvaluator {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PolicyEvaluator.class);
-
-    @SuppressWarnings("unchecked")
-    public <T extends AbstractPolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) {
-        T result;
-        switch (policy.getType()) {
-            case PASSWORD:
-                PasswordPolicySpec ppSpec = ((PasswordPolicy) policy).getSpecification();
-                PasswordPolicySpec evaluatedPPSpec = new PasswordPolicySpec();
-
-                BeanUtils.copyProperties(ppSpec, evaluatedPPSpec, new String[] { "schemasNotPermitted" });
-
-                for (String schema : ppSpec.getSchemasNotPermitted()) {
-                    PlainAttr<?> attr = any.getPlainAttr(schema);
-                    if (attr != null) {
-                        List<String> values = attr.getValuesAsStrings();
-                        if (values != null && !values.isEmpty()) {
-                            evaluatedPPSpec.getWordsNotPermitted().add(values.get(0));
-                        }
-                    }
-                }
-
-                // Password history verification and update
-                if (!(any instanceof User)) {
-                    LOG.error("Cannot check previous passwords. instance is not user object: {}",
-                            any.getClass().getName());
-                    result = (T) evaluatedPPSpec;
-                    break;
-                }
-                User user = (User) any;
-                if (user.verifyPasswordHistory(user.getClearPassword(), ppSpec.getHistoryLength())) {
-                    evaluatedPPSpec.getWordsNotPermitted().add(user.getClearPassword());
-                }
-                result = (T) evaluatedPPSpec;
-                break;
-
-            case ACCOUNT:
-                AccountPolicySpec spec = ((AccountPolicy) policy).getSpecification();
-                AccountPolicySpec accountPolicy = new AccountPolicySpec();
-
-                BeanUtils.copyProperties(spec, accountPolicy, new String[] { "schemasNotPermitted" });
-
-                for (String schema : spec.getSchemasNotPermitted()) {
-                    PlainAttr<?> attr = any.getPlainAttr(schema);
-                    if (attr != null) {
-                        List<String> values = attr.getValuesAsStrings();
-                        if (values != null && !values.isEmpty()) {
-                            accountPolicy.getWordsNotPermitted().add(values.get(0));
-                        }
-                    }
-                }
-
-                result = (T) accountPolicy;
-                break;
-
-            default:
-                result = null;
-        }
-
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
index a1a1822..9652f73 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
@@ -88,81 +88,85 @@ public class DefaultPasswordGenerator implements PasswordGenerator {
     }
 
     private DefaultPasswordRuleConf merge(final List<DefaultPasswordRuleConf> defaultRuleConfs) {
-        DefaultPasswordRuleConf fpps = new DefaultPasswordRuleConf();
-        fpps.setMinLength(VERY_MIN_LENGTH);
-        fpps.setMaxLength(VERY_MAX_LENGTH);
+        DefaultPasswordRuleConf result = new DefaultPasswordRuleConf();
+        result.setMinLength(VERY_MIN_LENGTH);
+        result.setMaxLength(VERY_MAX_LENGTH);
 
         for (DefaultPasswordRuleConf ruleConf : defaultRuleConfs) {
-            if (ruleConf.getMinLength() > fpps.getMinLength()) {
-                fpps.setMinLength(ruleConf.getMinLength());
+            if (ruleConf.getMinLength() > result.getMinLength()) {
+                result.setMinLength(ruleConf.getMinLength());
             }
 
-            if ((ruleConf.getMaxLength() != 0) && ((ruleConf.getMaxLength() < fpps.getMaxLength()))) {
-                fpps.setMaxLength(ruleConf.getMaxLength());
+            if ((ruleConf.getMaxLength() != 0) && ((ruleConf.getMaxLength() < result.getMaxLength()))) {
+                result.setMaxLength(ruleConf.getMaxLength());
             }
-            fpps.getPrefixesNotPermitted().addAll(ruleConf.getPrefixesNotPermitted());
-            fpps.getSuffixesNotPermitted().addAll(ruleConf.getSuffixesNotPermitted());
+            result.getPrefixesNotPermitted().addAll(ruleConf.getPrefixesNotPermitted());
+            result.getSuffixesNotPermitted().addAll(ruleConf.getSuffixesNotPermitted());
 
-            if (!fpps.isNonAlphanumericRequired()) {
-                fpps.setNonAlphanumericRequired(ruleConf.isNonAlphanumericRequired());
+            if (!result.isNonAlphanumericRequired()) {
+                result.setNonAlphanumericRequired(ruleConf.isNonAlphanumericRequired());
             }
 
-            if (!fpps.isAlphanumericRequired()) {
-                fpps.setAlphanumericRequired(ruleConf.isAlphanumericRequired());
+            if (!result.isAlphanumericRequired()) {
+                result.setAlphanumericRequired(ruleConf.isAlphanumericRequired());
             }
-            if (!fpps.isDigitRequired()) {
-                fpps.setDigitRequired(ruleConf.isDigitRequired());
+            if (!result.isDigitRequired()) {
+                result.setDigitRequired(ruleConf.isDigitRequired());
             }
 
-            if (!fpps.isLowercaseRequired()) {
-                fpps.setLowercaseRequired(ruleConf.isLowercaseRequired());
+            if (!result.isLowercaseRequired()) {
+                result.setLowercaseRequired(ruleConf.isLowercaseRequired());
             }
-            if (!fpps.isUppercaseRequired()) {
-                fpps.setUppercaseRequired(ruleConf.isUppercaseRequired());
+            if (!result.isUppercaseRequired()) {
+                result.setUppercaseRequired(ruleConf.isUppercaseRequired());
             }
-            if (!fpps.isMustStartWithDigit()) {
-                fpps.setMustStartWithDigit(ruleConf.isMustStartWithDigit());
+            if (!result.isMustStartWithDigit()) {
+                result.setMustStartWithDigit(ruleConf.isMustStartWithDigit());
             }
-            if (!fpps.isMustntStartWithDigit()) {
-                fpps.setMustntStartWithDigit(ruleConf.isMustntStartWithDigit());
+            if (!result.isMustntStartWithDigit()) {
+                result.setMustntStartWithDigit(ruleConf.isMustntStartWithDigit());
             }
-            if (!fpps.isMustEndWithDigit()) {
-                fpps.setMustEndWithDigit(ruleConf.isMustEndWithDigit());
+            if (!result.isMustEndWithDigit()) {
+                result.setMustEndWithDigit(ruleConf.isMustEndWithDigit());
             }
-            if (fpps.isMustntEndWithDigit()) {
-                fpps.setMustntEndWithDigit(ruleConf.isMustntEndWithDigit());
+            if (result.isMustntEndWithDigit()) {
+                result.setMustntEndWithDigit(ruleConf.isMustntEndWithDigit());
             }
-            if (!fpps.isMustStartWithAlpha()) {
-                fpps.setMustStartWithAlpha(ruleConf.isMustStartWithAlpha());
+            if (!result.isMustStartWithAlpha()) {
+                result.setMustStartWithAlpha(ruleConf.isMustStartWithAlpha());
             }
-            if (!fpps.isMustntStartWithAlpha()) {
-                fpps.setMustntStartWithAlpha(ruleConf.isMustntStartWithAlpha());
+            if (!result.isMustntStartWithAlpha()) {
+                result.setMustntStartWithAlpha(ruleConf.isMustntStartWithAlpha());
             }
-            if (!fpps.isMustStartWithNonAlpha()) {
-                fpps.setMustStartWithNonAlpha(ruleConf.isMustStartWithNonAlpha());
+            if (!result.isMustStartWithNonAlpha()) {
+                result.setMustStartWithNonAlpha(ruleConf.isMustStartWithNonAlpha());
             }
-            if (!fpps.isMustntStartWithNonAlpha()) {
-                fpps.setMustntStartWithNonAlpha(ruleConf.isMustntStartWithNonAlpha());
+            if (!result.isMustntStartWithNonAlpha()) {
+                result.setMustntStartWithNonAlpha(ruleConf.isMustntStartWithNonAlpha());
             }
-            if (!fpps.isMustEndWithNonAlpha()) {
-                fpps.setMustEndWithNonAlpha(ruleConf.isMustEndWithNonAlpha());
+            if (!result.isMustEndWithNonAlpha()) {
+                result.setMustEndWithNonAlpha(ruleConf.isMustEndWithNonAlpha());
             }
-            if (!fpps.isMustntEndWithNonAlpha()) {
-                fpps.setMustntEndWithNonAlpha(ruleConf.isMustntEndWithNonAlpha());
+            if (!result.isMustntEndWithNonAlpha()) {
+                result.setMustntEndWithNonAlpha(ruleConf.isMustntEndWithNonAlpha());
             }
-            if (!fpps.isMustEndWithAlpha()) {
-                fpps.setMustEndWithAlpha(ruleConf.isMustEndWithAlpha());
+            if (!result.isMustEndWithAlpha()) {
+                result.setMustEndWithAlpha(ruleConf.isMustEndWithAlpha());
             }
-            if (!fpps.isMustntEndWithAlpha()) {
-                fpps.setMustntEndWithAlpha(ruleConf.isMustntEndWithAlpha());
+            if (!result.isMustntEndWithAlpha()) {
+                result.setMustntEndWithAlpha(ruleConf.isMustntEndWithAlpha());
+            }
+            if (!result.isUsernameAllowed()) {
+                result.setUsernameAllowed(ruleConf.isUsernameAllowed());
             }
         }
 
-        if (fpps.getMinLength() == 0) {
-            fpps.setMinLength(fpps.getMaxLength() < MIN_LENGTH_IF_ZERO ? fpps.getMaxLength() : MIN_LENGTH_IF_ZERO);
+        if (result.getMinLength() == 0) {
+            result.setMinLength(
+                    result.getMaxLength() < MIN_LENGTH_IF_ZERO ? result.getMaxLength() : MIN_LENGTH_IF_ZERO);
         }
 
-        return fpps;
+        return result;
     }
 
     private void check(final DefaultPasswordRuleConf defaultPasswordRuleConf)

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
index d5e2e14..936dae5 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
@@ -18,315 +18,15 @@
  */
 package org.apache.syncope.core.misc.security;
 
-import java.util.ArrayList;
 import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
-import org.apache.syncope.core.misc.policy.PolicyPattern;
-import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-/**
- * Generate random passwords according to given policies.
- * When no minimum and / or maximum length are specified, default values are set.
- *
- * @see org.apache.syncope.core.persistence.api.entity.PasswordPolicy
- */
-@Component
-public class PasswordGenerator {
-
-    private static final char[] SPECIAL_CHARS = { '!', '£', '%', '&', '(', ')', '?', '#', '$' };
-
-    private static final int VERY_MIN_LENGTH = 0;
-
-    private static final int VERY_MAX_LENGTH = 64;
-
-    private static final int MIN_LENGTH_IF_ZERO = 6;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private RealmDAO realmDAO;
-
-    public String generate(final List<PasswordPolicySpec> ppSpecs) throws InvalidPasswordPolicySpecException {
-        PasswordPolicySpec policySpec = merge(ppSpecs);
-
-        check(policySpec);
-
-        return generate(policySpec);
-    }
-
-    public String generate(final User user)
-            throws InvalidPasswordPolicySpecException {
-
-        List<PasswordPolicySpec> ppSpecs = new ArrayList<>();
-
-        for (Realm ancestor : realmDAO.findAncestors(user.getRealm())) {
-            if (ancestor.getPasswordPolicy() != null
-                    && ancestor.getPasswordPolicy().getSpecification() != null) {
-
-                ppSpecs.add(ancestor.getPasswordPolicy().getSpecification());
-            }
-        }
-
-        for (ExternalResource resource : userDAO.findAllResources(user)) {
-            if (resource.getPasswordPolicy() != null
-                    && resource.getPasswordPolicy().getSpecification() != null) {
-
-                ppSpecs.add(resource.getPasswordPolicy().getSpecification());
-            }
-        }
-
-        PasswordPolicySpec policySpec = merge(ppSpecs);
-        check(policySpec);
-        return generate(policySpec);
-    }
-
-    private PasswordPolicySpec merge(final List<PasswordPolicySpec> ppSpecs) {
-        PasswordPolicySpec fpps = new PasswordPolicySpec();
-        fpps.setMinLength(VERY_MIN_LENGTH);
-        fpps.setMaxLength(VERY_MAX_LENGTH);
-
-        for (PasswordPolicySpec policySpec : ppSpecs) {
-            if (policySpec.getMinLength() > fpps.getMinLength()) {
-                fpps.setMinLength(policySpec.getMinLength());
-            }
-
-            if ((policySpec.getMaxLength() != 0) && ((policySpec.getMaxLength() < fpps.getMaxLength()))) {
-                fpps.setMaxLength(policySpec.getMaxLength());
-            }
-            fpps.getPrefixesNotPermitted().addAll(policySpec.getPrefixesNotPermitted());
-            fpps.getSuffixesNotPermitted().addAll(policySpec.getSuffixesNotPermitted());
-
-            if (!fpps.isNonAlphanumericRequired()) {
-                fpps.setNonAlphanumericRequired(policySpec.isNonAlphanumericRequired());
-            }
-
-            if (!fpps.isAlphanumericRequired()) {
-                fpps.setAlphanumericRequired(policySpec.isAlphanumericRequired());
-            }
-            if (!fpps.isDigitRequired()) {
-                fpps.setDigitRequired(policySpec.isDigitRequired());
-            }
-
-            if (!fpps.isLowercaseRequired()) {
-                fpps.setLowercaseRequired(policySpec.isLowercaseRequired());
-            }
-            if (!fpps.isUppercaseRequired()) {
-                fpps.setUppercaseRequired(policySpec.isUppercaseRequired());
-            }
-            if (!fpps.isMustStartWithDigit()) {
-                fpps.setMustStartWithDigit(policySpec.isMustStartWithDigit());
-            }
-            if (!fpps.isMustntStartWithDigit()) {
-                fpps.setMustntStartWithDigit(policySpec.isMustntStartWithDigit());
-            }
-            if (!fpps.isMustEndWithDigit()) {
-                fpps.setMustEndWithDigit(policySpec.isMustEndWithDigit());
-            }
-            if (fpps.isMustntEndWithDigit()) {
-                fpps.setMustntEndWithDigit(policySpec.isMustntEndWithDigit());
-            }
-            if (!fpps.isMustStartWithAlpha()) {
-                fpps.setMustStartWithAlpha(policySpec.isMustStartWithAlpha());
-            }
-            if (!fpps.isMustntStartWithAlpha()) {
-                fpps.setMustntStartWithAlpha(policySpec.isMustntStartWithAlpha());
-            }
-            if (!fpps.isMustStartWithNonAlpha()) {
-                fpps.setMustStartWithNonAlpha(policySpec.isMustStartWithNonAlpha());
-            }
-            if (!fpps.isMustntStartWithNonAlpha()) {
-                fpps.setMustntStartWithNonAlpha(policySpec.isMustntStartWithNonAlpha());
-            }
-            if (!fpps.isMustEndWithNonAlpha()) {
-                fpps.setMustEndWithNonAlpha(policySpec.isMustEndWithNonAlpha());
-            }
-            if (!fpps.isMustntEndWithNonAlpha()) {
-                fpps.setMustntEndWithNonAlpha(policySpec.isMustntEndWithNonAlpha());
-            }
-            if (!fpps.isMustEndWithAlpha()) {
-                fpps.setMustEndWithAlpha(policySpec.isMustEndWithAlpha());
-            }
-            if (!fpps.isMustntEndWithAlpha()) {
-                fpps.setMustntEndWithAlpha(policySpec.isMustntEndWithAlpha());
-            }
-        }
-
-        if (fpps.getMinLength() == 0) {
-            fpps.setMinLength(fpps.getMaxLength() < MIN_LENGTH_IF_ZERO ? fpps.getMaxLength() : MIN_LENGTH_IF_ZERO);
-        }
-
-        return fpps;
-    }
-
-    private void check(final PasswordPolicySpec policySpec)
-            throws InvalidPasswordPolicySpecException {
-
-        if (policySpec.isMustEndWithAlpha() && policySpec.isMustntEndWithAlpha()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustEndWithAlpha and mustntEndWithAlpha are both true");
-        }
-        if (policySpec.isMustEndWithAlpha() && policySpec.isMustEndWithDigit()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustEndWithAlpha and mustEndWithDigit are both true");
-        }
-        if (policySpec.isMustEndWithDigit() && policySpec.isMustntEndWithDigit()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustEndWithDigit and mustntEndWithDigit are both true");
-        }
-        if (policySpec.isMustEndWithNonAlpha() && policySpec.isMustntEndWithNonAlpha()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustEndWithNonAlpha and mustntEndWithNonAlpha are both true");
-        }
-        if (policySpec.isMustStartWithAlpha() && policySpec.isMustntStartWithAlpha()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustStartWithAlpha and mustntStartWithAlpha are both true");
-        }
-        if (policySpec.isMustStartWithAlpha() && policySpec.isMustStartWithDigit()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustStartWithAlpha and mustStartWithDigit are both true");
-        }
-        if (policySpec.isMustStartWithDigit() && policySpec.isMustntStartWithDigit()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustStartWithDigit and mustntStartWithDigit are both true");
-        }
-        if (policySpec.isMustStartWithNonAlpha() && policySpec.isMustntStartWithNonAlpha()) {
-            throw new InvalidPasswordPolicySpecException(
-                    "mustStartWithNonAlpha and mustntStartWithNonAlpha are both true");
-        }
-        if (policySpec.getMinLength() > policySpec.getMaxLength()) {
-            throw new InvalidPasswordPolicySpecException("Minimun length (" + policySpec.getMinLength() + ")"
-                    + "is greater than maximum length (" + policySpec.getMaxLength() + ")");
-        }
-    }
-
-    private String generate(final PasswordPolicySpec policySpec) {
-        String[] generatedPassword = new String[policySpec.getMinLength()];
-
-        for (int i = 0; i < generatedPassword.length; i++) {
-            generatedPassword[i] = StringUtils.EMPTY;
-        }
-
-        checkStartChar(generatedPassword, policySpec);
-
-        checkEndChar(generatedPassword, policySpec);
-
-        checkRequired(generatedPassword, policySpec);
-
-        for (int firstEmptyChar = firstEmptyChar(generatedPassword);
-                firstEmptyChar < generatedPassword.length - 1; firstEmptyChar++) {
-
-            generatedPassword[firstEmptyChar] = SecureRandomUtils.generateRandomLetter();
-        }
-
-        checkPrefixAndSuffix(generatedPassword, policySpec);
-
-        return StringUtils.join(generatedPassword);
-    }
-
-    private void checkStartChar(final String[] generatedPassword, final PasswordPolicySpec policySpec) {
-        if (policySpec.isMustStartWithAlpha()) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
-        }
-        if (policySpec.isMustStartWithNonAlpha() || policySpec.isMustStartWithDigit()) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomNumber();
-        }
-        if (policySpec.isMustntStartWithAlpha()) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomNumber();
-        }
-        if (policySpec.isMustntStartWithDigit()) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
-        }
-        if (policySpec.isMustntStartWithNonAlpha()) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
-        }
-
-        if (StringUtils.EMPTY.equals(generatedPassword[0])) {
-            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
-        }
-    }
-
-    private void checkEndChar(final String[] generatedPassword, final PasswordPolicySpec policySpec) {
-        if (policySpec.isMustEndWithAlpha()) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
-        }
-        if (policySpec.isMustEndWithNonAlpha() || policySpec.isMustEndWithDigit()) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomNumber();
-        }
-
-        if (policySpec.isMustntEndWithAlpha()) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomNumber();
-        }
-        if (policySpec.isMustntEndWithDigit()) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
-        }
-        if (policySpec.isMustntEndWithNonAlpha()) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
-        }
-
-        if (StringUtils.EMPTY.equals(generatedPassword[policySpec.getMinLength() - 1])) {
-            generatedPassword[policySpec.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
-        }
-    }
-
-    private int firstEmptyChar(final String[] generatedPStrings) {
-        int index = 0;
-        while (!generatedPStrings[index].isEmpty()) {
-            index++;
-        }
-        return index;
-    }
-
-    private void checkRequired(final String[] generatedPassword, final PasswordPolicySpec policySpec) {
-        if (policySpec.isDigitRequired()
-                && !PolicyPattern.DIGIT.matcher(StringUtils.join(generatedPassword)).matches()) {
-
-            generatedPassword[firstEmptyChar(generatedPassword)] = SecureRandomUtils.generateRandomNumber();
-        }
-
-        if (policySpec.isUppercaseRequired()
-                && !PolicyPattern.ALPHA_UPPERCASE.matcher(StringUtils.join(generatedPassword)).matches()) {
-
-            generatedPassword[firstEmptyChar(generatedPassword)] =
-                    SecureRandomUtils.generateRandomLetter().toUpperCase();
-        }
-
-        if (policySpec.isLowercaseRequired()
-                && !PolicyPattern.ALPHA_LOWERCASE.matcher(StringUtils.join(generatedPassword)).matches()) {
-
-            generatedPassword[firstEmptyChar(generatedPassword)] =
-                    SecureRandomUtils.generateRandomLetter().toLowerCase();
-        }
-
-        if (policySpec.isNonAlphanumericRequired()
-                && !PolicyPattern.NON_ALPHANUMERIC.matcher(StringUtils.join(generatedPassword)).matches()) {
 
-            generatedPassword[firstEmptyChar(generatedPassword)] =
-                    SecureRandomUtils.generateRandomSpecialCharacter(SPECIAL_CHARS);
-        }
-    }
+public interface PasswordGenerator {
 
-    private void checkPrefixAndSuffix(final String[] generatedPassword, final PasswordPolicySpec policySpec) {
-        for (String prefix : policySpec.getPrefixesNotPermitted()) {
-            if (StringUtils.join(generatedPassword).startsWith(prefix)) {
-                checkStartChar(generatedPassword, policySpec);
-            }
-        }
+    String generate(User user) throws InvalidPasswordRuleConf;
 
-        for (String suffix : policySpec.getSuffixesNotPermitted()) {
-            if (StringUtils.join(generatedPassword).endsWith(suffix)) {
-                checkEndChar(generatedPassword, policySpec);
-            }
-        }
-    }
+    String generate(List<PasswordRuleConf> ruleConfs) throws InvalidPasswordRuleConf;
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/resources/security.properties
----------------------------------------------------------------------
diff --git a/core/misc/src/main/resources/security.properties b/core/misc/src/main/resources/security.properties
index a0557b5..73db510 100644
--- a/core/misc/src/main/resources/security.properties
+++ b/core/misc/src/main/resources/security.properties
@@ -29,3 +29,4 @@ digester.invertPositionOfPlainSaltInEncryptionResults=true
 digester.invertPositionOfSaltInMessageBeforeDigesting=true
 digester.useLenientSaltSizeCheck=true
 
+passwordGenerator=org.apache.syncope.core.misc.security.DefaultPasswordGenerator

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/main/resources/securityContext.xml
----------------------------------------------------------------------
diff --git a/core/misc/src/main/resources/securityContext.xml b/core/misc/src/main/resources/securityContext.xml
index 1022815..711e2f3 100644
--- a/core/misc/src/main/resources/securityContext.xml
+++ b/core/misc/src/main/resources/securityContext.xml
@@ -32,6 +32,7 @@ under the License.
     <constructor-arg value="${anonymousUser}"/>
   </bean>
   
+  <bean class="${passwordGenerator}"/>
   <bean class="org.apache.syncope.core.misc.spring.DefaultRolesPrefixPostProcessor"/>
   
   <security:global-method-security pre-post-annotations="enabled"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/misc/src/test/java/org/apache/syncope/core/misc/security/PasswordGeneratorTest.java
----------------------------------------------------------------------
diff --git a/core/misc/src/test/java/org/apache/syncope/core/misc/security/PasswordGeneratorTest.java b/core/misc/src/test/java/org/apache/syncope/core/misc/security/PasswordGeneratorTest.java
index e3e26e0..536fa60 100644
--- a/core/misc/src/test/java/org/apache/syncope/core/misc/security/PasswordGeneratorTest.java
+++ b/core/misc/src/test/java/org/apache/syncope/core/misc/security/PasswordGeneratorTest.java
@@ -25,114 +25,118 @@ import static org.junit.Assert.fail;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.core.misc.policy.InvalidPasswordPolicySpecException;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.misc.policy.PolicyPattern;
 import org.junit.Test;
 
 public class PasswordGeneratorTest {
 
-    private final PasswordGenerator passwordGenerator = new PasswordGenerator();
-
-    private PasswordPolicySpec createBasePasswordPolicySpec() {
-        PasswordPolicySpec basePasswordPolicySpec = new PasswordPolicySpec();
-        basePasswordPolicySpec.setAlphanumericRequired(false);
-        basePasswordPolicySpec.setDigitRequired(false);
-        basePasswordPolicySpec.setLowercaseRequired(false);
-        basePasswordPolicySpec.setMaxLength(1000);
-        basePasswordPolicySpec.setMinLength(8);
-        basePasswordPolicySpec.setMustEndWithAlpha(false);
-        basePasswordPolicySpec.setMustEndWithDigit(false);
-        basePasswordPolicySpec.setMustEndWithNonAlpha(false);
-        basePasswordPolicySpec.setMustStartWithAlpha(false);
-        basePasswordPolicySpec.setMustStartWithDigit(false);
-        basePasswordPolicySpec.setMustStartWithNonAlpha(false);
-        basePasswordPolicySpec.setMustntEndWithAlpha(false);
-        basePasswordPolicySpec.setMustntEndWithDigit(false);
-        basePasswordPolicySpec.setMustntEndWithNonAlpha(false);
-        basePasswordPolicySpec.setMustntStartWithAlpha(false);
-        basePasswordPolicySpec.setMustntStartWithDigit(false);
-        basePasswordPolicySpec.setMustntStartWithNonAlpha(false);
-        basePasswordPolicySpec.setNonAlphanumericRequired(false);
-        basePasswordPolicySpec.setUppercaseRequired(false);
-        return basePasswordPolicySpec;
+    private final DefaultPasswordGenerator passwordGenerator = new DefaultPasswordGenerator();
+
+    private DefaultPasswordRuleConf createBaseDefaultPasswordRuleConf() {
+        DefaultPasswordRuleConf baseDefaultPasswordRuleConf = new DefaultPasswordRuleConf();
+        baseDefaultPasswordRuleConf.setAlphanumericRequired(false);
+        baseDefaultPasswordRuleConf.setDigitRequired(false);
+        baseDefaultPasswordRuleConf.setLowercaseRequired(false);
+        baseDefaultPasswordRuleConf.setMaxLength(1000);
+        baseDefaultPasswordRuleConf.setMinLength(8);
+        baseDefaultPasswordRuleConf.setMustEndWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustEndWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustEndWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustStartWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustStartWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustStartWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustntEndWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithAlpha(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithDigit(false);
+        baseDefaultPasswordRuleConf.setMustntStartWithNonAlpha(false);
+        baseDefaultPasswordRuleConf.setNonAlphanumericRequired(false);
+        baseDefaultPasswordRuleConf.setUppercaseRequired(false);
+        return baseDefaultPasswordRuleConf;
     }
 
     @Test
-    public void startEndWithDigit() throws InvalidPasswordPolicySpecException {
-        PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMustStartWithDigit(true);
-
-        PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMustEndWithDigit(true);
-        List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<>();
-        passwordPolicySpecs.add(passwordPolicySpec);
-        passwordPolicySpecs.add(passwordPolicySpec2);
-        String generatedPassword = passwordGenerator.generate(passwordPolicySpecs);
+    public void startEndWithDigit() throws InvalidPasswordRuleConf {
+        DefaultPasswordRuleConf pwdRuleConf = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf.setMustStartWithDigit(true);
+
+        DefaultPasswordRuleConf pwdRuleConf2 = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf2.setMustEndWithDigit(true);
+
+        List<PasswordRuleConf> ruleConfs = new ArrayList<>();
+        ruleConfs.add(pwdRuleConf);
+        ruleConfs.add(pwdRuleConf2);
+        String generatedPassword = passwordGenerator.generate(ruleConfs);
         assertTrue(Character.isDigit(generatedPassword.charAt(0)));
         assertTrue(Character.isDigit(generatedPassword.charAt(generatedPassword.length() - 1)));
     }
 
     @Test
-    public void startWithDigitAndWithAlpha() throws InvalidPasswordPolicySpecException {
-        PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMustStartWithDigit(true);
-
-        PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMustEndWithAlpha(true);
-        List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<>();
-        passwordPolicySpecs.add(passwordPolicySpec);
-        passwordPolicySpecs.add(passwordPolicySpec2);
-        String generatedPassword = passwordGenerator.generate(passwordPolicySpecs);
+    public void startWithDigitAndWithAlpha() throws InvalidPasswordRuleConf {
+        DefaultPasswordRuleConf pwdRuleConf = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf.setMustStartWithDigit(true);
+
+        DefaultPasswordRuleConf pwdRuleConf2 = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf2.setMustEndWithAlpha(true);
+
+        List<PasswordRuleConf> pwdRuleConfs = new ArrayList<>();
+        pwdRuleConfs.add(pwdRuleConf);
+        pwdRuleConfs.add(pwdRuleConf2);
+        String generatedPassword = passwordGenerator.generate(pwdRuleConfs);
         assertTrue(Character.isDigit(generatedPassword.charAt(0)));
         assertTrue(Character.isLetter(generatedPassword.charAt(generatedPassword.length() - 1)));
     }
 
     @Test
-    public void passwordWithNonAlpha() throws InvalidPasswordPolicySpecException {
-        PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
-        passwordPolicySpec.setNonAlphanumericRequired(true);
-
-        PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMustEndWithAlpha(true);
-        List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<>();
-        passwordPolicySpecs.add(passwordPolicySpec);
-        passwordPolicySpecs.add(passwordPolicySpec2);
-        String generatedPassword = passwordGenerator.generate(passwordPolicySpecs);
+    public void passwordWithNonAlpha() throws InvalidPasswordRuleConf {
+        DefaultPasswordRuleConf pwdRuleConf = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf.setNonAlphanumericRequired(true);
+
+        DefaultPasswordRuleConf pwdRuleConf2 = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf2.setMustEndWithAlpha(true);
+
+        List<PasswordRuleConf> pwdRuleConfs = new ArrayList<>();
+        pwdRuleConfs.add(pwdRuleConf);
+        pwdRuleConfs.add(pwdRuleConf2);
+        String generatedPassword = passwordGenerator.generate(pwdRuleConfs);
         assertTrue(PolicyPattern.NON_ALPHANUMERIC.matcher(generatedPassword).matches());
         assertTrue(Character.isLetter(generatedPassword.charAt(generatedPassword.length() - 1)));
     }
 
-    @Test(expected = InvalidPasswordPolicySpecException.class)
-    public void incopatiblePolicies() throws InvalidPasswordPolicySpecException {
-        PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMinLength(12);
+    @Test(expected = InvalidPasswordRuleConf.class)
+    public void incopatiblePolicies() throws InvalidPasswordRuleConf {
+        DefaultPasswordRuleConf pwdRuleConf = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf.setMinLength(12);
 
-        PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
-        passwordPolicySpec.setMaxLength(10);
+        DefaultPasswordRuleConf pwdRuleConf2 = createBaseDefaultPasswordRuleConf();
+        pwdRuleConf.setMaxLength(10);
 
-        List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<>();
-        passwordPolicySpecs.add(passwordPolicySpec);
-        passwordPolicySpecs.add(passwordPolicySpec2);
-        passwordGenerator.generate(passwordPolicySpecs);
+        List<PasswordRuleConf> pwdRuleConfs = new ArrayList<>();
+        pwdRuleConfs.add(pwdRuleConf);
+        pwdRuleConfs.add(pwdRuleConf2);
+        passwordGenerator.generate(pwdRuleConfs);
     }
 
     @Test
     public void issueSYNCOPE678() {
         String password = null;
         try {
-            password = passwordGenerator.generate(Collections.<PasswordPolicySpec>emptyList());
-        } catch (InvalidPasswordPolicySpecException e) {
+            password = passwordGenerator.generate(Collections.<PasswordRuleConf>emptyList());
+        } catch (InvalidPasswordRuleConf e) {
             fail(e.getMessage());
         }
         assertNotNull(password);
 
-        PasswordPolicySpec ppSpec = createBasePasswordPolicySpec();
+        DefaultPasswordRuleConf ppSpec = createBaseDefaultPasswordRuleConf();
         ppSpec.setMinLength(0);
         password = null;
         try {
-            password = passwordGenerator.generate(Collections.singletonList(ppSpec));
-        } catch (InvalidPasswordPolicySpecException e) {
+            password = passwordGenerator.generate(Collections.<PasswordRuleConf>singletonList(ppSpec));
+        } catch (InvalidPasswordRuleConf e) {
             fail(e.getMessage());
         }
         assertNotNull(password);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
index 25e9e86..25145de 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
@@ -19,9 +19,12 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import org.apache.syncope.core.persistence.api.entity.user.User;
 
-public interface AccountRule extends PolicyRule {
-
-    void setConf(AccountRuleConf conf);
+/**
+ * Interface for enforcing a given account rule to user.
+ */
+public interface AccountRule {
 
+    void enforce(AccountRuleConf conf, User user);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
index 4f92092..4cb1ba9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
@@ -19,9 +19,12 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.core.persistence.api.entity.user.User;
 
-public interface PasswordRule extends PolicyRule {
-
-    void setConf(PasswordRuleConf conf);
+/**
+ * Interface for enforcing a given password rule to user.
+ */
+public interface PasswordRule {
 
+    void enforce(PasswordRuleConf conf, User user);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
index 58281ff..a27f1c0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.common.lib.types.PolicyType;
-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.Policy;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
deleted file mode 100644
index 72f8cac..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
+++ /dev/null
@@ -1,38 +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.core.persistence.api.entity.resource.ExternalResource;
-import java.util.Set;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-
-public interface AccountPolicy extends Policy {
-
-    AccountPolicySpec getSpecification();
-
-    void setSpecification(AccountPolicySpec spec);
-    
-    boolean add(ExternalResource resource);
-
-    boolean remove(ExternalResource resource);
-
-    Set<String> getResourceNames();
-
-    Set<? extends ExternalResource> getResources();
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
deleted file mode 100644
index a4004ce..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.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.PasswordPolicySpec;
-
-public interface PasswordPolicy extends Policy {
-
-    PasswordPolicySpec getSpecification();
-
-    void setSpecification(PasswordPolicySpec 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/PushPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
deleted file mode 100644
index e1c37df..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
+++ /dev/null
@@ -1,28 +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.PushPolicySpec;
-
-public interface PushPolicy extends Policy {
-
-    PushPolicySpec getSpecification();
-
-    void setSpecification(PushPolicySpec 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/Realm.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
index ab8fcac..ae3290f 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Realm.java
@@ -18,6 +18,9 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
+
 public interface Realm extends Entity<Long> {
 
     String getName();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
index 618e612..30245d0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
@@ -35,7 +35,7 @@ public interface Report extends Entity<Long> {
 
     boolean add(ReportletConf reportletConf);
 
-    boolean remove(ReportletConf reportletConf);
+    void removeAllReportletConfs();
 
     List<? extends ReportletConf> getReportletConfs();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b8cadde8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/ReportletConfInstance.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/ReportletConfInstance.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/ReportletConfInstance.java
deleted file mode 100644
index 5b9196d..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/ReportletConfInstance.java
+++ /dev/null
@@ -1,33 +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.report.ReportletConf;
-
-public interface ReportletConfInstance extends Entity<Long> {
-
-    ReportletConf getInstance();
-
-    Report getReport();
-
-    void setInstance(ReportletConf instance);
-
-    void setReport(Report report);
-
-}


[08/12] syncope git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope

Posted by il...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope


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

Branch: refs/heads/master
Commit: 77f697b2dbb05c81818288f74f3f7b7656db8b7f
Parents: 8e21972 4cdb34b
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Aug 20 11:41:11 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 20 11:41:11 2015 +0200

----------------------------------------------------------------------
 .../lib/policy/AbstractAccountRuleConf.java     |  52 +++
 .../lib/policy/AbstractPasswordRuleConf.java    |  52 +++
 .../common/lib/policy/AbstractPolicyTO.java     |  97 ++++++
 .../common/lib/policy/AccountPolicyTO.java      |  77 +++++
 .../common/lib/policy/AccountRuleConf.java      |  23 ++
 .../lib/policy/DefaultAccountRuleConf.java      |  94 ++++++
 .../lib/policy/DefaultPasswordRuleConf.java     | 277 ++++++++++++++++
 .../common/lib/policy/PasswordPolicyTO.java     |  68 ++++
 .../common/lib/policy/PasswordRuleConf.java     |  23 ++
 .../syncope/common/lib/policy/PolicyType.java   |  43 +++
 .../common/lib/policy/PushPolicySpec.java       |  28 ++
 .../syncope/common/lib/policy/RuleConf.java     |  32 ++
 .../common/lib/policy/SyncPolicySpec.java       |  63 ++++
 .../syncope/common/lib/policy/SyncPolicyTO.java |  45 +++
 .../common/lib/wrap/ReportletConfClass.java     |  30 --
 .../misc/policy/InvalidPasswordRuleConf.java    |  37 +++
 .../misc/security/DefaultPasswordGenerator.java | 330 +++++++++++++++++++
 .../core/persistence/api/dao/AccountRule.java   |  27 ++
 .../api/dao/AccountRuleConfClass.java           |  32 ++
 .../core/persistence/api/dao/PasswordRule.java  |  27 ++
 .../api/dao/PasswordRuleConfClass.java          |  32 ++
 .../api/entity/policy/AccountPolicy.java        |  50 +++
 .../api/entity/policy/PasswordPolicy.java       |  40 +++
 .../api/entity/policy/PushPolicy.java           |  29 ++
 .../api/entity/policy/SyncPolicy.java           |  30 ++
 .../persistence/jpa/dao/DefaultAccountRule.java | 112 +++++++
 .../jpa/dao/DefaultPasswordRule.java            | 218 ++++++++++++
 .../jpa/entity/policy/AbstractPolicy.java       |  67 ++++
 .../jpa/entity/policy/JPAAccountPolicy.java     | 160 +++++++++
 .../policy/JPAAccountRuleConfInstance.java      |  73 ++++
 .../jpa/entity/policy/JPAPasswordPolicy.java    | 115 +++++++
 .../policy/JPAPasswordRuleConfInstance.java     |  73 ++++
 .../jpa/entity/policy/JPAPushPolicy.java        |  55 ++++
 .../jpa/entity/policy/JPASyncPolicy.java        |  54 +++
 .../jpa/entity/task/AbstractTask.java           |  96 ++++++
 .../fit/core/reference/TestAccountRule.java     |  48 +++
 .../fit/core/reference/TestAccountRuleConf.java |  36 ++
 .../fit/core/reference/TestPasswordRule.java    |  48 +++
 .../core/reference/TestPasswordRuleConf.java    |  36 ++
 39 files changed, 2799 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
index 0000000,0000000..8fe5e24
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccountRuleConf.java
@@@ -1,0 -1,0 +1,52 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.report;
++
++import javax.xml.bind.annotation.XmlSeeAlso;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.commons.lang3.StringUtils;
++import org.apache.syncope.common.lib.AbstractBaseBean;
++
++@XmlType
++@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, GroupReportletConf.class })
++public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
++
++    private static final long serialVersionUID = -6130008602014516608L;
++
++    private String name;
++
++    public AbstractReportletConf() {
++        this(StringUtils.EMPTY);
++        setName(getClass().getName());
++    }
++
++    public AbstractReportletConf(final String name) {
++        super();
++        this.name = name;
++    }
++
++    @Override
++    public final String getName() {
++        return name;
++    }
++
++    public final void setName(final String name) {
++        this.name = name;
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
index 0000000,0000000..8fe5e24
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPasswordRuleConf.java
@@@ -1,0 -1,0 +1,52 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.report;
++
++import javax.xml.bind.annotation.XmlSeeAlso;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.commons.lang3.StringUtils;
++import org.apache.syncope.common.lib.AbstractBaseBean;
++
++@XmlType
++@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, GroupReportletConf.class })
++public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
++
++    private static final long serialVersionUID = -6130008602014516608L;
++
++    private String name;
++
++    public AbstractReportletConf() {
++        this(StringUtils.EMPTY);
++        setName(getClass().getName());
++    }
++
++    public AbstractReportletConf(final String name) {
++        super();
++        this.name = name;
++    }
++
++    @Override
++    public final String getName() {
++        return name;
++    }
++
++    public final void setName(final String name) {
++        this.name = name;
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPolicyTO.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPolicyTO.java
index 0000000,0000000..9157ba2
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractPolicyTO.java
@@@ -1,0 -1,0 +1,97 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import com.fasterxml.jackson.annotation.JsonProperty;
++import com.fasterxml.jackson.annotation.JsonTypeInfo;
++import java.util.ArrayList;
++import java.util.List;
++import javax.ws.rs.PathParam;
++import javax.xml.bind.annotation.XmlElement;
++import javax.xml.bind.annotation.XmlElementWrapper;
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlSeeAlso;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.syncope.common.lib.AbstractBaseBean;
++import org.apache.syncope.common.lib.types.PolicyType;
++
++@XmlRootElement(name = "abstractPolicy")
++@XmlType
++@XmlSeeAlso({ AccountPolicyTO.class, PasswordPolicyTO.class, SyncPolicyTO.class })
++@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
++public abstract class AbstractPolicyTO extends AbstractBaseBean {
++
++    private static final long serialVersionUID = -2903888572649721035L;
++
++    private long key;
++
++    private String description;
++
++    private final PolicyType type;
++
++    private final List<String> usedByResources = new ArrayList<>();
++
++    private final List<String> usedByRealms = new ArrayList<>();
++
++    private AbstractPolicyTO() {
++        super();
++        throw new UnsupportedOperationException("No-arg constructor is just to keep JAXB from complaining");
++    }
++
++    protected AbstractPolicyTO(final PolicyType type) {
++        super();
++        this.type = type;
++    }
++
++    public long getKey() {
++        return key;
++    }
++
++    @PathParam("key")
++    public void setKey(final long key) {
++        this.key = key;
++    }
++
++    public String getDescription() {
++        return description;
++    }
++
++    public void setDescription(final String description) {
++        this.description = description;
++    }
++
++    public PolicyType getType() {
++        return type;
++    }
++
++    @XmlElementWrapper(name = "usedByResources")
++    @XmlElement(name = "resource")
++    @JsonProperty("usedByResources")
++    public List<String> getUsedByResources() {
++        return usedByResources;
++    }
++
++    @XmlElementWrapper(name = "usedByRealms")
++    @XmlElement(name = "group")
++    @JsonProperty("usedByRealms")
++    public List<String> getUsedByRealms() {
++        return usedByRealms;
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
index 0000000,0000000..67d9fe0
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/AccountPolicyTO.java
@@@ -1,0 -1,0 +1,77 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import com.fasterxml.jackson.annotation.JsonProperty;
++import java.util.ArrayList;
++import java.util.List;
++import javax.xml.bind.annotation.XmlElement;
++import javax.xml.bind.annotation.XmlElementWrapper;
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.syncope.common.lib.types.PolicyType;
++
++@XmlRootElement(name = "accountPolicy")
++@XmlType
++public class AccountPolicyTO extends AbstractPolicyTO {
++
++    private static final long serialVersionUID = -1557150042828800134L;
++
++    private boolean propagateSuspension;
++
++    private int maxAuthenticationAttempts;
++
++    private final List<AccountRuleConf> ruleConfs = new ArrayList<>();
++
++    private final List<String> resources = new ArrayList<>();
++
++    public AccountPolicyTO() {
++        super(PolicyType.ACCOUNT);
++    }
++
++    public boolean isPropagateSuspension() {
++        return propagateSuspension;
++    }
++
++    public void setPropagateSuspension(final boolean propagateSuspension) {
++        this.propagateSuspension = propagateSuspension;
++    }
++
++    public int getMaxAuthenticationAttempts() {
++        return maxAuthenticationAttempts;
++    }
++
++    public void setMaxAuthenticationAttempts(final int maxAuthenticationAttempts) {
++        this.maxAuthenticationAttempts = maxAuthenticationAttempts;
++    }
++
++    @XmlElementWrapper(name = "ruleConfs")
++    @XmlElement(name = "ruleConf")
++    @JsonProperty("ruleConfs")
++    public List<AccountRuleConf> getRuleConfs() {
++        return ruleConfs;
++    }
++
++    @XmlElementWrapper(name = "resources")
++    @XmlElement(name = "resource")
++    @JsonProperty("resources")
++    public List<String> getResources() {
++        return resources;
++    }
++}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
index 0000000,0000000..929f05b
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
@@@ -1,0 -1,0 +1,94 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlType;
++
++@XmlRootElement(name = "defaultAccountRuleConf")
++@XmlType
++public class DefaultAccountRuleConf extends AbstractRuleConf implements AccountRuleConf {
++
++    private static final long serialVersionUID = 3259256974414758406L;
++
++    /**
++     * Minimum length.
++     */
++    private int maxLength;
++
++    /**
++     * Maximum length.
++     */
++    private int minLength;
++
++    /**
++     * Pattern (regular expression) that must match.
++     */
++    private String pattern;
++
++    /**
++     * Specify if one or more lowercase characters are permitted.
++     */
++    private boolean allUpperCase;
++
++    /**
++     * Specify if one or more uppercase characters are permitted.
++     */
++    private boolean allLowerCase;
++
++    public boolean isAllLowerCase() {
++        return allLowerCase;
++    }
++
++    public void setAllLowerCase(final boolean allLowerCase) {
++        this.allLowerCase = allLowerCase;
++    }
++
++    public boolean isAllUpperCase() {
++        return allUpperCase;
++    }
++
++    public void setAllUpperCase(final boolean allUpperCase) {
++        this.allUpperCase = allUpperCase;
++    }
++
++    public int getMaxLength() {
++        return maxLength;
++    }
++
++    public void setMaxLength(final int maxLength) {
++        this.maxLength = maxLength;
++    }
++
++    public int getMinLength() {
++        return minLength;
++    }
++
++    public void setMinLength(final int minLength) {
++        this.minLength = minLength;
++    }
++
++    public String getPattern() {
++        return pattern;
++    }
++
++    public void setPattern(final String pattern) {
++        this.pattern = pattern;
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
index 0000000,0000000..629e820
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
@@@ -1,0 -1,0 +1,277 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlType;
++
++@XmlRootElement(name = "defaultPasswordRuleConf")
++@XmlType
++public class DefaultPasswordRuleConf extends AbstractRuleConf implements PasswordRuleConf {
++
++    private static final long serialVersionUID = -7988778083915548547L;
++
++    /**
++     * Minimum length.
++     */
++    private int maxLength;
++
++    /**
++     * Maximum length.
++     */
++    private int minLength;
++
++    /**
++     * Specify if one or more non alphanumeric characters are required.
++     */
++    private boolean nonAlphanumericRequired;
++
++    /**
++     * Specify if one or more alphanumeric characters are required.
++     */
++    private boolean alphanumericRequired;
++
++    /**
++     * Specify if one or more digits are required.
++     */
++    private boolean digitRequired;
++
++    /**
++     * Specify if one or more lowercase alphabetic characters are required.
++     */
++    private boolean lowercaseRequired;
++
++    /**
++     * Specify if one or more uppercase alphabetic characters are required.
++     */
++    private boolean uppercaseRequired;
++
++    /**
++     * Specify if must start with a digit.
++     */
++    private boolean mustStartWithDigit;
++
++    /**
++     * Specify if mustn't start with a digit.
++     */
++    private boolean mustntStartWithDigit;
++
++    /**
++     * Specify if must end with a digit.
++     */
++    private boolean mustEndWithDigit;
++
++    /**
++     * Specify if mustn't end with a digit.
++     */
++    private boolean mustntEndWithDigit;
++
++    /**
++     * Specify if must start with a non alphanumeric character.
++     */
++    private boolean mustStartWithNonAlpha;
++
++    /**
++     * Specify if must start with a alphanumeric character.
++     */
++    private boolean mustStartWithAlpha;
++
++    /**
++     * Specify if mustn't start with a non alphanumeric character.
++     */
++    private boolean mustntStartWithNonAlpha;
++
++    /**
++     * Specify if mustn't start with a alphanumeric character.
++     */
++    private boolean mustntStartWithAlpha;
++
++    /**
++     * Specify if must end with a non alphanumeric character.
++     */
++    private boolean mustEndWithNonAlpha;
++
++    /**
++     * Specify if must end with a alphanumeric character.
++     */
++    private boolean mustEndWithAlpha;
++
++    /**
++     * Specify if mustn't end with a non alphanumeric character.
++     */
++    private boolean mustntEndWithNonAlpha;
++
++    /**
++     * Specify if mustn't end with a alphanumeric character.
++     */
++    private boolean mustntEndWithAlpha;
++
++    public boolean isDigitRequired() {
++        return digitRequired;
++    }
++
++    public void setDigitRequired(final boolean digitRequired) {
++        this.digitRequired = digitRequired;
++    }
++
++    public boolean isLowercaseRequired() {
++        return lowercaseRequired;
++    }
++
++    public void setLowercaseRequired(final boolean lowercaseRequired) {
++        this.lowercaseRequired = lowercaseRequired;
++    }
++
++    public int getMaxLength() {
++        return maxLength;
++    }
++
++    public void setMaxLength(final int maxLength) {
++        this.maxLength = maxLength;
++    }
++
++    public int getMinLength() {
++        return minLength;
++    }
++
++    public void setMinLength(final int minLength) {
++        this.minLength = minLength;
++    }
++
++    public boolean isMustEndWithDigit() {
++        return mustEndWithDigit;
++    }
++
++    public void setMustEndWithDigit(final boolean mustEndWithDigit) {
++        this.mustEndWithDigit = mustEndWithDigit;
++    }
++
++    public boolean isMustEndWithNonAlpha() {
++        return mustEndWithNonAlpha;
++    }
++
++    public void setMustEndWithNonAlpha(final boolean mustEndWithNonAlpha) {
++        this.mustEndWithNonAlpha = mustEndWithNonAlpha;
++    }
++
++    public boolean isMustStartWithDigit() {
++        return mustStartWithDigit;
++    }
++
++    public void setMustStartWithDigit(final boolean mustStartWithDigit) {
++        this.mustStartWithDigit = mustStartWithDigit;
++    }
++
++    public boolean isMustStartWithNonAlpha() {
++        return mustStartWithNonAlpha;
++    }
++
++    public void setMustStartWithNonAlpha(final boolean mustStartWithNonAlpha) {
++        this.mustStartWithNonAlpha = mustStartWithNonAlpha;
++    }
++
++    public boolean isMustntEndWithDigit() {
++        return mustntEndWithDigit;
++    }
++
++    public void setMustntEndWithDigit(final boolean mustntEndWithDigit) {
++        this.mustntEndWithDigit = mustntEndWithDigit;
++    }
++
++    public boolean isMustntEndWithNonAlpha() {
++        return mustntEndWithNonAlpha;
++    }
++
++    public void setMustntEndWithNonAlpha(final boolean mustntEndWithNonAlpha) {
++        this.mustntEndWithNonAlpha = mustntEndWithNonAlpha;
++    }
++
++    public boolean isMustntStartWithDigit() {
++        return mustntStartWithDigit;
++    }
++
++    public void setMustntStartWithDigit(final boolean mustntStartWithDigit) {
++        this.mustntStartWithDigit = mustntStartWithDigit;
++    }
++
++    public boolean isMustntStartWithNonAlpha() {
++        return mustntStartWithNonAlpha;
++    }
++
++    public void setMustntStartWithNonAlpha(final boolean mustntStartWithNonAlpha) {
++        this.mustntStartWithNonAlpha = mustntStartWithNonAlpha;
++    }
++
++    public boolean isNonAlphanumericRequired() {
++        return nonAlphanumericRequired;
++    }
++
++    public void setNonAlphanumericRequired(final boolean nonAlphanumericRequired) {
++        this.nonAlphanumericRequired = nonAlphanumericRequired;
++    }
++
++    public boolean isUppercaseRequired() {
++        return uppercaseRequired;
++    }
++
++    public void setUppercaseRequired(final boolean uppercaseRequired) {
++        this.uppercaseRequired = uppercaseRequired;
++    }
++
++    public boolean isAlphanumericRequired() {
++        return alphanumericRequired;
++    }
++
++    public void setAlphanumericRequired(final boolean alphanumericRequired) {
++        this.alphanumericRequired = alphanumericRequired;
++    }
++
++    public boolean isMustEndWithAlpha() {
++        return mustEndWithAlpha;
++    }
++
++    public void setMustEndWithAlpha(final boolean mustEndWithAlpha) {
++        this.mustEndWithAlpha = mustEndWithAlpha;
++    }
++
++    public boolean isMustStartWithAlpha() {
++        return mustStartWithAlpha;
++    }
++
++    public void setMustStartWithAlpha(final boolean mustStartWithAlpha) {
++        this.mustStartWithAlpha = mustStartWithAlpha;
++    }
++
++    public boolean isMustntEndWithAlpha() {
++        return mustntEndWithAlpha;
++    }
++
++    public void setMustntEndWithAlpha(final boolean mustntEndWithAlpha) {
++        this.mustntEndWithAlpha = mustntEndWithAlpha;
++    }
++
++    public boolean isMustntStartWithAlpha() {
++        return mustntStartWithAlpha;
++    }
++
++    public void setMustntStartWithAlpha(final boolean mustntStartWithAlpha) {
++        this.mustntStartWithAlpha = mustntStartWithAlpha;
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
index 0000000,0000000..cf91df2
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PasswordPolicyTO.java
@@@ -1,0 -1,0 +1,68 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import com.fasterxml.jackson.annotation.JsonProperty;
++import java.util.ArrayList;
++import java.util.List;
++import javax.xml.bind.annotation.XmlElement;
++import javax.xml.bind.annotation.XmlElementWrapper;
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.syncope.common.lib.types.PolicyType;
++
++@XmlRootElement(name = "passwordPolicy")
++@XmlType
++public class PasswordPolicyTO extends AbstractPolicyTO {
++
++    private static final long serialVersionUID = -5606086441294799690L;
++
++    private boolean allowNullPassword;
++
++    private int historyLength;
++
++    private final List<PasswordRuleConf> ruleConfs = new ArrayList<>();
++
++    public PasswordPolicyTO() {
++        super(PolicyType.PASSWORD);
++    }
++
++    public boolean isAllowNullPassword() {
++        return allowNullPassword;
++    }
++
++    public void setAllowNullPassword(final boolean allowNullPassword) {
++        this.allowNullPassword = allowNullPassword;
++    }
++
++    public int getHistoryLength() {
++        return historyLength;
++    }
++
++    public void setHistoryLength(final int historyLength) {
++        this.historyLength = historyLength;
++    }
++
++    @XmlElementWrapper(name = "ruleConfs")
++    @XmlElement(name = "ruleConf")
++    @JsonProperty("ruleConfs")
++    public List<PasswordRuleConf> getRuleConfs() {
++        return ruleConfs;
++    }
++}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyType.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyType.java
index 0000000,0000000..7f1c11e
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyType.java
@@@ -1,0 -1,0 +1,43 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.types;
++
++import javax.xml.bind.annotation.XmlEnum;
++
++@XmlEnum
++public enum PolicyType {
++
++    /**
++     * How username values should look like.
++     */
++    ACCOUNT,
++    /**
++     * How password values should look like.
++     */
++    PASSWORD,
++    /**
++     * For handling conflicts resolution during synchronization.
++     */
++    SYNC,
++    /**
++     * For handling conflicts resolution during push.
++     */
++    PUSH;
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PushPolicySpec.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/PushPolicySpec.java
index 0000000,0000000..4b61374
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PushPolicySpec.java
@@@ -1,0 -1,0 +1,28 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import javax.xml.bind.annotation.XmlType;
++
++@XmlType
++public class PushPolicySpec {
++
++    private static final long serialVersionUID = 3641030189482617497L;
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/RuleConf.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/RuleConf.java
index 0000000,0000000..5a99cd1
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/RuleConf.java
@@@ -1,0 -1,0 +1,32 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import com.fasterxml.jackson.annotation.JsonTypeInfo;
++
++@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
++public interface RuleConf {
++
++    /**
++     * Give name of related rule instance.
++     *
++     * @return name of this rule instance
++     */
++    String getName();
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicySpec.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicySpec.java
index 0000000,0000000..1eb578e
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicySpec.java
@@@ -1,0 -1,0 +1,63 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import com.fasterxml.jackson.annotation.JsonIgnore;
++import com.fasterxml.jackson.annotation.JsonProperty;
++import java.util.HashMap;
++import java.util.Map;
++import javax.xml.bind.annotation.XmlType;
++import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
++import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
++import org.apache.syncope.common.lib.types.ConflictResolutionAction;
++
++@XmlType
++public class SyncPolicySpec {
++
++    private static final long serialVersionUID = -3144027171719498127L;
++
++    private ConflictResolutionAction conflictResolutionAction;
++
++    /**
++     * Associates anyTypeKey to either:
++     * <ol>
++     * <li>Java class name, implementing {@code SyncCorrelationRule}</li>
++     * <li>JSON array containing plain schema names - this will be used to feed
++     * {@code PlainAttrsSyncCorrelationRule}</li>
++     * </ol>
++     */
++    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
++    @JsonIgnore
++    private final Map<String, String> correlationRules = new HashMap<>();
++
++    public ConflictResolutionAction getConflictResolutionAction() {
++        return conflictResolutionAction == null
++                ? ConflictResolutionAction.IGNORE
++                : conflictResolutionAction;
++    }
++
++    public void setConflictResolutionAction(final ConflictResolutionAction conflictResolutionAction) {
++        this.conflictResolutionAction = conflictResolutionAction;
++    }
++
++    @JsonProperty
++    public Map<String, String> getCorrelationRules() {
++        return correlationRules;
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicyTO.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicyTO.java
index 0000000,0000000..911c445
new file mode 100644
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/SyncPolicyTO.java
@@@ -1,0 -1,0 +1,45 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.common.lib.policy;
++
++import javax.xml.bind.annotation.XmlRootElement;
++import javax.xml.bind.annotation.XmlType;
++import org.apache.syncope.common.lib.types.PolicyType;
++
++@XmlRootElement(name = "syncPolicy")
++@XmlType
++public class SyncPolicyTO extends AbstractPolicyTO {
++
++    private static final long serialVersionUID = 993024634238024242L;
++
++    private SyncPolicySpec specification;
++
++    public SyncPolicyTO() {
++        super(PolicyType.SYNC);
++    }
++
++    public SyncPolicySpec getSpecification() {
++        return specification;
++    }
++
++    public void setSpecification(final SyncPolicySpec specification) {
++        this.specification = specification;
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java
----------------------------------------------------------------------
diff --cc common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java
index 24ba188,24ba188..0000000
deleted file mode 100644,100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java
+++ /dev/null
@@@ -1,30 -1,30 +1,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.common.lib.wrap;
--
--import javax.xml.bind.annotation.XmlRootElement;
--import javax.xml.bind.annotation.XmlType;
--
--@XmlRootElement(name = "reportletConfClass")
--@XmlType
--public class ReportletConfClass extends AbstractWrappable<String> {
--
--    private static final long serialVersionUID = 1343357929074360450L;
--
--}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordRuleConf.java
----------------------------------------------------------------------
diff --cc core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordRuleConf.java
index 0000000,0000000..4b13807
new file mode 100644
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/InvalidPasswordRuleConf.java
@@@ -1,0 -1,0 +1,37 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.misc.policy;
++
++/**
++ * Raise when the merge of two or more PasswordRuleconf instances led to an inconsistent condition.
++ *
++ * @see org.apache.syncope.common.lib.policy.PasswordRuleConf
++ */
++public class InvalidPasswordRuleConf extends Exception {
++
++    private static final long serialVersionUID = 4810651743226663580L;
++
++    public InvalidPasswordRuleConf(final String msg) {
++        super(msg);
++    }
++
++    public InvalidPasswordRuleConf(final String msg, final Exception e) {
++        super(msg, e);
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
----------------------------------------------------------------------
diff --cc core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
index 0000000,0000000..a1a1822
new file mode 100644
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/DefaultPasswordGenerator.java
@@@ -1,0 -1,0 +1,330 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.misc.security;
++
++import java.util.ArrayList;
++import java.util.List;
++import org.apache.commons.lang3.StringUtils;
++import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.apache.syncope.core.misc.policy.InvalidPasswordRuleConf;
++import org.apache.syncope.core.misc.policy.PolicyPattern;
++import org.apache.syncope.core.persistence.api.dao.RealmDAO;
++import org.apache.syncope.core.persistence.api.dao.UserDAO;
++import org.apache.syncope.core.persistence.api.entity.Realm;
++import org.springframework.beans.factory.annotation.Autowired;
++
++/**
++ * Generate random passwords according to given policies.
++ * When no minimum and / or maximum length are specified, default values are set.
++ *
++ * <strong>WARNING</strong>: This class only takes {@link DefaultPasswordRuleConf} into account.
++ */
++public class DefaultPasswordGenerator implements PasswordGenerator {
++
++    private static final char[] SPECIAL_CHARS = { '!', '£', '%', '&', '(', ')', '?', '#', '$' };
++
++    private static final int VERY_MIN_LENGTH = 0;
++
++    private static final int VERY_MAX_LENGTH = 64;
++
++    private static final int MIN_LENGTH_IF_ZERO = 6;
++
++    @Autowired
++    private UserDAO userDAO;
++
++    @Autowired
++    private RealmDAO realmDAO;
++
++    @Override
++    public String generate(final User user) throws InvalidPasswordRuleConf {
++        List<PasswordRuleConf> ruleConfs = new ArrayList<>();
++
++        for (Realm ancestor : realmDAO.findAncestors(user.getRealm())) {
++            if (ancestor.getPasswordPolicy() != null) {
++                ruleConfs.addAll(ancestor.getPasswordPolicy().getRuleConfs());
++            }
++        }
++
++        for (ExternalResource resource : userDAO.findAllResources(user)) {
++            if (resource.getPasswordPolicy() != null) {
++                ruleConfs.addAll(resource.getPasswordPolicy().getRuleConfs());
++            }
++        }
++
++        return generate(ruleConfs);
++    }
++
++    @Override
++    public String generate(final List<PasswordRuleConf> ruleConfs) throws InvalidPasswordRuleConf {
++        List<DefaultPasswordRuleConf> defaultRuleConfs = new ArrayList<>();
++        for (PasswordRuleConf ruleConf : ruleConfs) {
++            if (ruleConf instanceof DefaultPasswordRuleConf) {
++                defaultRuleConfs.add((DefaultPasswordRuleConf) ruleConf);
++            }
++        }
++
++        DefaultPasswordRuleConf ruleConf = merge(defaultRuleConfs);
++        check(ruleConf);
++        return generate(ruleConf);
++    }
++
++    private DefaultPasswordRuleConf merge(final List<DefaultPasswordRuleConf> defaultRuleConfs) {
++        DefaultPasswordRuleConf fpps = new DefaultPasswordRuleConf();
++        fpps.setMinLength(VERY_MIN_LENGTH);
++        fpps.setMaxLength(VERY_MAX_LENGTH);
++
++        for (DefaultPasswordRuleConf ruleConf : defaultRuleConfs) {
++            if (ruleConf.getMinLength() > fpps.getMinLength()) {
++                fpps.setMinLength(ruleConf.getMinLength());
++            }
++
++            if ((ruleConf.getMaxLength() != 0) && ((ruleConf.getMaxLength() < fpps.getMaxLength()))) {
++                fpps.setMaxLength(ruleConf.getMaxLength());
++            }
++            fpps.getPrefixesNotPermitted().addAll(ruleConf.getPrefixesNotPermitted());
++            fpps.getSuffixesNotPermitted().addAll(ruleConf.getSuffixesNotPermitted());
++
++            if (!fpps.isNonAlphanumericRequired()) {
++                fpps.setNonAlphanumericRequired(ruleConf.isNonAlphanumericRequired());
++            }
++
++            if (!fpps.isAlphanumericRequired()) {
++                fpps.setAlphanumericRequired(ruleConf.isAlphanumericRequired());
++            }
++            if (!fpps.isDigitRequired()) {
++                fpps.setDigitRequired(ruleConf.isDigitRequired());
++            }
++
++            if (!fpps.isLowercaseRequired()) {
++                fpps.setLowercaseRequired(ruleConf.isLowercaseRequired());
++            }
++            if (!fpps.isUppercaseRequired()) {
++                fpps.setUppercaseRequired(ruleConf.isUppercaseRequired());
++            }
++            if (!fpps.isMustStartWithDigit()) {
++                fpps.setMustStartWithDigit(ruleConf.isMustStartWithDigit());
++            }
++            if (!fpps.isMustntStartWithDigit()) {
++                fpps.setMustntStartWithDigit(ruleConf.isMustntStartWithDigit());
++            }
++            if (!fpps.isMustEndWithDigit()) {
++                fpps.setMustEndWithDigit(ruleConf.isMustEndWithDigit());
++            }
++            if (fpps.isMustntEndWithDigit()) {
++                fpps.setMustntEndWithDigit(ruleConf.isMustntEndWithDigit());
++            }
++            if (!fpps.isMustStartWithAlpha()) {
++                fpps.setMustStartWithAlpha(ruleConf.isMustStartWithAlpha());
++            }
++            if (!fpps.isMustntStartWithAlpha()) {
++                fpps.setMustntStartWithAlpha(ruleConf.isMustntStartWithAlpha());
++            }
++            if (!fpps.isMustStartWithNonAlpha()) {
++                fpps.setMustStartWithNonAlpha(ruleConf.isMustStartWithNonAlpha());
++            }
++            if (!fpps.isMustntStartWithNonAlpha()) {
++                fpps.setMustntStartWithNonAlpha(ruleConf.isMustntStartWithNonAlpha());
++            }
++            if (!fpps.isMustEndWithNonAlpha()) {
++                fpps.setMustEndWithNonAlpha(ruleConf.isMustEndWithNonAlpha());
++            }
++            if (!fpps.isMustntEndWithNonAlpha()) {
++                fpps.setMustntEndWithNonAlpha(ruleConf.isMustntEndWithNonAlpha());
++            }
++            if (!fpps.isMustEndWithAlpha()) {
++                fpps.setMustEndWithAlpha(ruleConf.isMustEndWithAlpha());
++            }
++            if (!fpps.isMustntEndWithAlpha()) {
++                fpps.setMustntEndWithAlpha(ruleConf.isMustntEndWithAlpha());
++            }
++        }
++
++        if (fpps.getMinLength() == 0) {
++            fpps.setMinLength(fpps.getMaxLength() < MIN_LENGTH_IF_ZERO ? fpps.getMaxLength() : MIN_LENGTH_IF_ZERO);
++        }
++
++        return fpps;
++    }
++
++    private void check(final DefaultPasswordRuleConf defaultPasswordRuleConf)
++            throws InvalidPasswordRuleConf {
++
++        if (defaultPasswordRuleConf.isMustEndWithAlpha() && defaultPasswordRuleConf.isMustntEndWithAlpha()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustEndWithAlpha and mustntEndWithAlpha are both true");
++        }
++        if (defaultPasswordRuleConf.isMustEndWithAlpha() && defaultPasswordRuleConf.isMustEndWithDigit()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustEndWithAlpha and mustEndWithDigit are both true");
++        }
++        if (defaultPasswordRuleConf.isMustEndWithDigit() && defaultPasswordRuleConf.isMustntEndWithDigit()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustEndWithDigit and mustntEndWithDigit are both true");
++        }
++        if (defaultPasswordRuleConf.isMustEndWithNonAlpha() && defaultPasswordRuleConf.isMustntEndWithNonAlpha()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustEndWithNonAlpha and mustntEndWithNonAlpha are both true");
++        }
++        if (defaultPasswordRuleConf.isMustStartWithAlpha() && defaultPasswordRuleConf.isMustntStartWithAlpha()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustStartWithAlpha and mustntStartWithAlpha are both true");
++        }
++        if (defaultPasswordRuleConf.isMustStartWithAlpha() && defaultPasswordRuleConf.isMustStartWithDigit()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustStartWithAlpha and mustStartWithDigit are both true");
++        }
++        if (defaultPasswordRuleConf.isMustStartWithDigit() && defaultPasswordRuleConf.isMustntStartWithDigit()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustStartWithDigit and mustntStartWithDigit are both true");
++        }
++        if (defaultPasswordRuleConf.isMustStartWithNonAlpha() && defaultPasswordRuleConf.isMustntStartWithNonAlpha()) {
++            throw new InvalidPasswordRuleConf(
++                    "mustStartWithNonAlpha and mustntStartWithNonAlpha are both true");
++        }
++        if (defaultPasswordRuleConf.getMinLength() > defaultPasswordRuleConf.getMaxLength()) {
++            throw new InvalidPasswordRuleConf(
++                    "Minimun length (" + defaultPasswordRuleConf.getMinLength() + ")"
++                    + "is greater than maximum length (" + defaultPasswordRuleConf.getMaxLength() + ")");
++        }
++    }
++
++    private String generate(final DefaultPasswordRuleConf ruleConf) {
++        String[] generatedPassword = new String[ruleConf.getMinLength()];
++
++        for (int i = 0; i < generatedPassword.length; i++) {
++            generatedPassword[i] = StringUtils.EMPTY;
++        }
++
++        checkStartChar(generatedPassword, ruleConf);
++
++        checkEndChar(generatedPassword, ruleConf);
++
++        checkRequired(generatedPassword, ruleConf);
++
++        for (int firstEmptyChar = firstEmptyChar(generatedPassword);
++                firstEmptyChar < generatedPassword.length - 1; firstEmptyChar++) {
++
++            generatedPassword[firstEmptyChar] = SecureRandomUtils.generateRandomLetter();
++        }
++
++        checkPrefixAndSuffix(generatedPassword, ruleConf);
++
++        return StringUtils.join(generatedPassword);
++    }
++
++    private void checkStartChar(final String[] generatedPassword, final DefaultPasswordRuleConf ruleConf) {
++        if (ruleConf.isMustStartWithAlpha()) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
++        }
++        if (ruleConf.isMustStartWithNonAlpha() || ruleConf.isMustStartWithDigit()) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomNumber();
++        }
++        if (ruleConf.isMustntStartWithAlpha()) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomNumber();
++        }
++        if (ruleConf.isMustntStartWithDigit()) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
++        }
++        if (ruleConf.isMustntStartWithNonAlpha()) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
++        }
++
++        if (StringUtils.EMPTY.equals(generatedPassword[0])) {
++            generatedPassword[0] = SecureRandomUtils.generateRandomLetter();
++        }
++    }
++
++    private void checkEndChar(final String[] generatedPassword, final DefaultPasswordRuleConf ruleConf) {
++        if (ruleConf.isMustEndWithAlpha()) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
++        }
++        if (ruleConf.isMustEndWithNonAlpha() || ruleConf.isMustEndWithDigit()) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomNumber();
++        }
++
++        if (ruleConf.isMustntEndWithAlpha()) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomNumber();
++        }
++        if (ruleConf.isMustntEndWithDigit()) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
++        }
++        if (ruleConf.isMustntEndWithNonAlpha()) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
++        }
++
++        if (StringUtils.EMPTY.equals(generatedPassword[ruleConf.getMinLength() - 1])) {
++            generatedPassword[ruleConf.getMinLength() - 1] = SecureRandomUtils.generateRandomLetter();
++        }
++    }
++
++    private int firstEmptyChar(final String[] generatedPStrings) {
++        int index = 0;
++        while (!generatedPStrings[index].isEmpty()) {
++            index++;
++        }
++        return index;
++    }
++
++    private void checkRequired(final String[] generatedPassword, final DefaultPasswordRuleConf ruleConf) {
++        if (ruleConf.isDigitRequired()
++                && !PolicyPattern.DIGIT.matcher(StringUtils.join(generatedPassword)).matches()) {
++
++            generatedPassword[firstEmptyChar(generatedPassword)] = SecureRandomUtils.generateRandomNumber();
++        }
++
++        if (ruleConf.isUppercaseRequired()
++                && !PolicyPattern.ALPHA_UPPERCASE.matcher(StringUtils.join(generatedPassword)).matches()) {
++
++            generatedPassword[firstEmptyChar(generatedPassword)] =
++                    SecureRandomUtils.generateRandomLetter().toUpperCase();
++        }
++
++        if (ruleConf.isLowercaseRequired()
++                && !PolicyPattern.ALPHA_LOWERCASE.matcher(StringUtils.join(generatedPassword)).matches()) {
++
++            generatedPassword[firstEmptyChar(generatedPassword)] =
++                    SecureRandomUtils.generateRandomLetter().toLowerCase();
++        }
++
++        if (ruleConf.isNonAlphanumericRequired()
++                && !PolicyPattern.NON_ALPHANUMERIC.matcher(StringUtils.join(generatedPassword)).matches()) {
++
++            generatedPassword[firstEmptyChar(generatedPassword)] =
++                    SecureRandomUtils.generateRandomSpecialCharacter(SPECIAL_CHARS);
++        }
++    }
++
++    private void checkPrefixAndSuffix(final String[] generatedPassword, final DefaultPasswordRuleConf ruleConf) {
++        for (String prefix : ruleConf.getPrefixesNotPermitted()) {
++            if (StringUtils.join(generatedPassword).startsWith(prefix)) {
++                checkStartChar(generatedPassword, ruleConf);
++            }
++        }
++
++        for (String suffix : ruleConf.getSuffixesNotPermitted()) {
++            if (StringUtils.join(generatedPassword).endsWith(suffix)) {
++                checkEndChar(generatedPassword, ruleConf);
++            }
++        }
++    }
++
++}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRuleConfClass.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRuleConfClass.java
index 0000000,0000000..5b6bace
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRuleConfClass.java
@@@ -1,0 -1,0 +1,32 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.persistence.api.dao;
++
++import java.lang.annotation.ElementType;
++import java.lang.annotation.Retention;
++import java.lang.annotation.RetentionPolicy;
++import java.lang.annotation.Target;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++
++@Target({ ElementType.TYPE })
++@Retention(RetentionPolicy.RUNTIME)
++public @interface AccountRuleConfClass {
++
++    Class<? extends AccountRuleConf> value();
++}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRuleConfClass.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRuleConfClass.java
index 0000000,0000000..745e336
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRuleConfClass.java
@@@ -1,0 -1,0 +1,32 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.persistence.api.dao;
++
++import java.lang.annotation.ElementType;
++import java.lang.annotation.Retention;
++import java.lang.annotation.RetentionPolicy;
++import java.lang.annotation.Target;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++
++@Target({ ElementType.TYPE })
++@Retention(RetentionPolicy.RUNTIME)
++public @interface PasswordRuleConfClass {
++
++    Class<? extends PasswordRuleConf> value();
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
index 0000000,0000000..f9a8277
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccountPolicy.java
@@@ -1,0 -1,0 +1,50 @@@
++/*
++ * 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.policy;
++
++import java.util.List;
++import java.util.Set;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
++
++public interface AccountPolicy extends Policy {
++
++    boolean isPropagateSuspension();
++
++    void setPropagateSuspension(boolean propagateSuspension);
++
++    int getMaxAuthenticationAttempts();
++
++    void setMaxAuthenticationAttempts(int maxAuthenticationAttempts);
++
++    boolean add(AccountRuleConf accountRuleConf);
++
++    boolean remove(AccountRuleConf accountRuleConf);
++
++    List<AccountRuleConf> getRuleConfs();
++
++    boolean add(ExternalResource resource);
++
++    boolean remove(ExternalResource resource);
++
++    Set<String> getResourceNames();
++
++    Set<? extends ExternalResource> getResources();
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
index 0000000,0000000..173608e
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PasswordPolicy.java
@@@ -1,0 -1,0 +1,40 @@@
++/*
++ * 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.policy;
++
++import java.util.List;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++
++public interface PasswordPolicy extends Policy {
++
++    boolean isAllowNullPassword();
++
++    void setAllowNullPassword(final boolean allowNullPassword);
++
++    int getHistoryLength();
++
++    void setHistoryLength(int historyLength);
++
++    boolean add(PasswordRuleConf passwordRuleConf);
++
++    boolean remove(PasswordRuleConf passwordRuleConf);
++
++    List<PasswordRuleConf> getRuleConfs();
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PushPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PushPolicy.java
index 0000000,0000000..4365e72
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PushPolicy.java
@@@ -1,0 -1,0 +1,29 @@@
++/*
++ * 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.policy;
++
++import org.apache.syncope.common.lib.policy.PushPolicySpec;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++
++public interface PushPolicy extends Policy {
++
++    PushPolicySpec getSpecification();
++
++    void setSpecification(PushPolicySpec spec);
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/SyncPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/SyncPolicy.java
index 0000000,0000000..78a9882
new file mode 100644
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/SyncPolicy.java
@@@ -1,0 -1,0 +1,30 @@@
++/*
++ * 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.policy;
++
++import org.apache.syncope.common.lib.policy.SyncPolicySpec;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++
++public interface SyncPolicy extends Policy {
++
++    SyncPolicySpec getSpecification();
++
++    void setSpecification(SyncPolicySpec spec);
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
index 0000000,0000000..7ef2ebf
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultAccountRule.java
@@@ -1,0 -1,0 +1,112 @@@
++/*
++ * 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.dao;
++
++import java.util.List;
++import java.util.regex.Pattern;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
++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.core.persistence.api.entity.PlainAttr;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@AccountRuleConfClass(DefaultAccountRuleConf.class)
++public class DefaultAccountRule implements AccountRule {
++
++    private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+");
++
++    private DefaultAccountRuleConf conf;
++
++    @Override
++    public void setConf(final AccountRuleConf conf) {
++        if (conf instanceof DefaultAccountRuleConf) {
++            this.conf = (DefaultAccountRuleConf) 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()) {
++            PlainAttr<?> attr = user.getPlainAttr(schema);
++            if (attr != null) {
++                List<String> values = attr.getValuesAsStrings();
++                if (values != null && !values.isEmpty()) {
++                    conf.getWordsNotPermitted().add(values.get(0));
++                }
++            }
++        }
++
++        if (user.getUsername() == null) {
++            throw new AccountPolicyException("Invalid account");
++        }
++
++        // check min length
++        if (conf.getMinLength() > 0 && conf.getMinLength() > user.getUsername().length()) {
++            throw new AccountPolicyException("Username too short");
++        }
++
++        // check max length
++        if (conf.getMaxLength() > 0 && conf.getMaxLength() < user.getUsername().length()) {
++            throw new AccountPolicyException("Username too long");
++        }
++
++        // check words not permitted
++        for (String word : 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())) {
++            throw new AccountPolicyException("No lowercase characters permitted");
++        }
++        if (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());
++        if (!pattern.matcher(user.getUsername()).matches()) {
++            throw new AccountPolicyException("Username does not match pattern");
++        }
++
++        // check prefix
++        for (String prefix : conf.getPrefixesNotPermitted()) {
++            if (user.getUsername().startsWith(prefix)) {
++                throw new AccountPolicyException("Prefix not permitted");
++            }
++        }
++
++        // check suffix
++        for (String suffix : conf.getSuffixesNotPermitted()) {
++            if (user.getUsername().endsWith(suffix)) {
++                throw new AccountPolicyException("Suffix not permitted");
++            }
++        }
++    }
++
++}


[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

Posted by il...@apache.org.
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">


[03/12] syncope git commit: Upgrading highlightjs

Posted by il...@apache.org.
Upgrading highlightjs


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

Branch: refs/heads/master
Commit: a4400ffee35418df3d87603c73fda28474f1ad12
Parents: 2cf7619
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Aug 18 14:56:07 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Aug 18 14:56:07 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/a4400ffe/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 6330b9e..d50da6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -378,7 +378,7 @@ under the License.
     <bootstrap-select.version>1.6.3</bootstrap-select.version>
     <font-awesome.version>4.4.0</font-awesome.version>
     <ionicons.version>2.0.1</ionicons.version>
-    <highlightjs.version>8.4-4</highlightjs.version>
+    <highlightjs.version>8.7</highlightjs.version>
     <codemirror.version>5.5</codemirror.version>
     <jsplumb.version>1.7.5</jsplumb.version>
     


[07/12] syncope git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
index 0000000,0000000..8eaad0e
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
@@@ -1,0 -1,0 +1,218 @@@
++/*
++ * 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.dao;
++
++import java.util.List;
++import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.misc.policy.PasswordPolicyException;
++import org.apache.syncope.core.misc.policy.PolicyPattern;
++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.PlainAttr;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@PasswordRuleConfClass(DefaultPasswordRuleConf.class)
++public class DefaultPasswordRule implements PasswordRule {
++
++    private DefaultPasswordRuleConf conf;
++
++    @Override
++    public void setConf(final PasswordRuleConf conf) {
++        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()) {
++            PlainAttr<?> attr = user.getPlainAttr(schema);
++            if (attr != null) {
++                List<String> values = attr.getValuesAsStrings();
++                if (values != null && !values.isEmpty()) {
++                    conf.getWordsNotPermitted().add(values.get(0));
++                }
++            }
++        }
++
++        String clearPassword = user.getClearPassword();
++        String password = user.getPassword();
++
++        if (password != null && clearPassword != null) {
++            // check length
++            if (conf.getMinLength() > 0 && conf.getMinLength() > clearPassword.length()) {
++                throw new PasswordPolicyException("Password too short");
++            }
++
++            if (conf.getMaxLength() > 0 && conf.getMaxLength() < clearPassword.length()) {
++                throw new PasswordPolicyException("Password too long");
++            }
++
++            // check words not permitted
++            for (String word : conf.getWordsNotPermitted()) {
++                if (clearPassword.contains(word)) {
++                    throw new PasswordPolicyException("Used word(s) not permitted");
++                }
++            }
++
++            // check digits occurrence
++            if (conf.isDigitRequired() && !checkDigit(clearPassword)) {
++                throw new PasswordPolicyException("Password must contain digit(s)");
++            }
++
++            // check lowercase alphabetic characters occurrence
++            if (conf.isLowercaseRequired() && !checkLowercase(clearPassword)) {
++                throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
++            }
++
++            // check uppercase alphabetic characters occurrence
++            if (conf.isUppercaseRequired() && !checkUppercase(clearPassword)) {
++                throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
++            }
++
++            // check prefix
++            for (String prefix : conf.getPrefixesNotPermitted()) {
++                if (clearPassword.startsWith(prefix)) {
++                    throw new PasswordPolicyException("Prefix not permitted");
++                }
++            }
++
++            // check suffix
++            for (String suffix : conf.getSuffixesNotPermitted()) {
++                if (clearPassword.endsWith(suffix)) {
++                    throw new PasswordPolicyException("Suffix not permitted");
++                }
++            }
++
++            // check digit first occurrence
++            if (conf.isMustStartWithDigit() && !checkFirstDigit(clearPassword)) {
++                throw new PasswordPolicyException("Password must start with a digit");
++            }
++
++            if (conf.isMustntStartWithDigit() && checkFirstDigit(clearPassword)) {
++                throw new PasswordPolicyException("Password mustn't start with a digit");
++            }
++
++            // check digit last occurrence
++            if (conf.isMustEndWithDigit() && !checkLastDigit(clearPassword)) {
++                throw new PasswordPolicyException("Password must end with a digit");
++            }
++
++            if (conf.isMustntEndWithDigit() && checkLastDigit(clearPassword)) {
++                throw new PasswordPolicyException("Password mustn't end with a digit");
++            }
++
++            // check alphanumeric characters occurence
++            if (conf.isAlphanumericRequired() && !checkAlphanumeric(clearPassword)) {
++                throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
++            }
++
++            // check non alphanumeric characters occurence
++            if (conf.isNonAlphanumericRequired() && !checkNonAlphanumeric(clearPassword)) {
++                throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
++            }
++
++            // check alphanumeric character first occurrence
++            if (conf.isMustStartWithAlpha() && !checkFirstAlphanumeric(clearPassword)) {
++                throw new PasswordPolicyException("Password must start with an alphanumeric character");
++            }
++
++            if (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)) {
++                throw new PasswordPolicyException("Password must end with an alphanumeric character");
++            }
++
++            if (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)) {
++                throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
++            }
++
++            if (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)) {
++                throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
++            }
++
++            if (conf.isMustntEndWithNonAlpha() && checkLastNonAlphanumeric(clearPassword)) {
++                throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
++            }
++        }
++    }
++
++    private boolean checkDigit(final String str) {
++        return PolicyPattern.DIGIT.matcher(str).matches();
++    }
++
++    private boolean checkLowercase(final String str) {
++        return PolicyPattern.ALPHA_LOWERCASE.matcher(str).matches();
++    }
++
++    private boolean checkUppercase(final String str) {
++        return PolicyPattern.ALPHA_UPPERCASE.matcher(str).matches();
++    }
++
++    private boolean checkFirstDigit(final String str) {
++        return PolicyPattern.FIRST_DIGIT.matcher(str).matches();
++    }
++
++    private boolean checkLastDigit(final String str) {
++        return PolicyPattern.LAST_DIGIT.matcher(str).matches();
++    }
++
++    private boolean checkAlphanumeric(final String str) {
++        return PolicyPattern.ALPHANUMERIC.matcher(str).matches();
++    }
++
++    private boolean checkFirstAlphanumeric(final String str) {
++        return PolicyPattern.FIRST_ALPHANUMERIC.matcher(str).matches();
++    }
++
++    private boolean checkLastAlphanumeric(final String str) {
++        return PolicyPattern.LAST_ALPHANUMERIC.matcher(str).matches();
++    }
++
++    private boolean checkNonAlphanumeric(final String str) {
++        return PolicyPattern.NON_ALPHANUMERIC.matcher(str).matches();
++    }
++
++    private boolean checkFirstNonAlphanumeric(final String str) {
++        return PolicyPattern.FIRST_NON_ALPHANUMERIC.matcher(str).matches();
++    }
++
++    private boolean checkLastNonAlphanumeric(final String str) {
++        return PolicyPattern.LAST_NON_ALPHANUMERIC.matcher(str).matches();
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
index 0000000,0000000..843bbcd
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
@@@ -1,0 -1,0 +1,67 @@@
++/*
++ * 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.policy;
++
++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.validation.constraints.NotNull;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
++public abstract class AbstractPolicy extends AbstractEntity<Long> implements Policy {
++
++    private static final long serialVersionUID = -5844833125843247458L;
++
++    @Id
++    private Long id;
++
++    @NotNull
++    private String description;
++
++    @NotNull
++    @Enumerated(EnumType.STRING)
++    protected PolicyType type;
++
++    @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/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
index 0000000,0000000..87aa04f
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
@@@ -1,0 -1,0 +1,160 @@@
++/*
++ * 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.policy;
++
++import java.util.ArrayList;
++import java.util.HashSet;
++import java.util.List;
++import java.util.Set;
++import javax.persistence.Basic;
++import javax.persistence.CascadeType;
++import javax.persistence.Entity;
++import javax.persistence.FetchType;
++import javax.persistence.JoinColumn;
++import javax.persistence.JoinTable;
++import javax.persistence.ManyToMany;
++import javax.persistence.OneToMany;
++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;
++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.jpa.entity.resource.JPAExternalResource;
++
++@Entity
++@Table(name = JPAAccountPolicy.TABLE)
++public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
++
++    private static final long serialVersionUID = -2767606675667839060L;
++
++    public static final String TABLE = "AccountPolicy";
++
++    @Basic
++    @Min(0)
++    @Max(1)
++    private Integer propagateSuspension;
++
++    private int maxAuthenticationAttempts;
++
++    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "accountPolicy")
++    private List<JPAAccountRuleConfInstance> ruleConfs;
++
++    /**
++     * 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 boolean isPropagateSuspension() {
++        return isBooleanAsInteger(propagateSuspension);
++    }
++
++    @Override
++    public void setPropagateSuspension(final boolean propagateSuspension) {
++        this.propagateSuspension = getBooleanAsInteger(propagateSuspension);
++    }
++
++    @Override
++    public int getMaxAuthenticationAttempts() {
++        return maxAuthenticationAttempts;
++    }
++
++    @Override
++    public void setMaxAuthenticationAttempts(final int maxAuthenticationAttempts) {
++        this.maxAuthenticationAttempts = maxAuthenticationAttempts;
++    }
++
++    @Override
++    public boolean add(final AccountRuleConf accountRuleConf) {
++        if (accountRuleConf == null) {
++            return false;
++        }
++
++        JPAAccountRuleConfInstance instance = new JPAAccountRuleConfInstance();
++        instance.setAccountPolicy(this);
++        instance.setInstance(accountRuleConf);
++
++        return ruleConfs.add(instance);
++    }
++
++    @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());
++            }
++        });
++    }
++
++    @Override
++    public List<AccountRuleConf> getRuleConfs() {
++        return CollectionUtils.collect(ruleConfs, new Transformer<JPAAccountRuleConfInstance, AccountRuleConf>() {
++
++            @Override
++            public AccountRuleConf transform(final JPAAccountRuleConfInstance input) {
++                return input.getInstance();
++            }
++        }, new ArrayList<AccountRuleConf>());
++    }
++
++    @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/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
index 0000000,0000000..782e6b4
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
@@@ -1,0 -1,0 +1,73 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.persistence.jpa.entity.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Id;
++import javax.persistence.Lob;
++import javax.persistence.ManyToOne;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Table(name = JPAAccountRuleConfInstance.TABLE)
++public class JPAAccountRuleConfInstance extends AbstractEntity<Long> {
++
++    private static final long serialVersionUID = -2436055132955674610L;
++
++    public static final String TABLE = "AccountRuleConfInstance";
++
++    @Id
++    private Long id;
++
++    @Lob
++    private String serializedInstance;
++
++    @ManyToOne
++    private JPAAccountPolicy accountPolicy;
++
++    @Override
++    public Long getKey() {
++        return id;
++    }
++
++    public AccountPolicy getAccountPolicy() {
++        return accountPolicy;
++    }
++
++    public void setAccountPolicy(final AccountPolicy report) {
++        checkType(report, JPAAccountPolicy.class);
++        this.accountPolicy = (JPAAccountPolicy) report;
++    }
++
++    public AccountRuleConf getInstance() {
++        return serializedInstance == null
++                ? null
++                : POJOHelper.deserialize(serializedInstance, AccountRuleConf.class);
++    }
++
++    public void setInstance(final AccountRuleConf instance) {
++        this.serializedInstance = instance == null
++                ? null
++                : POJOHelper.serialize(instance);
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
index 0000000,0000000..1491c25
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
@@@ -1,0 -1,0 +1,115 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.persistence.jpa.entity.policy;
++
++import java.util.ArrayList;
++import java.util.List;
++import javax.persistence.Basic;
++import javax.persistence.CascadeType;
++import javax.persistence.Entity;
++import javax.persistence.FetchType;
++import javax.persistence.OneToMany;
++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;
++import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
++
++@Entity
++@Table(name = JPAPasswordPolicy.TABLE)
++public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy {
++
++    private static final long serialVersionUID = 9138550910385232849L;
++
++    public static final String TABLE = "PasswordPolicy";
++
++    @Basic
++    @Min(0)
++    @Max(1)
++    private Integer allowNullPassword;
++
++    private int historyLength;
++
++    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "passwordPolicy")
++    private List<JPAPasswordRuleConfInstance> ruleConfs;
++
++    public JPAPasswordPolicy() {
++        super();
++        this.type = PolicyType.PASSWORD;
++    }
++
++    @Override
++    public boolean isAllowNullPassword() {
++        return isBooleanAsInteger(allowNullPassword);
++    }
++
++    @Override
++    public void setAllowNullPassword(final boolean allowNullPassword) {
++        this.allowNullPassword = getBooleanAsInteger(allowNullPassword);
++    }
++
++    @Override
++    public int getHistoryLength() {
++        return historyLength;
++    }
++
++    @Override
++    public void setHistoryLength(final int historyLength) {
++        this.historyLength = historyLength;
++    }
++
++    @Override
++    public boolean add(final PasswordRuleConf passwordRuleConf) {
++        if (passwordRuleConf == null) {
++            return false;
++        }
++
++        JPAPasswordRuleConfInstance instance = new JPAPasswordRuleConfInstance();
++        instance.setPasswordPolicy(this);
++        instance.setInstance(passwordRuleConf);
++
++        return ruleConfs.add(instance);
++    }
++
++    @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());
++            }
++        });
++    }
++
++    @Override
++    public List<PasswordRuleConf> getRuleConfs() {
++        return CollectionUtils.collect(ruleConfs, new Transformer<JPAPasswordRuleConfInstance, PasswordRuleConf>() {
++
++            @Override
++            public PasswordRuleConf transform(final JPAPasswordRuleConfInstance input) {
++                return input.getInstance();
++            }
++        }, new ArrayList<PasswordRuleConf>());
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
index 0000000,0000000..4b39dc8
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
@@@ -1,0 -1,0 +1,73 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.core.persistence.jpa.entity.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Id;
++import javax.persistence.Lob;
++import javax.persistence.ManyToOne;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Table(name = JPAPasswordRuleConfInstance.TABLE)
++public class JPAPasswordRuleConfInstance extends AbstractEntity<Long> {
++
++    private static final long serialVersionUID = -2436055132955674610L;
++
++    public static final String TABLE = "PasswordRuleConfInstance";
++
++    @Id
++    private Long id;
++
++    @Lob
++    private String serializedInstance;
++
++    @ManyToOne
++    private JPAPasswordPolicy passwordPolicy;
++
++    @Override
++    public Long getKey() {
++        return id;
++    }
++
++    public PasswordPolicy getPasswordPolicy() {
++        return passwordPolicy;
++    }
++
++    public void setPasswordPolicy(final PasswordPolicy report) {
++        checkType(report, JPAPasswordPolicy.class);
++        this.passwordPolicy = (JPAPasswordPolicy) report;
++    }
++
++    public PasswordRuleConf getInstance() {
++        return serializedInstance == null
++                ? null
++                : POJOHelper.deserialize(serializedInstance, PasswordRuleConf.class);
++    }
++
++    public void setInstance(final PasswordRuleConf instance) {
++        this.serializedInstance = instance == null
++                ? null
++                : POJOHelper.serialize(instance);
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
index 0000000,0000000..3bc0009
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
@@@ -1,0 -1,0 +1,55 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Lob;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.common.lib.policy.PushPolicySpec;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
++
++@Entity
++@Table(name = JPAPushPolicy.TABLE)
++public class JPAPushPolicy extends AbstractPolicy implements PushPolicy {
++
++    private static final long serialVersionUID = -5875589156893921113L;
++
++    public static final String TABLE = "PushPolicy";
++
++    @Lob
++    private String specification;
++
++    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/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
index 0000000,0000000..913ee54
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
@@@ -1,0 -1,0 +1,54 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Lob;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.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.policy.SyncPolicy;
++
++@Entity
++@Table(name = JPASyncPolicy.TABLE)
++public class JPASyncPolicy extends AbstractPolicy implements SyncPolicy {
++
++    private static final long serialVersionUID = -6090413855809521279L;
++
++    public static final String TABLE = "SyncPolicy";
++
++    @Lob
++    private String specification;
++
++    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/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
index 0000000,0000000..36c52a3
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
@@@ -1,0 -1,0 +1,96 @@@
++/*
++ * 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 = AbstractTask.TABLE)
++@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
++@DiscriminatorColumn(name = "DTYPE")
++public abstract class AbstractTask 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 AbstractTask() {
++        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/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
index 0000000,0000000..2b67f37
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
@@@ -1,0 -1,0 +1,48 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.fit.core.reference;
++
++import 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.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@AccountRuleConfClass(TestAccountRuleConf.class)
++public class TestAccountRule implements AccountRule {
++
++    private TestAccountRuleConf conf;
++
++    @Transactional(readOnly = true)
++    @Override
++    public void enforce(final AccountRuleConf conf, final User user) {
++        if (conf instanceof TestAccountRuleConf) {
++            this.conf = TestAccountRuleConf.class.cast(conf);
++        } else {
++            throw new IllegalArgumentException(
++                    AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
++        }
++
++        if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
++            throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
++        }
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
index 0000000,0000000..8903058
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
@@@ -1,0 -1,0 +1,36 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.fit.core.reference;
++
++import org.apache.syncope.common.lib.AbstractBaseBean;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++
++public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
++
++    private static final long serialVersionUID = -1803947511928491978L;
++
++    @Override
++    public String getName() {
++        return getClass().getName();
++    }
++
++    public String getMustContainSubstring() {
++        return "YYY";
++    }
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
index 0000000,0000000..2b67f37
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
@@@ -1,0 -1,0 +1,48 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.fit.core.reference;
++
++import 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.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@AccountRuleConfClass(TestAccountRuleConf.class)
++public class TestAccountRule implements AccountRule {
++
++    private TestAccountRuleConf conf;
++
++    @Transactional(readOnly = true)
++    @Override
++    public void enforce(final AccountRuleConf conf, final User user) {
++        if (conf instanceof TestAccountRuleConf) {
++            this.conf = TestAccountRuleConf.class.cast(conf);
++        } else {
++            throw new IllegalArgumentException(
++                    AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
++        }
++
++        if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
++            throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
++        }
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
index 0000000,0000000..8903058
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
@@@ -1,0 -1,0 +1,36 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements.  See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership.  The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied.  See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ */
++package org.apache.syncope.fit.core.reference;
++
++import org.apache.syncope.common.lib.AbstractBaseBean;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++
++public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
++
++    private static final long serialVersionUID = -1803947511928491978L;
++
++    @Override
++    public String getName() {
++        return getClass().getName();
++    }
++
++    public String getMustContainSubstring() {
++        return "YYY";
++    }
++}


[04/12] syncope git commit: Some small cleanings

Posted by il...@apache.org.
Some small cleanings


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

Branch: refs/heads/master
Commit: 56568a43c8cd56393bd3a1d58d3e307595c80de4
Parents: a4400ff
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Aug 18 16:54:31 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Aug 18 16:54:31 2015 +0200

----------------------------------------------------------------------
 .../common/lib/types/AbstractPolicySpec.java    |  2 +-
 .../common/lib/types/EntityViolationType.java   |  3 ---
 .../syncope/common/lib/types/PolicySpec.java    | 25 --------------------
 .../common/lib/types/PushPolicySpec.java        |  2 +-
 .../common/lib/types/SyncPolicySpec.java        |  2 +-
 .../core/logic/report/ReportJobDelegate.java    |  2 +-
 .../core/misc/policy/PolicyEvaluator.java       |  4 ++--
 .../core/persistence/api/entity/Report.java     | 15 ++++++------
 .../persistence/jpa/dao/JPAReportExecDAO.java   |  2 +-
 .../core/persistence/jpa/entity/JPAReport.java  |  8 +++----
 .../core/persistence/jpa/inner/ReportTest.java  |  4 ++--
 .../core/persistence/jpa/outer/ReportTest.java  |  2 +-
 .../java/data/ReportDataBinderImpl.java         |  4 ++--
 13 files changed, 24 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
index 33a0c62..e951419 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AbstractPolicySpec.java
@@ -30,7 +30,7 @@ import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
 @XmlType
-public abstract class AbstractPolicySpec implements PolicySpec {
+public abstract class AbstractPolicySpec {
 
     private static final long serialVersionUID = -6210646284287392063L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index 6e05a52..a97f510 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -24,7 +24,6 @@ import javax.xml.bind.annotation.XmlEnum;
 public enum EntityViolationType {
 
     Standard(""),
-    InvalidAccountPolicy("org.apache.syncope.core.persistence.validation.accountpolicy"),
     InvalidAnyType("org.apache.syncope.core.persistence.validation.anytype"),
     InvalidConnInstanceLocation("org.apache.syncope.core.persistence.validation.conninstance.location"),
     InvalidConnPoolConf("org.apache.syncope.core.persistence.validation.conninstance.poolConf"),
@@ -32,7 +31,6 @@ public enum EntityViolationType {
     InvalidName("org.apache.syncope.core.persistence.validation.name"),
     InvalidNotification("org.apache.syncope.core.persistence.validation.notification"),
     InvalidPassword("org.apache.syncope.core.persistence.validation.user.password"),
-    InvalidPasswordPolicy("org.apache.syncope.core.persistence.validation.passwordpolicy"),
     InvalidPolicy("org.apache.syncope.core.persistence.validation.policy"),
     InvalidPropagationTask("org.apache.syncope.core.persistence.validation.propagationtask"),
     InvalidRealm("org.apache.syncope.core.persistence.validation.realm"),
@@ -44,7 +42,6 @@ public enum EntityViolationType {
     InvalidSchemaMultivalueUnique("org.apache.syncope.core.persistence.validation.schema.multivalueUnique"),
     InvalidSchedTask("org.apache.syncope.core.persistence.validation.schedtask"),
     InvalidSyncTask("org.apache.syncope.core.persistence.validation.synctask"),
-    InvalidSyncPolicy("org.apache.syncope.core.persistence.validation.syncpolicy"),
     InvalidPlainSchema("org.apache.syncope.core.persistence.validation.attrvalue.plainSchema"),
     InvalidDerSchema("org.apache.syncope.core.persistence.validation.attrvalue.derSchema"),
     InvalidVirSchema("org.apache.syncope.core.persistence.validation.attrvalue.virSchema"),

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicySpec.java
deleted file mode 100644
index 7de0e48..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PolicySpec.java
+++ /dev/null
@@ -1,25 +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.common.lib.types;
-
-import java.io.Serializable;
-
-public interface PolicySpec extends Serializable {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
index d7a5640..0bbea85 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.types;
 import javax.xml.bind.annotation.XmlType;
 
 @XmlType
-public class PushPolicySpec implements PolicySpec {
+public class PushPolicySpec {
 
     private static final long serialVersionUID = 3641030189482617497L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
index 5a3d309..7bdaea0 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/SyncPolicySpec.java
@@ -27,7 +27,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlType
-public class SyncPolicySpec implements PolicySpec {
+public class SyncPolicySpec {
 
     private static final long serialVersionUID = -3144027171719498127L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
index 9920c1f..f7a8def 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java
@@ -87,7 +87,7 @@ public class ReportJobDelegate {
         execution.setReport(report);
         execution = reportExecDAO.save(execution);
 
-        report.addExec(execution);
+        report.add(execution);
         report = reportDAO.save(report);
 
         // 2. define a SAX handler for generating result as XML

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
index f7d946c..48cc981 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.misc.policy;
 
 import java.util.List;
+import org.apache.syncope.common.lib.types.AbstractPolicySpec;
 import org.apache.syncope.common.lib.types.AccountPolicySpec;
 import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.PolicySpec;
 import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
@@ -39,7 +39,7 @@ public class PolicyEvaluator {
     private static final Logger LOG = LoggerFactory.getLogger(PolicyEvaluator.class);
 
     @SuppressWarnings("unchecked")
-    public <T extends PolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) {
+    public <T extends AbstractPolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) {
         T result;
         switch (policy.getType()) {
             case PASSWORD:

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
index a2605e7..618e612 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Report.java
@@ -25,21 +25,22 @@ public interface Report extends Entity<Long> {
 
     String getName();
 
-    boolean addExec(ReportExec exec);
+    void setName(String name);
 
-    boolean addReportletConf(ReportletConf reportletConf);
+    boolean add(ReportExec exec);
 
-    String getCronExpression();
+    boolean remove(ReportExec exec);
 
     List<? extends ReportExec> getExecs();
 
-    List<? extends ReportletConf> getReportletConfs();
+    boolean add(ReportletConf reportletConf);
 
-    boolean removeExec(ReportExec exec);
+    boolean remove(ReportletConf reportletConf);
 
-    boolean removeReportletConf(ReportletConf reportletConf);
+    List<? extends ReportletConf> getReportletConfs();
+
+    String getCronExpression();
 
     void setCronExpression(String cronExpression);
 
-    void setName(String name);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
index cf9e781..35b7556 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java
@@ -91,7 +91,7 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements R
     @Override
     public void delete(final ReportExec execution) {
         if (execution.getReport() != null) {
-            execution.getReport().removeExec(execution);
+            execution.getReport().remove(execution);
         }
 
         entityManager().remove(execution);

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/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 544868f..15c33ea 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
@@ -82,13 +82,13 @@ public class JPAReport extends AbstractEntity<Long> implements Report {
     }
 
     @Override
-    public boolean addExec(final ReportExec exec) {
+    public boolean add(final ReportExec exec) {
         checkType(exec, JPAReportExec.class);
         return exec != null && !executions.contains((JPAReportExec) exec) && executions.add((JPAReportExec) exec);
     }
 
     @Override
-    public boolean removeExec(final ReportExec exec) {
+    public boolean remove(final ReportExec exec) {
         checkType(exec, JPAReportExec.class);
         return exec != null && executions.remove((JPAReportExec) exec);
     }
@@ -99,7 +99,7 @@ public class JPAReport extends AbstractEntity<Long> implements Report {
     }
 
     @Override
-    public boolean addReportletConf(final ReportletConf reportletConf) {
+    public boolean add(final ReportletConf reportletConf) {
         if (reportletConf == null) {
             return false;
         }
@@ -112,7 +112,7 @@ public class JPAReport extends AbstractEntity<Long> implements Report {
     }
 
     @Override
-    public boolean removeReportletConf(final ReportletConf reportletConf) {
+    public boolean remove(final ReportletConf reportletConf) {
         return CollectionUtils.filter(reportletConfs, new Predicate<JPAReportletConfInstance>() {
 
             @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
index 1144981..536d74f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
@@ -59,8 +59,8 @@ public class ReportTest extends AbstractTest {
 
         Report report = entityFactory.newEntity(Report.class);
         report.setName("new report");
-        report.addReportletConf(new UserReportletConf("first"));
-        report.addReportletConf(new UserReportletConf("second"));
+        report.add(new UserReportletConf("first"));
+        report.add(new UserReportletConf("second"));
 
         report = reportDAO.save(report);
         assertNotNull(report);

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
index f143fd8..36f275c 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ReportTest.java
@@ -80,7 +80,7 @@ public class ReportTest extends AbstractTest {
         reportExec.setEndDate(new Date());
         reportExec.setStatus(ReportExecStatus.SUCCESS);
 
-        report.addExec(reportExec);
+        report.add(reportExec);
 
         reportExec = reportExecDAO.save(reportExec);
         assertNotNull(reportExec);

http://git-wip-us.apache.org/repos/asf/syncope/blob/56568a43/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 e98bc7d..6a40803 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
@@ -68,12 +68,12 @@ public class ReportDataBinderImpl implements ReportDataBinder {
             toRemove.add(conf);
         }
         for (ReportletConf conf : toRemove) {
-            report.removeReportletConf(conf);
+            report.remove(conf);
         }
 
         // 2. take all reportlet confs from reportTO
         for (ReportletConf conf : reportTO.getReportletConfs()) {
-            report.addReportletConf(conf);
+            report.add(conf);
         }
     }
 


[06/12] syncope git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope

Posted by il...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/syncope


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

Branch: refs/heads/master
Commit: 8e219725d643ac5475257b85fc821de9521c64f0
Parents: 8502698 0e5694a
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Aug 19 16:17:59 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Aug 19 16:17:59 2015 +0200

----------------------------------------------------------------------
 .../syncope/client/console/pages/BasePage.java  |   5 +-
 .../console/panels/NotificationPanel.java       |   2 +-
 .../client/console/panels/ResourceModal.java    |   1 -
 .../client/console/topology/Topology.java       |   1 +
 .../console/topology/TopologyNodePanel.java     |  10 +-
 .../markup/html/form/ActionLinksPanel.java      | 192 ++++++++++++++++++-
 .../META-INF/resources/css/syncopeConsole.css   |   4 +
 .../syncope/client/console/pages/BasePage.html  |   2 +-
 8 files changed, 204 insertions(+), 13 deletions(-)
----------------------------------------------------------------------



[02/12] syncope git commit: [SYNCOPE-685] Pre: more cleanup

Posted by il...@apache.org.
[SYNCOPE-685] Pre: more cleanup


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

Branch: refs/heads/master
Commit: 2cf761973049f874380d5ac054b4daf95360fc57
Parents: fc91e51
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Aug 17 17:56:15 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Aug 17 17:56:15 2015 +0200

----------------------------------------------------------------------
 .../common/lib/types/PushPolicySpec.java        | 28 ++++++++++
 .../syncope/core/misc/ConnObjectUtils.java      |  8 +--
 .../core/misc/policy/PolicyEvaluator.java       |  6 +-
 .../core/misc/security/PasswordGenerator.java   |  8 +--
 .../persistence/api/entity/AccountPolicy.java   |  5 ++
 .../persistence/api/entity/PasswordPolicy.java  |  8 ++-
 .../core/persistence/api/entity/Policy.java     |  5 --
 .../core/persistence/api/entity/PushPolicy.java |  7 ++-
 .../core/persistence/api/entity/SyncPolicy.java |  8 ++-
 .../jpa/entity/JPAAccountPolicy.java            | 12 ++++
 .../jpa/entity/JPAPasswordPolicy.java           | 12 ++++
 .../core/persistence/jpa/entity/JPAPolicy.java  | 16 +-----
 .../persistence/jpa/entity/JPAPushPolicy.java   | 16 ++++--
 .../persistence/jpa/entity/JPASyncPolicy.java   | 12 ++++
 .../jpa/validation/entity/PolicyCheck.java      | 41 --------------
 .../jpa/validation/entity/PolicyValidator.java  | 59 --------------------
 .../core/persistence/jpa/inner/PolicyTest.java  | 31 +++-------
 .../java/data/PolicyDataBinderImpl.java         | 18 +++---
 .../provisioning/java/sync/SyncJobDelegate.java |  2 +-
 .../core/provisioning/java/sync/SyncUtils.java  |  2 +-
 20 files changed, 132 insertions(+), 172 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
new file mode 100644
index 0000000..d7a5640
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PushPolicySpec.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.types;
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class PushPolicySpec implements PolicySpec {
+
+    private static final long serialVersionUID = 3641030189482617497L;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
index 6257d59..de1bcfb 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
@@ -123,9 +123,9 @@ public class ConnObjectUtils {
             if (realm != null) {
                 for (Realm ancestor : realmDAO.findAncestors(realm)) {
                     if (ancestor.getPasswordPolicy() != null
-                            && ancestor.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
+                            && ancestor.getPasswordPolicy().getSpecification() != null) {
 
-                        ppSpecs.add(ancestor.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
+                        ppSpecs.add(ancestor.getPasswordPolicy().getSpecification());
                     }
                 }
             }
@@ -133,9 +133,9 @@ public class ConnObjectUtils {
             for (String resName : userTO.getResources()) {
                 ExternalResource resource = resourceDAO.find(resName);
                 if (resource != null && resource.getPasswordPolicy() != null
-                        && resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
+                        && resource.getPasswordPolicy().getSpecification() != null) {
 
-                    ppSpecs.add(resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
+                    ppSpecs.add(resource.getPasswordPolicy().getSpecification());
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
index 425568d..f7d946c 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PolicyEvaluator.java
@@ -22,7 +22,9 @@ import java.util.List;
 import org.apache.syncope.common.lib.types.AccountPolicySpec;
 import org.apache.syncope.common.lib.types.PasswordPolicySpec;
 import org.apache.syncope.common.lib.types.PolicySpec;
+import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -41,7 +43,7 @@ public class PolicyEvaluator {
         T result;
         switch (policy.getType()) {
             case PASSWORD:
-                PasswordPolicySpec ppSpec = policy.getSpecification(PasswordPolicySpec.class);
+                PasswordPolicySpec ppSpec = ((PasswordPolicy) policy).getSpecification();
                 PasswordPolicySpec evaluatedPPSpec = new PasswordPolicySpec();
 
                 BeanUtils.copyProperties(ppSpec, evaluatedPPSpec, new String[] { "schemasNotPermitted" });
@@ -71,7 +73,7 @@ public class PolicyEvaluator {
                 break;
 
             case ACCOUNT:
-                AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class);
+                AccountPolicySpec spec = ((AccountPolicy) policy).getSpecification();
                 AccountPolicySpec accountPolicy = new AccountPolicySpec();
 
                 BeanUtils.copyProperties(spec, accountPolicy, new String[] { "schemasNotPermitted" });

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
index 9514f27..d5e2e14 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/PasswordGenerator.java
@@ -71,17 +71,17 @@ public class PasswordGenerator {
 
         for (Realm ancestor : realmDAO.findAncestors(user.getRealm())) {
             if (ancestor.getPasswordPolicy() != null
-                    && ancestor.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
+                    && ancestor.getPasswordPolicy().getSpecification() != null) {
 
-                ppSpecs.add(ancestor.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
+                ppSpecs.add(ancestor.getPasswordPolicy().getSpecification());
             }
         }
 
         for (ExternalResource resource : userDAO.findAllResources(user)) {
             if (resource.getPasswordPolicy() != null
-                    && resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class) != null) {
+                    && resource.getPasswordPolicy().getSpecification() != null) {
 
-                ppSpecs.add(resource.getPasswordPolicy().getSpecification(PasswordPolicySpec.class));
+                ppSpecs.add(resource.getPasswordPolicy().getSpecification());
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
index bafc554..72f8cac 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccountPolicy.java
@@ -20,9 +20,14 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import java.util.Set;
+import org.apache.syncope.common.lib.types.AccountPolicySpec;
 
 public interface AccountPolicy extends Policy {
 
+    AccountPolicySpec getSpecification();
+
+    void setSpecification(AccountPolicySpec spec);
+    
     boolean add(ExternalResource resource);
 
     boolean remove(ExternalResource resource);

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
index 4981ff2..a4004ce 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PasswordPolicy.java
@@ -18,6 +18,12 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
+import org.apache.syncope.common.lib.types.PasswordPolicySpec;
+
 public interface PasswordPolicy extends Policy {
-    
+
+    PasswordPolicySpec getSpecification();
+
+    void setSpecification(PasswordPolicySpec spec);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Policy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Policy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Policy.java
index 5edca88..d02de0a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Policy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Policy.java
@@ -18,18 +18,13 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import org.apache.syncope.common.lib.types.PolicySpec;
 import org.apache.syncope.common.lib.types.PolicyType;
 
 public interface Policy extends Entity<Long> {
 
     String getDescription();
 
-    <T extends PolicySpec> T getSpecification(Class<T> reference);
-
     PolicyType getType();
 
     void setDescription(String description);
-
-    void setSpecification(PolicySpec policy);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
index 761525d..e1c37df 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PushPolicy.java
@@ -18,6 +18,11 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
+import org.apache.syncope.common.lib.types.PushPolicySpec;
+
 public interface PushPolicy extends Policy {
-    
+
+    PushPolicySpec getSpecification();
+
+    void setSpecification(PushPolicySpec spec);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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
index 3acb092..1e389d7 100644
--- 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
@@ -18,6 +18,12 @@
  */
 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/2cf76197/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
index 64475aa..844b49a 100644
--- 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
@@ -28,7 +28,9 @@ 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;
@@ -55,6 +57,16 @@ public class JPAAccountPolicy extends JPAPolicy implements AccountPolicy {
     }
 
     @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);

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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
index 51f55a5..8a755f4 100644
--- 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
@@ -20,7 +20,9 @@ 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
@@ -33,4 +35,14 @@ public class JPAPasswordPolicy extends JPAPolicy implements PasswordPolicy {
         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/2cf76197/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
index 3104c23..1dc5de6 100644
--- 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
@@ -28,17 +28,13 @@ import javax.persistence.InheritanceType;
 import javax.persistence.Lob;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.PolicySpec;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.entity.Policy;
-import org.apache.syncope.core.persistence.jpa.validation.entity.PolicyCheck;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
 
 @Entity
 @Table(name = JPAPolicy.TABLE)
 @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
 @DiscriminatorColumn(name = "DTYPE")
-@PolicyCheck
 public abstract class JPAPolicy extends AbstractEntity<Long> implements Policy {
 
     private static final long serialVersionUID = -5844833125843247458L;
@@ -56,7 +52,7 @@ public abstract class JPAPolicy extends AbstractEntity<Long> implements Policy {
     protected PolicyType type;
 
     @Lob
-    private String specification;
+    protected String specification;
 
     @Override
     public Long getKey() {
@@ -77,14 +73,4 @@ public abstract class JPAPolicy extends AbstractEntity<Long> implements Policy {
     public PolicyType getType() {
         return type;
     }
-
-    @Override
-    public <T extends PolicySpec> T getSpecification(final Class<T> reference) {
-        return POJOHelper.deserialize(specification, reference);
-    }
-
-    @Override
-    public void setSpecification(final PolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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
index f4be722..c3440b2 100644
--- 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
@@ -20,6 +20,8 @@ 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
@@ -28,12 +30,18 @@ public class JPAPushPolicy extends JPAPolicy implements PushPolicy {
     private static final long serialVersionUID = -5875589156893921113L;
 
     public JPAPushPolicy() {
-        this(false);
-    }
-
-    public JPAPushPolicy(final boolean global) {
         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/2cf76197/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
index 39b7565..e244223 100644
--- 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
@@ -20,7 +20,9 @@ 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
@@ -33,4 +35,14 @@ public class JPASyncPolicy extends JPAPolicy implements SyncPolicy {
         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/2cf76197/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyCheck.java
deleted file mode 100644
index 45873be..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyCheck.java
+++ /dev/null
@@ -1,41 +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.validation.entity;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-
-@Target({ ElementType.TYPE })
-@Retention(RetentionPolicy.RUNTIME)
-@Constraint(validatedBy = PolicyValidator.class)
-@Documented
-public @interface PolicyCheck {
-
-    String message() default "{org.apache.syncope.core.persistence.validation.policy}";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyValidator.java
deleted file mode 100644
index fd95c4c..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PolicyValidator.java
+++ /dev/null
@@ -1,59 +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.validation.entity;
-
-import javax.validation.ConstraintValidatorContext;
-import org.apache.syncope.common.lib.types.AccountPolicySpec;
-import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
-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;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
-
-public class PolicyValidator extends AbstractValidator<PolicyCheck, Policy> {
-
-    @Override
-    public boolean isValid(final Policy object, final ConstraintValidatorContext context) {
-        context.disableDefaultConstraintViolation();
-
-        EntityViolationType violationType =
-                object instanceof PasswordPolicy
-                && !(object.getSpecification(PasswordPolicySpec.class) instanceof PasswordPolicySpec)
-                        ? EntityViolationType.InvalidPasswordPolicy
-                        : object instanceof AccountPolicy
-                        && !(object.getSpecification(AccountPolicySpec.class) instanceof AccountPolicySpec)
-                                ? EntityViolationType.InvalidAccountPolicy
-                                : object instanceof SyncPolicy
-                                && !(object.getSpecification(SyncPolicySpec.class) instanceof SyncPolicySpec)
-                                        ? EntityViolationType.InvalidSyncPolicy
-                                        : null;
-
-        if (violationType != null) {
-            context.buildConstraintViolationWithTemplate(getTemplate(violationType,
-                    "Invalid policy specification")).addPropertyNode("specification").
-                    addConstraintViolation();
-
-            return false;
-        }
-
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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 603cd01..780d192 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
@@ -31,9 +31,9 @@ import org.apache.syncope.common.lib.types.PasswordPolicySpec;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.SyncPolicySpec;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
 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;
 import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
@@ -62,7 +62,7 @@ public class PolicyTest extends AbstractTest {
         SyncPolicy policy = policyDAO.find(3L);
         assertNotNull("findById did not work", policy);
 
-        SyncPolicySpec spec = policy.getSpecification(SyncPolicySpec.class);
+        SyncPolicySpec spec = policy.getSpecification();
         assertNotNull(spec);
 
         String rule = spec.getCorrelationRules().get(AnyTypeKind.USER.name());
@@ -81,19 +81,6 @@ public class PolicyTest extends AbstractTest {
         assertFalse(policies.isEmpty());
     }
 
-    @Test(expected = InvalidEntityException.class)
-    public void saveInvalidPolicy() {
-        PasswordPolicySpec passwordPolicy = new PasswordPolicySpec();
-        passwordPolicy.setMaxLength(8);
-        passwordPolicy.setMinLength(6);
-
-        SyncPolicy policy = entityFactory.newEntity(SyncPolicy.class);
-        policy.setSpecification(passwordPolicy);
-        policy.setDescription("sync policy");
-
-        policyDAO.save(policy);
-    }
-
     @Test
     public void create() {
         SyncPolicy policy = entityFactory.newEntity(SyncPolicy.class);
@@ -113,10 +100,10 @@ public class PolicyTest extends AbstractTest {
 
         assertNotNull(policy);
         assertEquals(PolicyType.SYNC, policy.getType());
-        assertEquals(syncURuleName, (policy.getSpecification(SyncPolicySpec.class)).
-                getCorrelationRules().get(anyTypeDAO.findUser().getKey()));
-        assertEquals(syncGRuleName, (policy.getSpecification(SyncPolicySpec.class)).
-                getCorrelationRules().get(anyTypeDAO.findGroup().getKey()));
+        assertEquals(syncURuleName,
+                policy.getSpecification().getCorrelationRules().get(anyTypeDAO.findUser().getKey()));
+        assertEquals(syncGRuleName,
+                policy.getSpecification().getCorrelationRules().get(anyTypeDAO.findGroup().getKey()));
     }
 
     @Test
@@ -125,7 +112,7 @@ public class PolicyTest extends AbstractTest {
         specification.setMaxLength(8);
         specification.setMinLength(6);
 
-        Policy policy = policyDAO.find(2L);
+        PasswordPolicy policy = policyDAO.find(2L);
         assertNotNull(policy);
         policy.setSpecification(specification);
 
@@ -133,8 +120,8 @@ public class PolicyTest extends AbstractTest {
 
         assertNotNull(policy);
         assertEquals(PolicyType.PASSWORD, policy.getType());
-        assertEquals((policy.getSpecification(PasswordPolicySpec.class)).getMaxLength(), 8);
-        assertEquals((policy.getSpecification(PasswordPolicySpec.class)).getMinLength(), 6);
+        assertEquals(policy.getSpecification().getMaxLength(), 8);
+        assertEquals(policy.getSpecification().getMinLength(), 6);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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 fa53bbd..7180b6c 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
@@ -24,10 +24,7 @@ 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.types.AccountPolicySpec;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.PasswordPolicySpec;
-import org.apache.syncope.common.lib.types.SyncPolicySpec;
 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;
@@ -59,24 +56,23 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
     @SuppressWarnings("unchecked")
     @Override
     public <T extends AbstractPolicyTO> T getPolicyTO(final Policy policy) {
-        final T policyTO;
-
+        T policyTO;
         switch (policy.getType()) {
             case PASSWORD:
                 policyTO = (T) new PasswordPolicyTO();
-                ((PasswordPolicyTO) policyTO).setSpecification(policy.getSpecification(PasswordPolicySpec.class));
+                ((PasswordPolicyTO) policyTO).setSpecification(((PasswordPolicy) policy).getSpecification());
                 break;
 
             case ACCOUNT:
                 policyTO = (T) new AccountPolicyTO();
-                ((AccountPolicyTO) policyTO).setSpecification(policy.getSpecification(AccountPolicySpec.class));
+                ((AccountPolicyTO) policyTO).setSpecification(((AccountPolicy) policy).getSpecification());
                 ((AccountPolicyTO) policyTO).getResources().addAll(((AccountPolicy) policy).getResourceNames());
                 break;
 
             case SYNC:
             default:
                 policyTO = (T) new SyncPolicyTO();
-                ((SyncPolicyTO) policyTO).setSpecification(policy.getSpecification(SyncPolicySpec.class));
+                ((SyncPolicyTO) policyTO).setSpecification(((SyncPolicy) policy).getSpecification());
         }
 
         policyTO.setKey(policy.getKey());
@@ -120,7 +116,7 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                 if (result == null) {
                     result = (T) entityFactory.newEntity(PasswordPolicy.class);
                 }
-                result.setSpecification(((PasswordPolicyTO) policyTO).getSpecification());
+                ((PasswordPolicy) result).setSpecification(((PasswordPolicyTO) policyTO).getSpecification());
                 break;
 
             case ACCOUNT:
@@ -131,7 +127,7 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                 if (result == null) {
                     result = (T) entityFactory.newEntity(AccountPolicy.class);
                 }
-                result.setSpecification(((AccountPolicyTO) policyTO).getSpecification());
+                ((AccountPolicy) result).setSpecification(((AccountPolicyTO) policyTO).getSpecification());
 
                 if (((AccountPolicy) result).getResources() != null
                         && !((AccountPolicy) result).getResources().isEmpty()) {
@@ -155,7 +151,7 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                 if (result == null) {
                     result = (T) entityFactory.newEntity(SyncPolicy.class);
                 }
-                result.setSpecification(((SyncPolicyTO) policyTO).getSpecification());
+                ((SyncPolicy) result).setSpecification(((SyncPolicyTO) policyTO).getSpecification());
         }
 
         result.setDescription(policyTO.getDescription());

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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 245a74a..2e70e80 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
@@ -210,7 +210,7 @@ public class SyncJobDelegate extends AbstractProvisioningJobDelegate<SyncTask> {
         if (task instanceof SyncTask) {
             syncPolicySpec = task.getResource().getSyncPolicy() == null
                     ? null
-                    : task.getResource().getSyncPolicy().getSpecification(SyncPolicySpec.class);
+                    : task.getResource().getSyncPolicy().getSpecification();
         } else {
             syncPolicySpec = null;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/2cf76197/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 7fd244b..4878362 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
@@ -279,7 +279,7 @@ public class SyncUtils {
 
         SyncPolicySpec syncPolicySpec = null;
         if (provision.getResource().getSyncPolicy() != null) {
-            syncPolicySpec = provision.getResource().getSyncPolicy().getSpecification(SyncPolicySpec.class);
+            syncPolicySpec = provision.getResource().getSyncPolicy().getSpecification();
         }
 
         SyncCorrelationRule syncRule = null;


[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

Posted by il...@apache.org.
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());
+        }
+
+    }
 }